Skip to content
This repository has been archived by the owner on Apr 13, 2018. It is now read-only.

Commit

Permalink
增加阿里云语音合成模块 (#35)
Browse files Browse the repository at this point in the history
* 增加阿里云语音识别

profile配置信息:

tts_engine: ali-tts

#阿里云语音
ali_yuyin:
ak_id: ''
ak_secret: ''
voice_name: 'xiaoyun' #xiaoyun为女生,xiaogang为男生

另附上讯飞语音合成的发音人配置:
将iflytek_yuyin里的vid编号替换成下文所附编号可更换发音人
建议先去配音配音阁 http://www.peiyinge.com/anchor?speakerType=1 测试后再进行更换

附文:
中文主播
65070 //小俊
65090 //彬哥
65080 //程程
65320 //小薛
65040 //小英
65010 //小洋
65110 //小光
65340 //小南
64010 //坤叔
65360 //瑶瑶
15675 //小宇
60100 //小媛
62020 //小芳
62060 //百合仙子
65310 //飞飞
62070 //韦香主
60150 //老马
65250 //大灰狼
62010 //小华
65270 //原野

特色语音合成
67230 //葛二爷
60170 //萌小新
60120 //小桃丸
67100 //颖儿

方言主播
68060 //小蓉
10003 //小梅
68030 //小坤
68010 //小强
68040 //晓倩
68120 //玉儿
68080 //小莹

英文主播
69055 //Mr.奥
69020 //凯瑟琳
69010 //John
69030 //Steve

童声主播
60130 //楠楠

* 增加阿里云语音识别

profile配置信息:

tts_engine: ali-tts

#阿里云语音
ali_yuyin:
ak_id: ''
ak_secret: ''
voice_name: 'xiaoyun' #xiaoyun为女生,xiaogang为男生

另附上讯飞语音合成的发音人配置:
将iflytek_yuyin里的vid编号替换成下文所附编号可更换发音人
建议先去配音配音阁 http://www.peiyinge.com/anchor?speakerType=1 测试后再进行更换

附文:
中文主播
65070 //小俊
65090 //彬哥
65080 //程程
65320 //小薛
65040 //小英
65010 //小洋
65110 //小光
65340 //小南
64010 //坤叔
65360 //瑶瑶
15675 //小宇
60100 //小媛
62020 //小芳
62060 //百合仙子
65310 //飞飞
62070 //韦香主
60150 //老马
65250 //大灰狼
62010 //小华
65270 //原野

特色语音合成
67230 //葛二爷
60170 //萌小新
60120 //小桃丸
67100 //颖儿

方言主播
68060 //小蓉
10003 //小梅
68030 //小坤
68010 //小强
68040 //晓倩
68120 //玉儿
68080 //小莹

英文主播
69055 //Mr.奥
69020 //凯瑟琳
69010 //John
69030 //Steve

童声主播
60130 //楠楠

* Update tts.py

* Update tts.py

* Update tts.py

* Update tts.py

* Update tts.py
  • Loading branch information
musistudio authored and wzpan committed Sep 12, 2017
1 parent 3a3af05 commit 8a7e7f6
Showing 1 changed file with 106 additions and 1 deletion.
107 changes: 106 additions & 1 deletion client/tts.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
import logging
import urllib
import requests
import datetime
import base64
import hmac
import hashlib
from abc import ABCMeta, abstractmethod
from uuid import getnode as get_mac

Expand Down Expand Up @@ -533,7 +537,7 @@ def __init__(self, vid='60170'):
def get_config(cls):
# FIXME: Replace this as soon as we have a config module
config = {}
# Try to get baidu_yuyin config from config
# Try to get iflytek_yuyin config from config
profile_path = dingdangpath.config('profile.yml')
if os.path.exists(profile_path):
with open(profile_path, 'r') as f:
Expand Down Expand Up @@ -580,6 +584,107 @@ def say(self, phrase):
os.remove(tmpfile)


class ALiBaBaTTS(AbstractMp3TTSEngine):
"""
使用阿里云的语音合成技术
要使用本模块, 请先在 profile.xml 中启用本模块并选择合适的发音人.
"""

SLUG = "ali-tts"

def __init__(self, ak_id, ak_secret, voice_name='xiaoyun'):
self._logger = logging.getLogger(__name__)
self.ak_id = ak_id
self.ak_secret = ak_secret
self.voice_name = voice_name

@classmethod
def get_config(cls):
# FIXME: Replace this as soon as we have a config module
config = {}
# Try to get ali_yuyin config from config
profile_path = dingdangpath.config('profile.yml')
if os.path.exists(profile_path):
with open(profile_path, 'r') as f:
profile = yaml.safe_load(f)
if 'ali_yuyin' in profile:
if 'ak_id' in profile['ali_yuyin']:
config['ak_id'] = \
profile['ali_yuyin']['ak_id']
if 'ak_secret' in profile['ali_yuyin']:
config['ak_secret'] = \
profile['ali_yuyin']['ak_secret']
if 'voice_name' in profile['ali_yuyin']:
config['voice_name'] = \
profile['ali_yuyin']['voice_name']
return config

@classmethod
def is_available(cls):
return diagnose.check_network_connection()

def split_sentences(self, text):
punctuations = ['.', '。', ';', ';', '\n']
for i in punctuations:
text = text.replace(i, '@@@')
return text.split('@@@')

def get_current_date(self):
date = datetime.datetime.strftime(datetime.datetime.utcnow(),
"%a, %d %b %Y %H: %M: %S GMT")
return date

def to_md5_base64(self, strBody):
hash = hashlib.md5()
hash.update(strBody)
return hash.digest().encode('base64').strip()

def to_sha1_base64(self, stringToSign, secret):
hmacsha1 = hmac.new(secret, stringToSign, hashlib.sha1)
return base64.b64encode(hmacsha1.digest())

def get_speech(self, phrase):
options = {
'url': 'http://nlsapi.aliyun.com/speak?encode_type=' +
'mp3&voice_name=' + self.voice_name + '&volume=50',
'method': 'POST',
'body': phrase.encode('utf8'),
}
headers = {
'date': self.get_current_date(),
'content-type': 'text/plain',
'authorization': '',
'accept': 'audio/wav, application/json'
}

body = ''
if 'body' in options:
body = options['body']

bodymd5 = ''
if not body == '':
bodymd5 = self.to_md5_base64(body)

stringToSign = options['method'] + '\n' + headers['accept'] + '\n' + \
bodymd5 + '\n' + headers['content-type'] + '\n' + headers['date']
signature = self.to_sha1_base64(stringToSign, self.ak_secret)
authHeader = 'Dataplus ' + self.ak_id + ':' + signature
headers['authorization'] = authHeader
url = options['url']
r = requests.post(url, data=body, headers=headers, verify=False)
with tempfile.NamedTemporaryFile(suffix='.mp3', delete=False) as f:
f.write(r.content)
tmpfile = f.name
return tmpfile

def say(self, phrase):
self._logger.debug(u"Saying '%s' with '%s'", phrase, self.SLUG)
tmpfile = self.get_speech(phrase)
if tmpfile is not None:
self.play_mp3(tmpfile)
os.remove(tmpfile)


def get_default_engine_slug():
return 'osx-tts' if platform.system().lower() == 'darwin' else 'espeak-tts'

Expand Down

0 comments on commit 8a7e7f6

Please # to comment.