ffmpeg - 将音频编码为样本列表

ffmpeg - 将音频编码为样本列表

我想从音频文件中生成振幅的数字列表。我应该能够:

  • 指定采样率(16kHz、44.1kHz 等)
  • 指定振幅样本的数据类型(8 位整数、32 位浮点数等)
  • 轻松解析列表,以便我可以将其导入其他工具,如 Python 的 numpy(换行符分隔、csv 等)
  • 反过来,我还想要一种方法来将这样的列表重新编码为任意音频格式。

我相信我以前曾使用过 ffmpeg 来做这件事,但一直找不到解决方案。(或者可能是 Audacity?)

当我看到我最近的 ffmpeg 支持的编解码器集时(摘自ffmpeg -codecs),我认为我已经找到了答案:

 DEA..S pcm_f64be            PCM 64-bit floating point big-endian
 DEA..S pcm_s24be            PCM signed 24-bit big-endian
 DEA..S pcm_s64be            PCM signed 64-bit big-endian
 DEA..S pcm_s8               PCM signed 8-bit
 DEA..S pcm_u32be            PCM unsigned 32-bit big-endian
 DEA..S pcm_u8               PCM unsigned 8-bit

以上 ”相控阵相机“方法似乎准确地描述了我想要做的事情,但我只需要知道如何以可解析的格式提取样本。

我尝试过的所有命令都会以某种二进制编码创建文件,这些文件似乎需要某种解码器才能理解。以下是一个例子:

ffmpeg -i audio.wav -f u8 -c:a pcm_u8 -ar 16000 out.raw

ffmpeg 顺利完成该命令,但输出却难以辨认。

答案1

所有格式都需要一些一种解析器/解码器,但是,您示例中的 PCM 格式所需的解析器实际上比 CSV 所需的更简单。-f u8是一种非常简单的格式 - “PCM”不涉及任何压缩,在您的情况下它实际上是每个样本 1 个字节。

这意味着可以使用各种内置 Python 和/或 Numpy 函数来读取它。使用u8(每个样本 1 个字节),您不需要任何额外的东西,因为 Python 已经为您提供了bytearray由无符号整数值组成的数据:

注意:所有示例均适用于 Python 3。

with open("out_pcm_u8.raw", "rb") as fh:
    samples = list(fh.read())

对于这样的格式u32be,您可以使用“struct”或“array”模块,以及numpy.frombuffer()。所有必要的信息都已包含在格式名称中,您只需使用它help(struct)来查找匹配的类型(>对于 big-endian、I对于 u32、i对于 s32)。例如:

import struct

with open("out_pcm_u32be.raw", "rb") as fh:
    buf = fh.read()
    samples = [t[0] for t in struct.iter_unpack(">I", buf)]
import numpy

dt = numpy.dtype(">u4")
with open("out_pcm_u32be.raw", "rb") as fh:
    buf = fh.read()
    samples = numpy.frombuffer(buf, dtype=dt)

为了完整性,前面的例子的扩展版本struct

import struct

samples = []
with open("out_pcm_u32be.raw", "rb") as fh:
    while True:
        buf = fh.read(32 // 8)
        if buf:
            (samp,) = struct.unpack(">I", buf)
            samples.append(samp)
        else:
            break

相关内容