有些蓝牙音频设备的本地音乐需要用到sbc
格式,比如恒玄(BES)的蓝牙耳机,如果是从事BES平台开发的同学肯定都非常了解吧,他们的本地音频使用的就是txt形式的sbc格式,而且还是单声道16比特,16KHz采样率的的sbc格式
实现思路
因为我个人平时使用Unix系统比较多,比如Macos和Ubuntu,所以我着重考虑如何在Unix平台上实现这种音频转换,其实很多带界面的工具使用起来也比较简案,但是个人认为命令工具效率很更高,尤其是在批量操作的时候,优势则更加明显,作为不怎么喜欢用鼠标的技术宅,能命令行就命令行吧
我能想到的有二种思路:
- 找一些wav编码成sbc的开源代码,这些开源代码基本上都是用C/C++实现的,把这些代码整合到自己项目中来,比如ffmpeg的编解码器等,然后用C调用这些编解码函数。但是这种实现非常麻烦,尤其是对于初学音频的人来说
- 第二种方案是自己用脚本来实现,我们知道
ffmpeg
是一款非常强大的音视频处理软件,我们直接在shell
上调用ffmpeg
命令就可以实现wav到sbc的格式转化,但是不能得到sbc的txt形式,不过后面这部分工作我们可以用脚本来实现,这种方案非常简单,而且不用懂音频知识都可以实现
环境安装
我现在使用的是Ubuntu的环境,由于Ubuntu默认情况下并没有安装ffmpeg
,但是安装命令也非常简单
$ sudo apt-get install ffmpeg -y
先来查看下我的测试音频
$ ffmpeg -i test.wav
Input #0, wav, from 'test.wav':
Duration: 00:00:01.91, bitrate: 1536 kb/s
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, 2 channels, s16, 1536 kb/s
可以看出我的音频文件是48KHz采样率,双声道,16比特的格式
现在需要将其转化成16KHz采样率,单声道,16比特的sbc文件,输入命令如下
$ ffmpeg -i test.wav -ar 16000 -ac 1 test.sbc
Stream mapping:
Stream #0:0 -> #0:0 (pcm_s16le (native) -> sbc (native))
Press [q] to stop, [?] for help
Output #0, sbc, to 'test.sbc':
Metadata:
encoder : Lavf58.45.100
Stream #0:0: Audio: sbc, 16000 Hz, mono, s16, 128 kb/s
Metadata:
encoder : Lavc58.91.100 sbc
size= 30kB time=00:00:01.91 bitrate= 128.0kbits/s speed= 513x
video:0kB audio:30kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
我们再查看下test.sbc的格式
$ ffmpeg -i test.sbc
Input #0, sbc, from 'test.sbc':
Duration: N/A, start: 0.000000, bitrate: N/A
Stream #0:0: Audio: sbc, 16000 Hz, mono, s16
已经是单声道,16KHz采样率,16比特的sbc文件了
我们现在继续将这个sbc文件转化成TXT格式
#! /usr/bin/python
import sys
import os
input = "test.sbc"
# 读sbc文件
with open(input, "rb") as f:
content = f.read()
out = ""
# 将其转化成Hex形式的TXT文件
for i in range(len(content)):
if i % 16 == 0 and i != 0:
out += "\n";
out += "0x%02x," % ord(content[i])
output = os.path.splitext(input)[0] + ".txt"
# 输出到文件 test.txt
with open(output, "w+") as f:
f.write(out)
print("done")
test.txt
文件就是我们想要的文件
功能整合
现在我们把这2部分工作整合到一个Python
脚本中来实现吧
#! /usr/bin/python
#coding=utf-8
# Filename: wav2sbc.py
import sys
import os
def transfer(input):
# 读sbc文件
with open(input, "rb") as f:
content = f.read()
out = ""
# 将其转化成Hex形式的TXT文件
for i in range(len(content)):
if i % 16 == 0 and i != 0:
out += "\n";
out += "0x%02x," % ord(content[i])
output = os.path.splitext(input)[0] + ".txt"
# 输出到文件 test.txt
with open(output, "w+") as f:
f.write(out)
def wav2sbcHex(wavFilename):
sbcFilename = os.path.splitext(wavFilename)[0] + ".sbc"
cmd = "ffmpeg -i %s -ar 16000 -ac 1 %s" % (wavFilename, sbcFilename)
os.popen(cmd)
if os.path.isfile(sbcFilename):
print("Wav Transfer sbc Successfully");
else:
print("Wav Transfer sbc Error")
exit(1)
transfer(sbcFilename)
txtFilename = os.path.splitext(sbcFilename)[0] + ".txt"
if os.path.isfile(txtFilename):
print("Sbc Transfer Hex txt Successfully")
print("Done")
else:
print("Sbc Transfer Hex txt Error")
exit(1)
if __name__ == "__main__":
for wavFilename in sys.argv[1:]:
wav2sbcHex(wavFilename)
这个脚本接收命令行参数作为输入,输出对应的sbc文件和txt文件
$ ./wav2sbc.py test.wav
Wav Transfer sbc Successfully
Sbc Transfer Hex txt Successfully
Done
上面的命令在当前目录生成test.sbc
和test.txt
文件
如果想要实现批量转化也非常简单,下面的命令可以一次性转化当前目录下所有的wav文件
$ ls *.wav | xargs ./wav2sbc.py