解码微信语音文件

编码格式

微信的语音文件虽然扩展名为.amr,但内部却用的SILK编码格式:

SILK v3 编码是 Skype 向第三方开发人员和硬件制造商提供免版税认证(RF)的 Silk 宽带音频编码器,Skype 后来将其开源

采样率为 24000Hz,单声道。

开源实现

skype 项目已经停用,silk v3 编码被腾讯继承并发扬光大,微信、QQ 等产品都在使用。

虽然 skype 已经开源,但使用起来并不方便。

先有基于官方 C 源码的silk-v3-decoder,然后有了 python bindings pilk
后有用 rust 改写的silk-rs,然后有了 silk-rs的 python binding rsilk

我也分叉silk-v3-decoder,加上了docker 支持

解码

1
2
3
4
5
6
7
8
9
> ./decoder
usage: decoder.exe in.bit out.pcm [settings]

in.bit : Bitstream input to decoder
out.pcm : Speech output from decoder
settings:
-Fs_API <Hz> : Sampling rate of output signal in Hz; default: 24000
-loss <perc> : Simulated packet loss percentage (0-100); default: 0
-quiet : Print out just some basic values

具体示例:

1
2
3
4
5
6
7
8
9
10
> ./decoder msg_13141905142479bebcac2e0102.amr 102.pcm
********** Silk Decoder (Fixed Point) v 1.0.9.6 ********************
********** Compiled for 32 bit cpu *******************************
Input: msg_13141905142479bebcac2e0102.amr
Output: 102.pcm
Packets decoded: 90
Decoding Finished

File length: 1.800 s
Time for decoding: 0.001 s (0.050% of realtime)

转码

pcm 文件是裸音频文件,24000 的采样率也没必要用 wav,一定都转成 mp3 格式使用。

转码可以使用专精 mp3 的lame或者全能王ffmpeg

lame

lame 的命令行参数可以参考这里

1
./lame -r -s 24000 -m m 106.pcm 106_lame_mono.mp3

但不知道为什么,这样输出的 mp3 文件会有少许拉伸,时间会变长。
使用立体声输出就没问题:

1
./lame -r -s 12000 106.pcm 106_lame.mp3

ffmpeg

ffmpeg 的音频用法可以参考官方文档

1
./ffmpeg -y -f s16le -ar 24000 -ac 1 -i 106.pcm 106_ffmpeg_mono.mp3

ffmpeg 就很稳定,转码后的文件时间和原文件几乎一致。转成双声道也没问题。

1
./ffmpeg -y -f s16le -ar 12000 -ac 2 -i 106.pcm 106_ffmpeg.mp3

最佳实践

直接使用 docker,不用担心编译环境问题。

为了简洁易用,默认 entrypoint 只有一个功能,将微信语音文件.amr转成.mp3

单个文件

转码当前目录下的单个文件为.mp3,文件名保持不变:

1
docker run -it --rm -v $(pwd):/app lckof/silk-v3-decoder msg_13141905142479bebcac2e0102.amr [102.mp3]

目录

递归遍历,转码指定目录下的所有.amr文件为.mp3,保持目录结构,输出到指定目录。

如不指定输入目录,则默认为当前目录。

如不指定输出目录,则默认输出到同输入目录。

1
docker run -it --rm -v $(pwd):/app lckof/silk-v3-decoder [.] [output]