github.com/eaburns/wav 是 go 中最轻量可控的 wav 解析方案,不依赖 cgo,自动校验 riff 结构、处理字节序与 chunk,支持 pcm 16/8-bit 解码为 []int16/[]byte;读取需用 wav.decode 并检查 format.tag == 1,写入必须用 wav.encode 自动更新 header,不可手动拼接。

github.com/eaburns/wav 是目前 Go 中解析 WAV 文件最轻量、最可控的选择,它不依赖 CGO,能安全提取头信息与原始采样数据,但只支持 PCM 编码(Format.Tag == 1)。其他格式(MP3、AAC、FLAC)必须走外部工具或绑定库。
怎么安全读取 WAV 头和 PCM 采样数据
别用 os.ReadFile + 手动跳 header,WAV 结构复杂(含可选 chunk、padding、字节序混用),极易错位或 panic。
github.com/eaburns/wav 会自动校验 RIFF 容器、识别 format chunk 和 data chunk,并把 PCM 样本转成 []int16(16-bit)或 []byte(8-bit)。
- 先用
os.Open打开文件,传给wav.Decode,它返回*wav.File - 检查
File.Format.Tag是否为1,否则直接报unsupported format -
File.SampleData就是原始采样点:单声道是[L0, L1, L2...],立体声是交错排列[L0, R0, L1, R1...] - 若需波形峰值(如画图),对每帧取
abs()后做滑动窗口最大值,别直接拿全部SampleData—— 大文件会 OOM
为什么不能直接用 encoding/binary 解析 WAV header
WAV 是小端序,但不同字段长度不一:ChunkSize 是 4 字节 uint32,BitsPerSample 是 2 字节 uint16,Subchunk1Size 后可能有 2 字节 padding。手动 binary.Read 极易偏移错位,尤其遇到 LIST / FACT chunk 时直接崩溃。
这个包内部做了 chunk 遍历+校验,比如跳过未知 chunk、对齐 subchunk 边界、验证 Subchunk2Size 是否匹配实际数据长度——这些逻辑自己写容易漏。
- 错误现象:
invalid wav: invalid data chunk size或解出静音/杂音 - 典型坑:把
fmt.Println(len(data))当作采样点数,其实要除以NumChannels × BitsPerSample/8 - 采样率、声道数、位宽必须从
File.Format读,不能硬编码
修改采样数据后怎么写回合法 WAV 文件
不能只改 SampleData 再用 os.WriteFile 封装——WAV header 里 Subchunk2Size(数据块字节数)和 ChunkSize(整个文件大小减 8)必须严格匹配新数据长度,否则播放器静音或拒绝加载。
wav.Encode 会自动重算所有 header 字段,但有硬性限制:
- 只接受
[]int16输入,即默认输出 PCM 16-bit;原始是 24-bit 或 float32 必须先转换,否则截断丢精度 - 输入长度必须是
NumChannels × N,否则 panic:sample count not divisible by channel count - 用
os.Create打开目标文件,别用os.OpenFile(..., os.O_APPEND)—— header 要从头写 - 该包不保留 INFO、LIST 等元数据 chunk;如需保留,得换
github.com/mjibson/go-dsp或手撸 chunk 遍历
非 WAV 格式(MP3/AAC/FLAC)怎么办
Go 没有稳定、完整的纯实现音频解码器。试图用 gopkg.in/h2non/gock.v1 或 faiface/audio 做格式转换,基本都会卡在 MP3 header 解析或 AAC ADTS 同步字上。
生产环境唯一靠谱方案是调用 ffmpeg 二进制:
- 用
exec.Command("ffmpeg", "-i", input, "-f", "wav", "-acodec", "pcm_s16le", "-y", output)先转成 WAV 再用eaburns/wav处理 - 务必用参数切片传参,避免 shell 注入;路径用绝对路径;加
-y防卡死;捕获cmd.Stderr查错 - 并发转多文件时,用
golang.org/x/sync/semaphore限流(建议 ≤3),否则 CPU 扛不住 - 不要幻想“纯 Go 实现所有编解码”,FFmpeg 的解码逻辑已迭代 20 年,稳定性和兼容性远超任何新写的 Go 库
真正容易被忽略的是:WAV 解析只是起点,后续波形缩放、峰值聚合、跨声道对齐这些操作,全得自己按 Format.NumChannels 和 Format.SampleRate 对齐——没标准 API,全靠手动算帧长和窗口步长。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











