我正在将无损压缩的视频和音频文件(Utvideo/LCPM)转换为 FFV1/FLAC 编解码器,使用 MKV 作为容器,以节省存储空间而不影响质量。我使用 ffmpeg 的 framemd5 功能来确保每次转换在输出方面与原始捕获都是 1:1。
批处理脚本如下:
for %%a in ("*.avi") do ffmpeg -i "%%a" -f framemd5 "%%~na.framemd5"
但是,当使用 FLAC 作为音频编解码器时,framemd5 输出的音频部分不再匹配。
以下是样本录音的 framemd5 的前 1001 行:
https://pastebin.com/axcf3f0a原始 LPCM
https://pastebin.com/3n75YTMjFLAC 转换
问题似乎是FLAC 添加了额外的元数据和自己的校验和,因此尽管音频应该是 1:1,但 framemd5 无法识别它。我不太熟悉 FLAC 的文件结构,所以我无法亲自验证这一点或想出解决方法。
有什么办法可以解决这个问题吗?我可以创建 framemd5 文件,以 1:1 的比例对 Utvideo/LPCM 和 FFV1/FLAC 之间的视频和音频进行校验吗?
这真是太令人沮丧了。我想使用 FLAC 来压缩音频,因为我已经尝试尽可能节省空间了。
答案1
这与 FLAC 流的元数据无关。
ffmpeg-all
在 framehash 上(framemd5是framehash的变体):
默认情况下,在计算哈希值之前,音频帧会转换为带符号的 16 位原始音频,视频帧会转换为原始视频
(注意:如果位深度较高,则需要指定相应的编码器, 例如-c:a pcm_s24le
后 -f framemd5
在“A 和 B”两种情况下都应避免对“截断的”音频帧执行校验和。)
因此,除非您指定了类似 的内容,否则校验和始终在解码的帧上执行(然后以某种“伪造”的方式编码,就像 PCM 的情况一样,或者不是这样)-c copy
。因此,元数据不会“干扰”此处的散列。
此处问题的真正原因是,与视频的情况不同,此处的“帧”在应用于音频流时不是指单个样本,而是指分组为数据包的整体样本。数据包的大小(样本数量)可能有所不同,具体取决于编码器/复用器(其代码中的默认值),也可能取决于用户的设置。
从输出线可以看出,对于 PCM,输入音频流中的每个数据包有 1024 个样本,而对于 FLAC,每个数据包有 4608 个样本。
TL;DR。这里的解决方案是在编码“压缩版本”-frame_size 1024
后添加。-c:a flac
PS 我不知道在任何情况下更改 FLAC 流的帧/数据包大小是否会给您带来任何问题(例如在播放中)/不良副作用,您可能想知道是否可以更改 PCM 流的帧/数据包大小。我只能说,在 PCM 的情况下,它将是复用器级别的事情,而不是像 FLAC 的情况那样是编码器级别的事情,这或多或少意味着它不太可能是用户可配置的。
虽然它可能有帮助也可能没帮助,但您始终可以尝试使用另一个 Matroska 多路复用器进行多路复用(来自原始流文件或 PCM 的 WAVE/AIFF 文件,而不是重新多路复用 Matroska 文件,因为所涉及的过程可能不同),以防1024
ffmpeg 中的 PCM-in-Matroksa 数据包/帧大小(即)在用于 FLAC 时不能很好地工作。
更新:显然,如果你使用 WAVE 文件作为输入,你可以使用-max_size
解复用器选项(WAVE dexmuer 的)来确定当流被输入到 Matrokska 复用器时每个数据包的大小。请注意,这-max_size
是以字节为单位而不是样本。因此,在这种情况下,您可以使用类似的东西ffmpeg ... -max_size 9216 -i path/to/input.wav ...
(确保您有-max_size
前 -i
)。我似乎没有在原始 PCM 解复用器 (例如s16le
) 中看到类似的选项,因此如果您需要使用它,则需要先将输入音频文件设为 WAVE 文件。
参考(默认代码中的位置):
https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/libavcodec/flacenc.c#L314
https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/libavformat/pcm.c#L27
https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/libavformat/wavdec.c#L76