使用 ffmpeg 连接音频文件会导致错误的总持续时间

Concatenating audio files with ffmpeg results in a wrong total duration

“总持续时间错误”是指总持续时间与音频文件的各个持续时间之和不同。

sum_duration_files != 持续时间(文件串联)

特别是我用这个命令连接了 2 个 OGG 音频文件

ffmpeg -safe 0 -loglevel quiet \
  -f concat -segment_time_metadata 1 -i {m3u_file_name} \
  -vf select=concatdec_select \
  -af aselect=concatdec_select,aresample=async=1 \
  {ogg_file_name}

我得到以下内容

# Output of:  ffprobe <FILE>.ogg


======== files_in 

Input #0, ogg, from 'f1.ogg':
  Duration: 00:00:04.32, start: 0.000000, bitrate: 28 kb/s
    Stream #0:0: Audio: opus, 48000 Hz, mono, fltp


Input #0, ogg, from 'f2.ogg':
  Duration: 00:00:00.70, start: 0.000000, bitrate: 68 kb/s
    Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 160 kb/s
    Metadata:
      ENCODER         : Lavc57.107.100 libvorbis

音符时长:4.32 和 0.7 秒

这是输出文件。

========== files out (concatenate of files_in)

Input #0, ogg, from 'f_concat_v1.ogg':
  Duration: 00:00:04.61, start: 0.000000, bitrate: 61 kb/s
    Stream #0:0: Audio: vorbis, 48000 Hz, mono, fltp, 80 kb/s
    Metadata:
      ENCODER         : Lavc57.107.100 libvorbis

时长:4.61 秒

因为 4.61 秒 != 4.32 + 0.7 秒我有问题。

我不知道为什么会这样,但我知道如何在我的特定情况下避免这个问题。

我的情况: 我正在混合(连接)由一个来源生成的不同音频文件和我生成的静音文件。

最初我用

生成了静默文件
# x is a float from python

ffmpeg -f lavfi -i anullsrc=r=44100:cl=mono -t {x:2.1f} -q:a 9 -acodec libvorbis silence-{x:2.1f}.ogg

试图解决我的问题 re-created 与我混音的音频具有相同参数的静音,即(48Khz 的单声道):

ffmpeg -f lavfi -i anullsrc=r=48000:cl=mono -t {x:2.1f} -c:a libvorbis silence-{x:2.1f}.ogg

现在 ffprobe 显示了预期的结果。

========== files out (concatenate of files_in)

Input #0, ogg, from 'f_concat_v2.ogg':
  Duration: 00:00:05.02, start: 0.000000, bitrate: 56 kb/s
    Stream #0:0: Audio: vorbis, 48000 Hz, mono, fltp, 80 kb/s
    Metadata:
      ENCODER         : Lavc57.107.100 libvorbis

持续时间:5.02 = 4.32 + 0.70

如果您想避免在将静音与其他声音连接时出现问题,请使用与您要混合的声音相同的参数(mono/stereo 和 Hz)创建静音

==== 2022-03-08 更新

使用@kesh 提供的信息,我使用

重新创建了静默的 ogg 文件
ffmpeg -f lavfi -i anullsrc=r=48000:cl=mono -t 5.8 -c:a libopus silence-5.8.ogg

现在

ffmpeg -safe 0 -f concat -segment_time_metadata 1 
-i {m3u_file_name} 
-vf select=concatdec_select 
-af aselect=concatdec_select,aresample=async=1 {ogg_file_name}

不再(多次)抛出此错误。

[opus @ 0x558b2c245400] Error parsing the packet header.
Error while decoding stream #0:0: Invalid data found when processing input

我必须说这个错误并没有(对我)造成任何问题,因为输出是我所期望的,但现在没有它我感觉好多了。

这里的问题是对这些文件使用了错误的串联方法。正如 FFmpeg wiki article 所建议的那样,file-level 串联 (-f concat) 要求列表中的所有文件具有完全相同的编解码器参数。在您的情况下,只有频道数 (mono) 和样本格式 (flt) 在它们之间是通用的。另一方面,编解码器(opus vs. vorbis)和采样率(48000 vs. 44100)不同。

-f concat 获取第一组参数并使用它运行。在您的情况下,它对所有文件使用 48000 S/s。虽然第二个文件是 44100 S/s,但它假定为 48k(因此播放速度会比现在快)。我不知道编解码器的差异如何在输出中发挥作用。

因此,标准方法是使用 -filter_complex concat=a=1:v=1:n=2 这些文件作为单独的输入。

出于好奇,你听过 wrong-duration 输出文件了吗? [编辑:没关系,你的 self-answer 表明其中之一是无声轨道]