概述
最近在对接百度TTS的python接口,对接的过程中发现一些问题,记录下解决方案。
百度TTS接口返回的音频数据格式有4种,分别是mp3,pcm-16k,pcm-8k,wav(pcm-16k)。
我们需要的结果是wav(pcm-8k)。
需求对齐后,分析解决方案,主要有以下几个选择。
1, mp3转码为wav,比如python库AudioSegment。
2, wav(pcm-16k)重采样为wav(pcm-8k),比如python库wave。
3, pcm-8k转换为wav格式,比如python库wave。
4, pcm-8k手动增加wav格式头信息,写入文件。
今天选择第4种方案,并顺便复习了一下wav格式的头部信息。
环境
python 3.10.3
wav文件格式
先复习一下wav文件的格式信息。
下面的截图是根据我的理解画的,仅仅针对pcm编码格式,其他压缩编码格式会多一个fact chunk(在fmt chunk和data chunk中间),有兴趣的可以自行查找资料。
源码
之前用c写过wav的头文件信息,用python还是第一次。
其中aip是百度tts的python库,struct是python内建模块,用于python字符串和C语言结构体之间的转换,我们用struct库对字符串和整数做序列化。
#required python3
from aip import AipSpeech
from struct import pack
def tts_baidu(content, filename):
#init client
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
## aue:3-mp3, 4-pcm-16k, 5-pcm-8k, 6-wav(pcm-16k)
result = client.synthesis(text = content, lang = 'zh', ctp = 1, options = {'aue': 5, 'per': 0, 'vol': 5})
# 识别正确返回语音二进制 错误则返回dict 参照下面错误码
if not isinstance(result, dict):
with open(filename, 'wb') as f:
##aue use 5-pcm-8k, write wav header info first
header = ''
header = pcm_wav_head(len(result), header)
f.write(header)
f.write(result)
f.close()
else:
raise Exception("tts fail, %s" % str(result))
return
###ONLY for pcm, 8000 sample, 16bits, 1 channel
def pcm_wav_head(data_len, header = ''):
header = b'RIFF' #WAVE DES, 4
header += pack('I', (data_len + 36)) #wav chunk len, 4
header += b'WAVE' # WAVE, 4
header += b'fmt ' #fmt , 4
header += pack('I', 16) #PCM fmt info len, 4
header += pack('H', 1) #fmt type PCM 0x0001, 2
header += pack('H', 1) #1 channel, 2
header += pack('I', 8000) #sample 8000, 4
header += pack('I', int(1 * 8000 * 16 / 8)) #bytes per second, 4
header += pack('H', int(1 * 16 / 8)) #sampling frame size, 2
header += pack('H', 16) #bit depth, 2
header += b'data' #data
header += pack('I', data_len) #data len
return header
if __name__ == "__main__":
content = '123456'
filename = r'C:\Users\12345\Desktop\101.wav'
tts_baidu(content, filename)
测试
发送tts请求,根据返回结果写wav文件,wav文件用UE打开,见截图。
截图中,我们可以看到几个数据段的标识,“RIFF“,”WAVEfmt “,”data“。
总结
简单复习了一下wav格式的头部信息,更加复杂的编解码和压缩格式头部信息也都可以在网上找到详细的描述。
wav是一个封装格式,封包的信息都在wav头中。
pcm编码格式是不压缩的语音编码格式,封装pcm数据的wav文件格式相对简单,对于理解音频文件的打包封装有一定帮助。
空空如常
求真得真