我使用一个分割器将我的MPEG2 Ts文件分割成一系列媒体片段,用于HTTP实时流
以及前一个分段之后的每个分段的开始时间(例如:段的开始时间:00:00,00:10:0,00:30,…)
(在Ubuntu中)
问题是:
当我使用ffmpeg对其中一个媒体片段进行转码时(例如800k bps到200k bps)
转码媒体段的开始时间将重置为0
例如:当我对第三段进行代码转换时,
分段的开始时间更改为:00:00,00:10,00:00,00:30,。。。
它导致我的播放器冻结一次播放转码的媒体片段
有什么解决方案可以在相同的开始时间对媒体文件进行转码吗?
我猜是ffmpeg重置了段的PTS(表示时间戳)
但我不知道如何修复…
这是我的ffmpeg命令(转码为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
==============================
救命!
感谢
h264编码段的直接分组时移
我最终链接了ffmpeg-libavformat/avcodec库进行读取,并直接移动数据包时间标头。偏移时间以秒为单位指定
unsigned int tsShift = offsetTime * 90000; // h264 defined sample rate is 90khz
并且进一步低于
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移位器源
以迂回的方式变换溪流
但是时间增量并不是我所说的
以下是
首先将原始ts文件转换为原始格式
ffmpeg-i original.ts original.avi
应用setpts过滤器并转换为编码格式(这取决于帧速率和所需的时移)
ffmpeg-i original.avi-filter:v"setpts=240+PTS"-sameq-vcodec libx264 shift.mp4
分段得到的移位.mp4
ffmpeg-i shift.mp4-qscale 0-bsf:v h264_mp4toannexb-vcodec copy-an-map 0-f segment_time 10-segment_format mpegts-y/温度-%03d.ts
创建的最后一个段文件,在我的例子中是temp-001.ts,是时移
问题是:这种方法感觉迟钝,因为它只移动了一些ts数据包的时间,它导致了10.5+的开始时间,而不是新的ts文件所需的10秒
最初的建议不起作用,如下所述
ffmpeg -itoffset prevTime (rest of ts gen args) | ffmpeg -ss prevTime -i _ -t 10 stuff.ts
prevTime是所有先前段的持续时间
第二个ffmpeg-ss调用使输出的mpegts文件相对于时间0(有时是1.4秒,可能是单个ts文件构造中的一个错误)
IMO-您有一个序列化的段列表,并希望将它们连接起来。
只要段的序列顺序通过连接得以保留,就可以了。
要在每个段条目上运行的进程,以便可以对其进行连接。。。。
getVideoRaw to its own file
getAudioRaw to its own file
当你把所有的分段都拆分成raw时,就这样做。。。。
concatenate video preserving serialized order so video segments remain correct order in videoConCatOUT.
concatenate the audio as above
然后将各个concatOUT文件复用到单个容器中。
这可以编写脚本,并且可以遵循Concat 上ffmpeg常见问题解答中的std.示例
参见此处的"3.14.4"部分
注意"tail"命令和关于从除第一段输入到concat过程之外的所有行中删除第1行的解释。。。
您应该在分段之前进行代码转换。当您对单个段进行代码转换时,它每次都会创建一个新的ts流,并且不会复制ts时间数据。
查看setpts
过滤器。这应该会让你对每件作品的PTS有足够的控制权。
有一个分段复用器https://ffmpeg.org/ffmpeg-formats.html#segment_002c-stream_005fsegment_002c-ssegment,它可能会帮助您实现目标。。。