批量文字转语音 tts工具

功能

之前想获得一段机器配音时,总是一句一句粘贴在翻译软件上读取,非常麻烦。 后来知道百度AI提供了免费的语音合成api,所以简单分享下使用方法。

使用说明

百度智能云语音识别

  • 首先打开上述网址点击立即开始注册或登录账号

  • 创建一个应用并按照你的需求注册,当然不只是语音识别还有其他类似人脸识别图像处理等接口,但是大部分是要收费的。具体其他业务可以看看官方指南在这里插入图片描述

  • 这些我们可以不管,只需要注册语音识别应用,文本转语音业务包含在其中。注册好可以如下图领取免费额度。 在这里插入图片描述

  • 最后配置完成后,下载python的sdk来安装,使用python setup.py install

其他组件

所有组件github地址: 百度AI python sdk地址. 其它功能也可类似调用接口实现,这里只是简单使用语音识别的文本语音转换功能。

文本转语音测试

参考了官方的测试案例编写了下面的代码,有兴趣的可以试试其他api的调用,此代码python2 3皆可使用。

# coding: utf-8
# 逐行读入source/test.txt文件,并创建audio1.mp3 audio2.mp3 audio3.mp3存入source文件夹中 ......
import sys
import json

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

API_KEY = '此处替换为你应用的API_KEY '
SECRET_KEY = '此处替换为你应用的SECRET_KEY'
TEXT = "欢迎使用百度语音合成。"

# 发音人选择,默认为度小美 
# 基础音库:0为度小美,1为度小宇,3为度逍遥,4为度丫丫,
# 精品音库:5为度小娇,103为度米朵,106为度博文,110为度小童,111为度小萌
PER = 3
# 语速,取值0-15,默认为5中语速
SPD = 6
# 音调,取值0-15,默认为5中语调
PIT = 5
# 音量,取值0-9,默认为5中音量
VOL = 7
# 下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
AUE = 3

FORMATS = {3: ".mp3", 4: ".pcm", 5: ".pcm", 6: ".wav"}
FORMAT = FORMATS[AUE]

CUID = "123456PYTHON"
TTS_URL = 'http://tsn.baidu.com/text2audio'

class DemoError(Exception):
    pass


"""  TOKEN start """
TOKEN_URL = 'http://openapi.baidu.com/oauth/2.0/token'
SCOPE = 'audio_tts_post'  # 有此scope表示有tts能力,没有请在网页里勾选

def fetch_token():
    print("fetch token begin")
    params = {'grant_type': 'client_credentials',
              'client_id': API_KEY,
              'client_secret': 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')
"""  TOKEN end """

def tts(str, id):
    # tex = quote_plus(TEXT) 
    tex = quote_plus(text[i])  # 此处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 "./source/result" + id + FORMAT    #三目运算符
    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)


if __name__ == '__main__':
    token = fetch_token()
    text = []
    file = open("./source/test.txt", 'r', encoding='UTF-8')
    while True:
        lines = file.readlines(100000)
        if not lines:
            break
        for line in lines:
            text.append(line)
    for i in range(len(text)):
        tts(text[i], str(i+1))