使用 ffmpeg、shntool 和 sox 连接多个 24 位 96 kHz wav 音频文件

使用 ffmpeg、shntool 和 sox 连接多个 24 位 96 kHz wav 音频文件

我正在尝试连接 15 个 wav 音频文件,这些文件录制为 24 位、96kHz、线性 PCM。我使用 ffmpeg、shntool 和 sox 进行了实验,结果各不相同。

这些文件是由 Zoom H2n 录音机创建的,它将约 15 小时的连续录音分成几个文件(实时),以适应 SD 存储卡规格。

前 14 个文件每个大小为 2,147,385,344 字节(时间为 1:02:08.04),最后一个文件大小为 1,838,248,046 字节(时间为 53:11.35)。原始文件报告的比特率为 4,608 kb/s(使用 ffmpeg -i)。

使用 ffmpeg

创建一个带有以下文件名的文本文件:

printf "file '%s'\n" ./*.WAV > mylist.txt

连接文件:

ffmpeg -f concat -i mylist.txt -c copy output-ffmpeg.wav

这将生成一个大小为 31,901,151,444 字节的文件,但报告的时间仅为 53:08。ffmpeg -i 报告的比特率为 80,049 kb/s,远高于原来的 4,608 kb/s。

使用 shntool

加入文件:

shntool join -r none 01.wav 02.wav [etc]

这将生成一个大小为 31,901,151,386 字节的文件——与 ffmpeg 连接不同——但报告的时间也是 53:08.16。同样,ffmpeg -i 报告的比特率为 80,049 kb/s,远高于原始的 4,608 kb/s。

使用 Sox

连接文件:

sox 01.wav 02.wav [etc] output-sox.wav

这将生成一个大小为 31,901,151,422 字节的文件 - 与 ffmpeg 和 shntool 均不同 - 但报告时间为 01:02:08.26。ffmpeg -i 报告的比特率为 68,452 kb/s,远高于原来的 4,608 kb/s,但与 ffmpeg 或 shntool 转换不同。

问题

1) 我怎样才能让文件反映其实际时间?将这段 31 Gb / ~15 小时的录音放入认为它只有 ~53 分钟长的音频软件中可能会有问题。

2) 为什么这三个连接的文件大小不同?我是否应该使用某个标志或设置来(例如,出于某种原因)填充长度?不同的文件大小是否能说明为什么文件认为它们只有 53:08 或 01:02:08 长?

当我第一次看到 53:08 时,我想,啊,它正在将最后一个文件的时间长度写入标题中——但最后一个文件的时间长度实际上是 53:11。当我第一次看到 01:02:08.26 时,我想,啊,它正在写入第一个文件的时间长度,但遗憾的是,不是(接近,但不完全准确)。

似乎我最好的线索是连接文件的比特率不正确(?)。我很惊讶流复制或文件连接会改变这一点。也许这只是一个元数据错误?

答案1

.wavRIFF 文件格式(msdn)

RIFF 块数据的大小以 32 位存储。(最大无符号值为 4 294 967 295)

每个文件 RIFF 限制为 ~4.2 GBytes。

当软件创建一个非常大的 RIFF 块时,它的大小以 32 位值存储。

在某一点整数溢出发生并且数字的高位被丢弃

示例文件:6.220 GBytes / 3:00:00 / 96000 Hz / 24 位 / 2 通道 / 4608 kbit/s

Real file size(hex):              01 72 C9 E0 86  (6 220 800 134)
Readed from RIFF header(hex) :       72 C9 E0 7E  (1 925 832 830)

Real file size(binary):            1 01110010 11001001 11100000 10000110  //33 bits
Readed from RIFF header(binary):     01110010 11001001 11100000 01111110  //32 bits

01这是删除的部分。

ffprobe 报告:

Duration: 00:55:43.46, bitrate: 14884 kb/s
 Stream #0:0: Audio: pcm_s24le ([1][0][0][0] / 0x0001), 96000 Hz, 2 channels, s32 (24 bit), 4608 kb/s

FFprobe 错误时长/比特率

FFprobe 在文件中找到任何元数据并尝试从中计算它真实数据:

  1. 一条溪流比特率:4608千比特/秒(96000Hz * 24 位 * 2 通道)
  2. RIFF 块大小:1 925 832 830(正确,但错误:D)

持续时间为(整个块大小除以比特率):

1 925 832 830 / (4 608 000 / 8) = 3343.459 seconds

/ 8因为比特率是比特每秒(一个字节为8位)

3343.459 正好是00:55:43.459

平均的?)整个文件的比特率为 SizeOfFile / TotalSeconds:

6 220 800 134 / 3343.459 = 1860588.1316字节s/s ( 14884705.053少量秒/秒


如何获取一个大文件?

使用其他格式来存储它,例如:

FLAC / .rf64 / .w64 / 等等

使用 ffmpeg 连接文件(FFmpeg Wiki 页面连接):

ffmpeg -f concat -i mylist.txt -c:a flac output-ffmpeg.flac

哪里mylist.txt

file '/path/to/file1.wav'
file '/path/to/file2.wav'
file '/path/to/file3.wav'

已经有较大的 WAV 文件了吗?

你可以它。整体。用一个技巧。
我们将 RIFF 数据块的大小设置为0。这将导致一些(?)音频播放器读取整个数据块(直到文件末尾)。

来自编辑文件的 FFprobe 报告:

Duration: 03:00:00.00, bitrate: 4608 kb/s
 Stream #0:0: Audio: pcm_s24le ([1][0][0][0] / 0x0001), 96000 Hz, 2 channels, s32 (24 bit), 4608 kb/s

注意:重写完整文件不需要在 HEX 编辑器中保存文件时。

  1. 下载免费的 HEX 编辑器(例如 HxD)
  2. 对标记的字节进行截图或复制。(作为备份)
  3. 用 填充它00
  4. 如果使用 HxD:立即按下save按钮Cancel(以防止创建完整的备份副本)
  5. 打开。(测试于VLC/MPC-HC. 但 WMP 失败了 :D) 十六进制编辑器中的大 wav


FLAC 也可以使用以下方式转换选项 --ignore-chunk-sizes

如果 .WAV 有一些元数据在文件末尾。
使用 Audacity 测试。使用 HEX 编辑器检查,发现元数据在文件末尾。

FLAC:ERROR: got partial sample
但文件长度为 2:59:59 秒。并且没有 md5 校验和。
这意味着我们有不是真的flac 文件(读损坏
但可读性强。

相关内容