Last active
November 3, 2021 01:20
-
-
Save hzbd/72f0a77402f1fa57ef6cf970a7ceb946 to your computer and use it in GitHub Desktop.
aliyun speech synthesis service demo. 阿里云语音合成服务演示
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding:utf-8 -*- | |
# | |
# Copyright (c) 2021 623 MIT | |
# | |
from urllib import parse | |
import logging | |
import os | |
import time | |
import uuid | |
import requests | |
import base64 | |
import hashlib | |
import hmac | |
import requests | |
import time | |
import uuid | |
logger = logging.getLogger(__name__) | |
ACCESS_KEY_ID ="" | |
ACCESS_SECRET ="" | |
class AliyunSig(object): | |
""" | |
REF doc: | |
https://help.aliyun.com/document_detail/94737.html | |
https://help.aliyun.com/document_detail/113251.html#h2-u7B7Eu540Du673Au52362 | |
Tips: | |
* synthesizing within 300 characters at a time for free. | |
""" | |
def __init__(self, | |
access_key=os.environ.get('ACCESS_KEY_ID', ACCESS_KEY_ID), | |
access_secret=os.environ.get('ACCESS_SECRET', ACCESS_SECRET)): | |
self.requests = requests.Session() | |
self.access_key = access_key | |
self.access_secret = access_secret | |
@staticmethod | |
def _encode_text(text): | |
encoded_text = parse.quote_plus(text) | |
return encoded_text.replace('+', '%20').replace('*', '%2A').replace('%7E', '~') | |
@staticmethod | |
def _encode_dict(dic): | |
keys = dic.keys() | |
dic_sorted = [(key, dic[key]) for key in sorted(keys)] | |
encoded_text = parse.urlencode(dic_sorted) | |
return encoded_text.replace('+', '%20').replace('*', '%2A').replace('%7E', '~') | |
def gen_token(self): | |
parameters = { | |
'AccessKeyId': self.access_key, | |
'Action': 'CreateToken', | |
'Format': 'JSON', | |
'RegionId': 'cn-shanghai', | |
'SignatureMethod': 'HMAC-SHA1', | |
'SignatureNonce': str(uuid.uuid1()), | |
'SignatureVersion': '1.0', | |
'Timestamp': time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), | |
'Version': '2019-02-28' | |
} | |
query_string = AliyunSig._encode_dict(parameters) | |
string_to_sign = 'GET' + '&' + \ | |
AliyunSig._encode_text('/') + '&' + AliyunSig._encode_text(query_string) | |
secreted_string = hmac.new(bytes(self.access_secret + '&', encoding='utf-8'), | |
bytes(string_to_sign, encoding='utf-8'), hashlib.sha1).digest() | |
signature = base64.b64encode(secreted_string) | |
signature = AliyunSig._encode_text(signature) | |
full_url = 'https://nls-meta.cn-shanghai.aliyuncs.com/?Signature=%s&%s' % ( | |
signature, query_string) | |
response = self.requests.get(full_url) | |
if response.ok: | |
root_obj = response.json() | |
key = 'Token' | |
if key in root_obj: | |
token = root_obj[key]['Id'] | |
expire_time = root_obj[key]['ExpireTime'] | |
return token, expire_time | |
logger.info(response.text) | |
return None, None | |
def gen_speech(self, appkey, text_words, sample_rate=16000, | |
voice="xiaoyun", volume=86, speech_rate=-357, format="wav"): | |
""" | |
Parameter list: | |
name type optional description | |
appkey String y 项目appkey。 | |
text String y 待合成的文本,需要为UTF-8编码。使用GET方法,需要再采用RFC 3986规范进行urlencode编码;使用POST方法不需要urlencode编码。 | |
token String n 若不设置token参数,需要在HTTP Headers中设置X-NLS-Token字段来指定Token。 | |
format String n 音频编码格式,支持pcm/wav/mp3格式。默认值:pcm。 | |
sample_rate Integer n 音频采样率,支持16000Hz/8000Hz,默认值:16000Hz。 | |
voice String n 发音人,默认值:xiaoyun。更多发音人请参见接口说明。 | |
volume Integer n 音量,取值范围:0~100,默认值:50。 | |
speech_rate Integer n 语速,取值范围:-500~500,默认值:0。 | |
pitch_rate Integer n 语调,取值范围:-500~500,默认值:0。 | |
""" | |
token, _ = self.gen_token() | |
headers = {'Content-type': 'application/json'} | |
payload = { | |
"appkey": appkey, | |
"text": text_words, | |
"sample_rate": sample_rate, | |
"voice": voice, | |
"volume": volume, | |
"speech_rate": speech_rate, | |
"token": token, | |
"format": format | |
} | |
# print(payload) | |
url = "https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/tts" | |
response = self.requests.post(url, json=payload, headers=headers) | |
return response | |
if __name__ == '__main__': | |
# token, expire_time = AliyunSig().gen_token() | |
# logger.info('token: %s, expire time(s): %s' % (token, expire_time)) | |
app_key = "<APPKEY-HERE>" | |
text_words = "你好啊,世界" | |
resp = AliyunSig().gen_speech(app_key, text_words) | |
audio_file = "/tmp/demo.wav" | |
if "audio/mpeg" == resp.headers['Content-Type']: | |
with open(audio_file, 'wb') as f: | |
f.write(resp.content) | |
else: | |
print(resp.content) | |
logger.warn("error message: {}".format(resp.content)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment