Wave标准库仅支持读取WAV头和PCM裸数据,不支持解码压缩格式、采样点浮点转换、声道混音或重采样;必须用'rb'模式打开文件,getparams()返回固定顺序六元组,readframes()返回bytes需手动转numpy数组。

Wave 标准库能读取 WAV 文件头和原始 PCM 数据,但不支持解码压缩格式(如 MP3、ADPCM)、不提供采样点浮点转换、也不做声道混音或重采样——它只做“裸数据搬运工”。
用 wave.open() 打开文件时必须注意二进制模式
WAV 是二进制格式,wave.open() 内部依赖字节流解析。如果用文本模式打开(比如 wave.open('a.wav', 'r')),Python 3 会报 TypeError: expected str, bytes or os.PathLike object, not int 或更隐蔽的 struct.error —— 因为底层 struct.unpack() 读到了错误字节。
- 正确写法始终是
wave.open('audio.wav', 'rb')(即使文档说 mode 可省略,默认也是'rb',但显式写出更安全) - Windows 下若用
'r'模式,换行符转换可能破坏 RIFF chunk 对齐,导致readframes()返回空或截断 - 如果路径含中文或特殊字符,建议先用
pathlib.Path.resolve()归一化,再传给wave.open()
getparams() 返回元组,不是字典,字段顺序固定
getparams() 返回的是 (nchannels, sampwidth, framerate, nframes, comptype, compname) 六元组,没有键名。新手常误以为它是 dict,写成 params['framerate'] 直接报 TypeError。
- 推荐解包使用:
nchannels, sampwidth, framerate, nframes, comptype, compname = wav.getparams() -
sampwidth是每样本字节数(1=8-bit, 2=16-bit, 4=32-bit),不是位深;8-bit WAV 是 unsigned,其他通常是 signed little-endian -
comptype为'NONE'才代表 PCM;若为'ULAW'或'IMA ADPCM',readframes()返回的是编码后字节,需额外解码——wave库不处理这些
用 readframes(n) 读 PCM 数据,结果是 bytes,不是 NumPy 数组
readframes(n) 返回的是原始字节串,长度为 n * nchannels * sampwidth。它不自动转成整数数组,也不区分单/双声道排列方式(LRLR 还是 LLRR)。
- 要转成 16-bit 立体声 numpy 数组:先
data_bytes = wav.readframes(-1),再np.frombuffer(data_bytes, dtype=np.int16).reshape(-1, nchannels) - 8-bit WAV 需手动偏移:
np.frombuffer(data_bytes, dtype=np.uint8) - 128得到有符号范围 - 读全部帧用
readframes(-1),别用readframes(wav.getnframes())—— 后者在某些损坏文件上可能少读最后一帧 - 大文件慎用
readframes(-1),可能爆内存;应分块读(如每次 8192 帧),并注意末尾帧数可能不足预期
真正容易被忽略的是:WAV 文件可能含非标准 chunk(如 LIST, cue , plst),wave 库会跳过它们,但若自定义 chunk 破坏了 RIFF 结构对齐,readframes() 可能提前 EOF 或静音。遇到读不出数据时,先用 xxd audio.wav | head -20 看前几个字节是否为 52 49 46 46 xx xx xx xx 57 41 56 45(即 "RIFF" + size + "WAVE")。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











