百度语音合成-官方提供key
百度语音合成(官方提供key)
将文本转换为可以播放的音频文件。
合成的文件格式为 mp3,pcm(8k及16k),wav(16k),具体见aue参数。
# coding=utf-8
import sys
import json
import os
import time
IS_PY3 = sys.version_info.major == 3
if IS_PY3:
from urllib.request import urlopen
from urllib.request import Request
from urllib.error import URLError
from urllib.parse import urlencode
from urllib.parse import quote_plus
# else:
# import urllib2
# from urllib import quote_plus
# from urllib2 import urlopen
# from urllib2 import Request
# from urllib2 import URLError
# from urllib import urlencode
class DemoError(Exception):
pass
class VoiceMerge():
def __init__(self, apiKey='4E1BG9lTnlSeIf1NQFlrSq6h', secretKey='544ca4657ba8002e3dea3ac2f5fdd241'):
# 本文件中的 apiKey,secretKey 是百度官网示例提供的(可用)
self.API_KEY = apiKey
self.SECRET_KEY = secretKey
def voiceMerge(self, text='', outFilePath='', per=1, spd=5, pit=5, vol=5, aue=3, cuid='', scope='audio_tts_post'):
'''
:param text: 需要转换为语音的文本内容
:param outFilePath: 输出文件路径
:param per: 发音人,0-普通女声,1-普通男生,3-情感合成-度逍遥,4-情感合成-度丫丫,默认为 0.
:param spd: 语速,取值0-15,默认为5中语速
:param pit: 音调,取值0-15,默认为5中语调
:param vol: 音量,取值0-9,默认为5中音量
:param aue: 下载的文件格式, 3 - mp3(default),4 - pcm-16k,5 - pcm-8k,6 - wav
:param cuid: 用户唯一标识,用来区分用户,填写机器 MAC 地址或 IMEI 码,长度为60以内
:param scope: 有此scope表示有tts能力,没有请在网页里勾选
:return:
注意文件名称与 aue 要相匹配
'''
TTS_URL = 'http://tsn.baidu.com/text2audio'
FORMATS = {3: "mp3", 4: "pcm", 5: "pcm", 6: "wav"}
format = FORMATS[aue]
cuid = str(cuid) if cuid else f"{int(time.time()*1000)}"
token = self.getToken(scope)
tex = quote_plus(text) # 此处 text 需要两次 urlencode
print(tex)
params = {'tok': token, 'tex': tex, 'per': per, 'spd': spd, 'pit': pit, 'vol': vol, 'aue': aue, 'cuid': cuid,
'lan': 'zh', 'ctp': 1} # lan ctp 固定参数
data = urlencode(params)
print('test on Web Browser' + TTS_URL + '?' + data)
req = Request(TTS_URL, data.encode('utf-8'))
has_error = False
try:
f = urlopen(req)
result_str = f.read()
headers = dict((name.lower(), value) for name, value in f.headers.items())
has_error = ('content-type' not in headers.keys() or headers['content-type'].find('audio/') < 0)
except URLError as err:
print('asr http response http code : ' + str(err.code))
result_str = err.read()
has_error = True
# save_file = "error.txt" if has_error else f'result_{per}_{spd}.' + format
flt = outFilePath.split('.')
save_file = f"{flt[0]}_error.txt" if has_error else f'{outFilePath}'
with open(save_file, 'wb') as of:
of.write(result_str)
if has_error:
if (IS_PY3):
result_str = str(result_str, 'utf-8')
print("tts api error:" + result_str)
print("result saved as :" + save_file)
def getToken(self, scope):
TOKEN_URL = 'http://openapi.baidu.com/oauth/2.0/token'
print("fetch token begin")
params = {'grant_type': 'client_credentials',
'client_id': self.API_KEY,
'client_secret': self.SECRET_KEY}
post_data = urlencode(params)
if (IS_PY3):
post_data = post_data.encode('utf-8')
req = Request(TOKEN_URL, post_data)
try:
f = urlopen(req, timeout=5)
result_str = f.read()
except URLError as err:
print('token http response http code : ' + str(err.code))
result_str = err.read()
if (IS_PY3):
result_str = result_str.decode()
print(result_str)
result = json.loads(result_str)
print(result)
if ('access_token' in result.keys() and 'scope' in result.keys()):
if not scope in result['scope'].split(' '):
raise DemoError('scope is not correct')
print('SUCCESS WITH TOKEN: %s ; EXPIRES IN SECONDS: %s' % (result['access_token'], result['expires_in']))
return result['access_token']
else:
raise DemoError('MAYBE API_KEY or SECRET_KEY not correct: access_token or scope not found in token response')
if __name__ == '__main__':
text = "像是加以人工似的,一丈以内绝无旁枝,这就是白杨树!"
rpath = os.getcwd()
outFilePath = os.path.join(rpath, 'fdir', 'test3.mp3')
vm = VoiceMerge()
vm.voiceMerge(text=text, outFilePath=outFilePath)