我正在编辑一些旧的自制视频,我想将文件(约 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 分钟片段的连接产生更多的延迟。
使用 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