我正在尝试连接 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
.wav
是RIFF
文件格式(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 在文件中找到任何元数据并尝试从中计算它真实数据:
- 一条溪流比特率:4608千比特/秒(96000Hz * 24 位 * 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 编辑器中保存文件时。
- 下载免费的 HEX 编辑器(例如 HxD)
- 对标记的字节进行截图或复制。(作为备份)
- 用 填充它
00
。 - 如果使用 HxD:立即按下
save
按钮Cancel
(以防止创建完整的备份副本) - 打开。(测试于VLC/MPC-HC. 但 WMP 失败了 :D)
FLAC 也可以使用以下方式转换选项 --ignore-chunk-sizes
但
如果 .WAV 有一些元数据在文件末尾。
使用 Audacity 测试。使用 HEX 编辑器检查,发现元数据在文件末尾。
FLAC:ERROR: got partial sample
但文件长度为 2:59:59 秒。并且没有 md5 校验和。
这意味着我们有不是真的flac 文件(读损坏)
但可读性强。