Ffmpeg 拆分、转码和连接导致音频不同步

Ffmpeg 拆分、转码和连接导致音频不同步

我正在尝试将 VFR 或 CFR .webm 文件转换为 .mp4。为此,我拆分了原始视频,然后转码所有片段(更改 fps),然后连接生成的转码片段。为了测试结果,我从头到尾播放了 .mp4 视频,没有进行定位,但播放视频一段时间后,音频和视频开始慢慢不同步。当我在视频文件中进行定位时,这种情况并没有发生。我正在使用不同类型的输入文件(VFR 或 CRF)和视频格式(H264、VP9)进行测试,得到了相同的结果。

这些是该过程中涉及的步骤。

  1. 段输入
ffmpeg -i input.webm -c copy -map 0 -f segment -segment_list -segment_time 30 -segment_format matroska -vsync 2 -fflags +genpts %3d.webm
  1. 对每个片段进行转码
ffmpeg -i 000.webm -c:a copy -c:v libx264 -vf fps=fps=23.976 -movflags +faststart 000-out.webm
  1. 康卡特
ffmpeg -y -loglevel debug -f concat -safe 0 -i files.txt -c:v copy -c:a aac -movflags +faststart output.mp4

我注意到,如果我将以下标志添加到连接步骤中,视频和音频就会同步,但代价是稍微改变关节处的音调。

-af aresample=async=250

[concat @ 0x7fba3680a200] file:1 stream:0 pts:167 pts_time:0.167 dts:NOPTS dts_time:NOPTS -> pts:31142 pts_time:31.142 dts:NOPTS dts_time:NOPTS
[concat @ 0x7fba3680a200] file:1 stream:0 pts:83 pts_time:0.083 dts:0 dts_time:0 -> pts:31058 pts_time:31.058 dts:30975 dts_time:30.975
[concat @ 0x7fba3680a200] file:1 stream:1 pts:11 pts_time:0.011 dts:11 dts_time:0.011 -> pts:30986 pts_time:30.986 dts:30986 dts_time:30.986
[Parsed_aresample_0 @ 0x7fba56505e00] [SWR @ 0x7fba40008000] compensating audio timestamp drift:0.010590 compensation:250 in:44100
[Parsed_aresample_0 @ 0x7fba56505e00] [SWR @ 0x7fba40008000] Using fltp internally between filters
[concat @ 0x7fba3680a200] file:1 stream:1 pts:35 pts_time:0.035 dts:35 dts_time:0.035 -> pts:31010 pts_time:31.01 dts:31010 dts_time:31.01 

我还注意到,转码步骤前后的视频流持续时间略有不同。此外,如果我复制视频流而不是在步骤 2 中对其进行转码,问题仍然存在,但当我转换整个视频而不对其进行分段时,问题就不会存在。

我想知道是否有可能在不发生音频漂移的情况下重新编码视频,如果不行,请说明背后的原因和/或替代方法。谢谢!

答案1

我要给你扔一些东西。它可能会有帮助(也可能没有)。

比 fps=fps=23.976 更好的是 fps=fps=24000/1001。这将在处理流中为您提供更好的时间基准。但是,matroska 编码器将声明 1KHz 时间基准,因此可能没有区别。

当我知道原始视频是 CFR(BD 和 DVD 电影)时,为了避免时间基问题,我会创建自己的时间基,该时间基仅生成整数 PTS(显示时间戳),如下所示:

-vf "settb=expr=24000/1001,setpts=expr=N"

(我这样做是为了代替‘fps=’,因为我发现它不可靠。)

这样会生成 PTS:1 2 3 ...(换句话说,每个帧号 N 都将成为该帧的 PTS)。这样就不会出现像 1KHz 时间基准那样的舍入(或截断)问题。

在我的应用程序中,我采用 23.976fps 并将其转换为精确的 24fps。然后我使用运动矢量插值将帧速率提高五倍至 120fps。这在 60Hz 和 120Hz 电视上都显示得非常好,没有电视电影抖动,并且与影院中看到的速率(和播放时间)相同。我使用“atempo=1.001”稍微加快音频以使其与视频保持同步。(请注意,当输入 120fps 视频时,60Hz 电视只会每隔一帧丢失一次,这很好,而且比电视电影好得多)。

我不知道这些是否对你有帮助,但这些已经够了。祝你好运。

相关内容