ffmpeg concat 过滤器逐渐增加音频延迟

ffmpeg concat 过滤器逐渐增加音频延迟

我使用 ffmpeg 连接大量视频文件,使用 filter_complex。但是,结果文件的音频不同步逐步地

并且我在接下来的过程中使用mediainfo --Inform='Video;%Duration%' filename.ext和来显示持续时间数字。mediainfo --Inform='Audio;%Duration%' filename.ext

给定原始源文件,下面是如何重现我的问题的方法:

Stream #0:0(eng): Video: wmv3 (Main) (WMV3 / 0x33564D57), yuv420p, 1920x1080, 6000 kb/s, 29.97 fps, 29.97 tbr, 1k tbn, 1k tbc
Stream #0:1(eng): Audio: wmav2 (a[1][0][0] / 0x0161), 48000 Hz, stereo, fltp, 128 kb/s

尺寸太大,但其视频和音频轨道共享持续时间完全相同mediainfo 报告 XXXXXXX 毫秒

为了测试目的,我使用了它的前 5 秒,使用双“-t 5”

ffmpeg -t 5 -i input.wmv -map 0:v:0 -map 0:a:0 -map_chapters -1 \
    -vcodec copy -acodec copy -t 5 source_v5a5.mkv

结果持续时间(毫秒):

5004.000000     video of source_v5a5.mkv
5119.000000     audio of source_v5a5.mkv

差异是 119-4=115ms,mediainfo filename.ext目前没有报告任何有关延迟的信息,这个片段在我观看时播放正常,可能包含 115ms 的延迟(在头部?)但并不那么明显,例如

[vvvvvvvvv………………v]
[-aaaaaaaaa………………a]

现在复制此文件 3 次,假装我们有很多不同的片段,然后分别编码视频和音频轨道:

ffmpeg -i source_v5a5_p1.mkv -i source_v5a5_p2.mkv -i source_v5a5_p3.mkv -i source_v5a5_p4.mkv \
    -filter_complex " \
    [0:v:0]setpts=PTS-STARTPTS[v0];[0:a:0]asetpts=PTS-STARTPTS[a0]; \
    [1:v:0]setpts=PTS-STARTPTS[v1];[1:a:0]asetpts=PTS-STARTPTS[a1]; \
    [2:v:0]setpts=PTS-STARTPTS[v2];[2:a:0]asetpts=PTS-STARTPTS[a2]; \
    [3:v:0]setpts=PTS-STARTPTS[v3];[3:a:0]asetpts=PTS-STARTPTS[a3]; \
    [v0][a0][v1][a1][v2][a2][v3][a3] concat=n=4:v=1:a=1 [out]" \
    -map "[out]" \
    -vsync vfr -vcodec libx264 -preset veryfast -tune film -crf 23 \
    -acodec pcm_s16le -f tee "[select=v:f=mp4]output_video_track.mp4"

是的,我在这里添加了编解码器,但只输出视频流。现在编码音频,将 ffmpeg 输出到 NeroAAC

ffmpeg -i source_v5a5_p1.mkv -i source_v5a5_p2.mkv -i source_v5a5_p3.mkv -i source_v5a5_p4.mkv \
    -filter_complex " \
    [0:v:0]setpts=PTS-STARTPTS[v0];[0:a:0]asetpts=PTS-STARTPTS[a0]; \
    [1:v:0]setpts=PTS-STARTPTS[v1];[1:a:0]asetpts=PTS-STARTPTS[a1]; \
    [2:v:0]setpts=PTS-STARTPTS[v2];[2:a:0]asetpts=PTS-STARTPTS[a2]; \
    [3:v:0]setpts=PTS-STARTPTS[v3];[3:a:0]asetpts=PTS-STARTPTS[a3]; \
    [v0][a0][v1][a1][v2][a2][v3][a3] concat=n=4:v=1:a=1 [out]" \
    -map "[out]" \
    -vcodec rawvideo \
    -acodec pcm_f32le -f tee "[select=a:f=wav]pipe\:"|neroAacEnc -ignorelength \
    -q 0.2 -if - -of "output_audio_track.m4a"

是的,我在这里添加了 vcodec 但只输出音频流。

结果持续时间(毫秒):

20020           output_video_track.mp4
20309           output_audio_track.m4a
20069.000000    video stream of output_MkvMergeMuxed.mkv
20310.000000    audio stream of output_MkvMergeMuxed.mkv

差别超过 200 毫秒,似乎延迟是在连接过程中加入的?播放混合文件时,一开始还可以,但最后一部分我会感觉到延迟

假设延迟发生在头部,则绘制如下:

[v111111v222222v333333v444444]
[-a111111-a222222-a333333-a444444]

正如文档中所写:https://ffmpeg.org/ffmpeg-filters.html#concat

concat 过滤器将使用每个片段中最长的流的持续时间(最后一个片段除外),并且如果有必要,用静音填充较短的音频流。

怀疑我的测试不够,我用source_重新做了一遍整个过程v5a2.mkv,然后再次使用 source_v5a10.mkv

期间:

5004.000000         video of source_v5a2.mkv
2279.000000         audio of source_v5a2.mkv
5004.000000         video of source_v5a10.mkv
10281.000000        audio of source_v5a10.mkv

ffmpeg 按照文档所述执行(静音填充,就像应用了 apad/最后一帧冻结一样),但结果仍然大致相同:在最后一段的开头发现明显的延迟

[v111111v222222v333333v444444]
[-a111___-a222___-a333___-a444]

[v111___v222___v333___v444___]
[-a111111-a222222-a333333-a444444]

上面的测试连接仅 4 个文件. 连接时50 多个文件,不同步是显著的,你不能忽视它


问题:

给定一堆视频文件(50+,视频音频相同的分辨率/编解码器/音轨号/等,大部分持续时间相同,有些则不同)连接,如何减少/避免延迟以使其同步无需用黑屏填充视频? 喜欢

[v111111v222222v333333v444444]
[-a111111a222222a333333a444444]

或者更好的是,延迟裁剪(也许 mkvmerge 可以在之后通过一些计算来处理这个问题

[v111111v222222v333333v444444]
[a111111a222222a333333a444444]

最好有没有创建中间文件,管道没问题


更新:

也许我完全搞错了。也许这不是延迟,而是“拉伸/挤压”。我进行了一次长时间的测试,连接了 30 个 wmv 文件,使用上面的命令,我得到了结果文件A,同步时间超过 1 秒:

Stream #0:0: Video: h264 (High), yuv420p(progressive), 640x480 [SAR 4:3 DAR 4:3], 29.97 fps, 29.97 tbr, 1k tbn, 59.94 tbc (default)
Metadata:
  DURATION-eng    : 05:32:10.544000000
  NUMBER_OF_FRAMES-eng: 597298
Stream #0:1: Audio: aac (HE-AAC), 48000 Hz, stereo, fltp (default)
Metadata:
  DURATION-eng    : 05:32:11.861000000
  NUMBER_OF_FRAMES-eng: 467153

之后,我aresample=async=1在 asetpts 之前添加到过滤器,然后重新编码为文件 B

Stream #0:0: Video: h264 (High), yuv420p(progressive), 640x480 [SAR 4:3 DAR 4:3], 29.97 fps, 29.97 tbr, 1k tbn, 59.94 tbc (default)
Metadata:
  DURATION-eng    : 05:32:11.727000000
  NUMBER_OF_FRAMES-eng: 597298
Stream #0:1: Audio: aac (HE-AAC), 48000 Hz, stereo, fltp (default)
Metadata:
  DURATION-eng    : 05:32:11.862000000
  NUMBER_OF_FRAMES-eng: 467153

文件 A 也有同步问题,但文件 B 同步正常!所以aresample=async=1适用于音频的规则实际上对音频没有任何影响,但对视频有影响!我认为这与 PTS 有关。经过一番谷歌搜索,我做了以下事情实验 A

  1. 转变05:32:10.54400000005:32:11.727000000进入1993054419931727
  2. 使用 mkvmerge,拖入文件 A,放入19931727/19930544进入 ”伸展“视频轨道框,开始复用

结果文件同步正常(可能没有明显的不同步),同步问题似乎与 PTS 有关?进一步研究,假设正确同步的文件持续时间较长,而不同步的文件持续时间较短,我做了以下事情实验 B

  1. 用于mediainfo --Inform='General;%Duration%' filename.ext获取每个文件的持续时间
  2. 将每个持续时间数字相加

总持续时间为05:32:10.438,几乎是持续时间较短的

新问题:

  1. 我的初始命令是否产生了“正确的 PTS,更长的音频”或“压缩的 PTS,正确的音频”?
  2. 如果是“正确的 PTS,更长的音频”,我该如何使音频正确?
  3. 如果是“压缩 PTS,纠正音频”,则表示aresample=async=1 在拼接视频时使用正确的方式修复 PTS从头开始
  4. 如果是“压缩 PTS,正确音频”,为什么我的实验 B显示总持续时间非常接近较短(压缩)的持续时间?
  5. 如果实验 B是错误的,我应该如何在编码过程之前预测/计算正确的总持续时间?
  6. 给定一个“挤压的 PTS,正确的音频”文件,没有源文件,我是否可以仅使用数字“AudioDuration/VideoDuration”来拉伸/挤压 PTS 来解决同步问题?
  7. 当不合并文件,只对一个文件进行编码时,是否有必要aresample=async=1是否使用 vf 或 af?如果使用 vf 或 af,是否有必要?是否有任何缺点?

上面的文字很长,即使你无法回答,也感谢你读到最后。:)

相关内容