使用SVT-HEVC编码器转码视频后音视频不同步的问题求助
看起来你遇到的核心问题是手动指定的帧计数与实际输入帧数不匹配,加上管道传输原生视频时缺少时间戳同步,导致SVT编码器生成的视频时间轴和原音频错位。我来拆解几个可能的原因和对应的解决办法:
1. 硬编码的frameCount是最大嫌疑
你手动设置了frameCount:=68808,但如果FFmpeg实际输出的帧数和这个数值不一致,SVT编码器就会要么提前停止编码(丢帧),要么补空帧,直接导致视频时长被压缩/拉长,和原音频不同步。
解决办法:
删掉SVT命令里的-n $frameCount参数,让SVT自动读取FFmpeg管道输出的所有帧,直到stdin结束。这样编码器会严格按照输入的帧数来编码,不会出现截断或补帧的问题。
2. FFmpeg输出原生视频时未强制对齐帧率
虽然你给SVT指定了fps-num和fps-denom,但FFmpeg在输出rawvideo时并没有明确的帧率约束——rawvideo本身不带时间戳,全靠编码器按指定帧率计算时间轴。如果FFmpeg输出的帧速率和你指定的24000/1001有偏差,哪怕是微小的误差,累计下来也会导致严重的音画不同步。
解决办法:
在FFmpeg的参数里加上-r 24000/1001,强制输出的原生视频严格按照23.98fps的速率输出,和SVT的参数完全匹配:
ffmpeg \ -hide_banner \ -i "$inputFile" \ -nostdin \ -r 24000/1001 \ # 新增:强制输出帧率与原视频一致 -f rawvideo \ -pix_fmt yuv420p \ -
3. 先确认原视频的真实帧数
你可以用FFmpeg命令快速获取原视频的准确帧数,验证一下你手动设置的68808是否正确:
ffmpeg -i "$inputFile" -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1
如果输出的数值和68808不一致,那手动指定帧计数就是问题的根源。
4. 更简单的替代方案:直接用FFmpeg封装的SVT-HEVC
现在FFmpeg已经支持直接调用SVT-HEVC编码器(需要编译时启用--enable-libsvt-hevc),这样可以完全避免管道传输的同步问题——FFmpeg会自动处理视频帧的时间戳、音频同步,操作也更简洁:
inputFile="testmovie.mp4" outputFile="testmovie_hevc.mp4" videoBitRate="2359296" ffmpeg -i "$inputFile" \ -c:v libsvt_hevc \ -rc 1 \ -b:v $videoBitRate \ -profile:v main \ -preset 0 \ # 对应SVT的encMode 0 -c:a copy \ # 直接复制原音频,避免重新编码 "$outputFile"
这个命令会直接生成包含音视频的MP4文件,音画同步问题基本可以解决。
关于你观察到的时间差的解释
原视频62.042秒的场景在转码后出现在59.542秒,说明转码后的视频时长被压缩了——本质是SVT编码的帧数比原视频少,或者按错误的帧率计算时间轴。比如如果原视频总帧数是X,23.98fps下时长是X/(24000/1001),但如果SVT只编码了Y帧(Y<X),时长就变成Y/(24000/1001),自然会比原音频快,导致不同步。
备注:内容来源于stack exchange,提问作者Cygon

