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
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
but the time delta is not precisely what I specify
Here's how
first convert the original ts file into a raw format
ffmpeg -i original.ts original.avi
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
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)
IMO - you have a serialized list of segments and you want to concatenate them.
Thats it as long as the serial order of the segments is preserved thru the concatenation.
Process to run on each segment entry so that it can be concatentated....
getVideoRaw to its own file
getAudioRaw to its own file
When you have splitout to raw all of your segements do this....
concatenate video preserving serialized order so video segments remain correct order in videoConCatOUT.
concatenate the audio as above
then mux the respective concatOUT files into a single container.
This can be scripted and can follow the std. example in the ffmpeg FAQ on Concat
see '3.14.4' section here
Note the 'tail' cmd and the explain about dropping line no. 1 from all except the first segment input to the concat process...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With