使用FFmpeg拼接含/无音频MP4文件出现音视频不同步问题求助
FFmpeg拼接混合音视频文件时音轨不同步的解决方案
问题背景
我之前也碰到过一模一样的场景:有一批程序生成的20多个MP4文件,部分带音频、部分完全没有音频轨道。用常规的FFmpeg拼接脚本处理时,只要混入无音频的文件,最终输出的音轨就会严重不同步,还会抛出DTS时序错误,关键是没办法提前预判哪些文件是无音频的。
原脚本的问题
最开始我用的脚本和你几乎一样:
for f in $(ls *.mp4); do ffmpeg -i $f -c copy -bsf:v h264_mp4toannexb -f mpegts $f.ts done CONCAT=$(echo $(ls *.ts ) | sed -e "s/ /|/g") ffmpeg -analyzeduration 2147483647 -probesize 2147483647 -i "concat:$CONCAT" -c copy output.ts ffmpeg -analyzeduration 2147483647 -probesize 2147483647 -i output.ts -acodec copy -vcodec copy output.mp4
这个脚本的问题在于:无音频的MP4转成TS后,只有视频流;而带音频的TS同时有音视频流。FFmpeg拼接混合流结构的文件时,无法正确对齐时序,就会出现下面的报错,最终导致音轨不同步:
Input #0, mpegts, from 'concat:video0.mp4.ts|...|zzzz.mp4.ts': Duration: 00:00:05.02, start: 1.420222, bitrate: 63089 kb/s ... [mpegts @ 0x7f9c68800000] DTS 130180 < 573000 out of order <-- HERE ...
解决思路
核心就是让所有待拼接的TS文件拥有完全一致的流结构:给所有无音频的MP4文件添加一条虚拟的“哑音轨”,这样所有TS文件都同时包含视频和音频流,FFmpeg就能正常对齐时序了。
最终可用脚本
我调整后的脚本会自动检测每个MP4是否有音频流,针对性处理:
for f in $(ls *.mp4); do # 用ffprobe检测当前文件是否存在音频流,静默输出只看结果 TEST=$(ffprobe -i $f -show_streams -select_streams a -loglevel error) if [ "$TEST" ]; then # 有音频的文件,按原逻辑转成TS ffmpeg -i $f -c copy -bsf:v h264_mp4toannexb -f mpegts $f.ts else # 无音频的文件,先添加虚拟音频轨生成临时文件 ffmpeg -f lavfi -i anullsrc -i $f -shortest -c:v copy -c:a aac -map 0:a -map 1:v $f.a.ts # 再把临时文件转成符合拼接要求的TS ffmpeg -i $f.a.ts -c copy -bsf:v h264_mp4toannexb -f mpegts $f.ts # 清理临时文件 rm $f.a.ts fi done
之后你就可以用原来的拼接逻辑处理这些TS文件,不会再出现音轨不同步和DTS错误了。
内容的提问来源于stack exchange,提问作者CYRUS
相关产品推荐
相关产品推荐

