ffmpeghttp-live-streamingtranscode

ffmpeg transcoding reset the start time of file


I use a segmenter to segment my MPEG 2 Ts file into a series of media segment for HTTP live streaming

and each segment's start time following the previous one (ex:start time of segments: 00:00,00:10,00:20,00:30,...)

(In Ubuntu)

The Question is:

When I use ffmpeg to transcode one of the media segment (ex 800k bps to 200k bps)

the start time of transcoded media segment will be reset to 0

ex:As I transcode the third segement,

start time of segments changing to : 00:00,00:10,00:00,00:30,...

It cause my player freezing once play the transcoded media segment

Is there any solution to transcode media file with the same start time?

I guess it's the ffmpeg reset the PTS(presentation timestamp) of segment

But I don't know how to fix it...

here is my ffmpeg command (transcode to 250k bps)

============================

ffmpeg -y -i sample-03.ts -f mpegts -acodec libfaac -ar 48000 -ab 64k -vcodec libx264 -b 250k -flags +loop -cmp +chroma \
 -partitions +parti4x4+partp8x8+partb8x8 -subq 7 -trellis 0 -refs 0 -coder 0 -me_range 16 -keyint_min 25 \
 -sc_threshold 40 -i_qfactor 0.71 -maxrate 250k -bufsize 250k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 \
 -qmin 10 -qmax 51 -qdiff 4 -level 30 -aspect 320:240 -g 30 -async 2 sample.ts

============================

Help!

thanks


Solution

  • direct packet time shifting of h264 encoded segments

    I ended up linking with ffmpeg libavformat/avcodec libraries to read in, and directly shift the packet time headers. Offset time is specified in seconds

    unsigned int tsShift = offsetTime * 90000; // h264 defined sample rate is 90khz
    

    and further below

    do {
        double segmentTime;
        AVPacket packet;
    
        decodeDone = av_read_frame(pInFormatCtx, &packet);
        if (decodeDone < 0) {
            break;
        }
    
        if (av_dup_packet(&packet) < 0) {
            cout << "Could not duplicate packet" << endl;
            av_free_packet(&packet);
            break;
        }
    
        if (packet.stream_index == videoIndex && (packet.flags & AV_PKT_FLAG_KEY)) {
            segmentTime = (double)pVideoStream->pts.val * pVideoStream->time_base.num / pVideoStream->time_base.den;
        }
        else if (videoIndex < 0) {
            segmentTime = (double)pAudioStream->pts.val * pAudioStream->time_base.num / pAudioStream->time_base.den;
        }
        else {
            segmentTime = prevSegmentTime;
        }
    
        // cout << "before packet pts dts " << packet.pts << " " << packet.dts;
        packet.pts += tsShift;
        packet.dts += tsShift;
        // cout << " after packet pts dts " << packet.pts << " " << packet.dts << endl;
    
    
        ret = av_interleaved_write_frame(pOutFormatCtx, &packet);
        if (ret < 0) {
            cout << "Warning: Could not write frame of stream" << endl;
        }
        else if (ret > 0) {
            cout <<  "End of stream requested" << endl;
            av_free_packet(&packet);
            break;
        }
    
        av_free_packet(&packet);
    
    } while (!decodeDone);
    

    mpegts shifter source


    shifted streams in a round about way

    but the time delta is not precisely what I specify

    Here's how

    1. first convert the original ts file into a raw format

      ffmpeg -i original.ts original.avi

    2. apply a setpts filter and convert to encoded format (this will differ depending on frame rate and desired time shift)

      ffmpeg -i original.avi -filter:v 'setpts=240+PTS' -sameq -vcodec libx264 shift.mp4

    3. segment the resulting shift.mp4

      ffmpeg -i shift.mp4 -qscale 0 -bsf:v h264_mp4toannexb -vcodec copy -an -map 0 -f segment -segment_time 10 -segment_format mpegts -y ./temp-%03d.ts

    the last segment file created, temp-001.ts in my case, was time shifted

    the problem: this method feels obtuse for merely shifting some ts packet times, and it resulted in a start time of 10.5+ instead of precisely 10 seconds desired for the new ts file


    original suggestion did not work as described below

    ffmpeg -itoffset prevTime (rest of ts gen args) | ffmpeg -ss prevTime -i _ -t 10 stuff.ts
    

    prevTime is the duration of all previous segments

    no good as the second ffmpeg -ss call makes the output mpegts file relative to time 0 (or sometimes 1.4sec - perhaps a bug in the construction of single ts files)