FFMPEG Concat 导致音频延迟

FFMPEG Concat 导致音频延迟

我正在编辑一些旧的自制视频,我想将文件(约 2 小时长,60 GB)分割成较小的块,约 10-15 分钟长,以便在不同的媒体上存档。

目前,我正在测试将文件(片段)合并/连接回完整长度的视频(源)。

源文件是隔行扫描的,恒定 25 fps,无损 ff1v 3.4,yuv 4:2:2,带有 pcm_s16le 48kHz 音频。我使用以下命令通过解复用器“segment”生成分割文件:

ffmpeg -r 25 -i source.mkv" -force_key_frames "expr:gte(t,n_forced*60)" -map 0 ^
-c:v copy -c:a pcm_s16le -f segment -segment_time 00:01:00 ^
-segment_time_delta 0 -reset_timestamps 1 -break_non_keyframes 0 ^
"%%~out_part%%03d.mkv"

(-r、-force_key_frames 可以省略 - 结果相同)

然后我使用 VirtualDub2 比较帧数、分割位置的帧数和音频:该命令生成与源相同的片段(帧数、音频延迟等)。所以,这一步似乎没问题。

使用 concat 命令我将这些 splatted 文件(段)连接起来:

ffmpeg -f concat -safe 0 -i list.txt -c copy D:\output.mkv

当将(VirtualDub2)concat 的结果与源进行比较时,我注意到结果有音频延迟(视频帧正常) - 参见下图。

现在,这不是一个交易障碍,因为每个段的延迟大约为 10 毫秒,但我仍然想知道我是否做错了什么。

看起来延迟是复合的:1 分钟片段的连接将比 5 分钟片段的连接产生更多的延迟。

源图像与 Concat 结果(和片段)的图像,音频延迟

使用 ffprobe(-show_format -show_streams)对片段进行操作时,我注意到音频流具有属性“start_time=0.001000”,这会是个问题吗?

我在源上运行了“-f md5”哈希和“-framehash -hash md5”,并将结果合并,但哈希值相等。它可能是 VirtualDub2 本身……

是否有任何 concat 或者segment 参数可以用来缓解这种行为?

欢迎任何建议。

此致!


源文件信息:

Input #0, matroska,webm, from 'source.mkv':
  Metadata:
    ENCODER         : Lavf58.29.100
  Duration: 00:34:47.16, start: 0.000000, bitrate: 64117 kb/s
    Stream #0:0: Video: ffv1 (FFV1 / 0x31564646), yuv422p(bt470bg), 768x576, 25 fps, 25 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      ENCODER         : Lavc58.54.100 ffv1
      DURATION        : 00:34:47.040000000
    Stream #0:1: Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s (default)
    Metadata:
      DURATION        : 00:34:47.161000000

答案1

事实证明,以上述方式使用 concat 会导致音频问题。另一种方法是使用选项 copyts 和 start_at_zero 生成 .m3u8 文件(片段列表)。此外,还应将音频提取到单独的文件中(而不是分段)。

分割文件的命令:

ffmpeg -i "source.mkv" -dn -sn ^
    -c:v copy -c:a copy -copyts -start_at_zero ^
    -f segment -segment_list "out.m3u8" -segment_time 00:05:00 "out_part%%03d.mkv" ^
    -dn -sn -vn -c:a copy "out.wav"

这应该会生成 m3u8 文件、视频+音频片段和 wav 格式的音频文件。

连接:我们不使用 concat,而是打开 m3u8 播放列表和音频文件,并使用命令合并片段:

ffmpeg -i "source.m3u8" ^
    -i "source.wav" ^
    -map 0:0 -map 1:0 ^
    -c:v copy -c:a copy "out_merged.mkv"

使用命令 map,我们将适当的流映射到 out_merged 文件。在我有限的测试中,即使我省略了生成单独的音频文件(而只是将音频分段合并),音频也是没问题的,但在我看来,这对于存档来说是更好的做法。

我对 ffmpeg 了解不够,不知道这种方法和 OP 中的 concat 有什么区别(可能是在消除时间戳?)。我从以下答案中得到了类似的代码和“灵感”:https://superuser.com/a/1536037/1147027. 它提到了“段列表文件”和“连接文件”之间的区别。

非常感谢 Eugen Rieck。


补充:有些文件存在 1/4 帧音频延迟,但似乎不会随着视频长度(2 小时)而增加,也不会因为片段时长缩短(1 分钟片段 vs 5 分钟片段)而增加,就像 OP 中的 concat 情况一样。合并分段音频或单独文件中的音频时确实如此。

合并后的文件比源文件略小(30 GB 视频上约 700 B),但音频/视频的 md5 哈希值相同。

有趣的是,如果合并的文件被分割并再次合并(源>分段->合并>分段2>合并2),则合并2与合并中没有音频延迟(即使源与合并中有延迟)并且文件大小相同。md5 哈希保持不变。

此外,我还在生成的视频+音频剪辑上测试了分段和连接。它表示一些简单的颜色和正弦波音频,并添加了“嘟嘟声”,以便于检测片段之间的异常:

ffmpeg -v "verbose" ^
    -f lavfi -i color=white:640x480:d=720 ^
    -f lavfi -i color=red:640x480:d=900 ^
    -f lavfi -i color=blue:640x480:d=420 ^
    -f lavfi -i "sine=f=25:b=100:r=48000:d=2040" ^
    -filter_complex "[0][1][2]concat=n=3:v=1:a=0,format=yuv420p[v0]" ^
    -map "[v0]" -map 3:a -shortest ^
    -c:v ffv1 -c:a pcm_s16le sample_source.mkv

相关内容