Microsoft Azure——文本转语音(TTS) REST API 使用教程

最近的工作需要用到文本转语音(Text-to-Speech, TTS),故简单地研究了现有的技术,在此与大家分享。

微软、谷歌、科大讯飞都发布了TTS的相关工具。微软在Azure上,开放了API和SDK(https://azure.microsoft.com/zh-cn/services/cognitive-services/text-to-speech/),下面将着重介绍API如何使用。谷歌同样发布了TTS产品(https://cloud.google.com/text-to-speech/,需要“科学上网”方能访问),其属于Google Cloud的一部分,所以想要免费体验或购买,都需要注册Google Cloud。而注册时,一定要绑定一张Visa或万事达信用卡才能成功完成,对于国内用户,这是极不友好的。科大讯飞的产品(https://www.xfyun.cn/doccenter/tts)在语音界有很大的名声,尤其是汉语、方言的生成,是讯飞的一大亮点。


Azure上,语音部分的文档写的较为详细,包含各种功能,如TTS API,TTS SDK,自定义语音模型进行文本转语音等。但是没有整体的、提纲挈领般的介绍,看完文档极有可能仍然不知如何下手。本文将一步步地介绍,如何从0开始使用Azure TTS API(以后有时间,再补充SDK的使用方法)。我们希望实现的效果是,输入一段文本,调用API后,返回给我们一段wav格式的音频,播放后,即为之前输入的文本。

  • Step1:注册Microsoft Azure账号

首先进入https://azure.microsoft.com/zh-cn/services/cognitive-services/text-to-speech/。如下图所示,点击“试用 文本到语音转换”,试用或者注册Azure。

Microsoft Azure——文本转语音(TTS) REST API 使用教程_第1张图片

 

  • Step2:得到终结点和密钥

注册完成后,在https://azure.microsoft.com/zh-cn/try/cognitive-services/?api=speech-services,添加“语音服务”功能后,会自动收到如下图的终结点和密钥。

Microsoft Azure——文本转语音(TTS) REST API 使用教程_第2张图片

  • Step3:下载示例代码

调用API是通过以下方式:本地程序发送HTTP请求(包含需要转换的文本)至微软服务器,经过身份验证后,服务器返回转换后的音频至本地。调用的程序可以在GitHub上下载:https://github.com/Azure-Samples/Cognitive-Speech-TTS。Samples-Http文件夹下有各种语言如Android, C#, Java, Node.js, PHP, Python,Ruby等的源码。此处以Python版(Python3)为例,接着介绍。

打开Python文件夹后,有两个文件:TTSSample.py和README。该py文件还不能直接运行,需做小小的修改(如何修改,下面再说。文末会附上修改后的源码)。修改后,运行该文件,程序会自动完成上一段叙述的所有操作,并把返回的结果存储在“data”中。

TTSSample.py文件需要做如下的修改(可参看README):

(1)apiKey = "Your api key goes here",把引号中的内容替换为STEP2图片中的密钥1或者密钥2。

(2)检查代码中终结点是否与STEP2图片中的终结点相同。比如程序中的AccessTokenHost = "westus.api.cognitive.microsoft.com",其中的“westus”就是终结点。再查看您账户中申请时分配的终结点名称,如STEP2图中的“westus”。若二者一致,则跳至下一步;若不一致,需要修改(只修改代码中的“westus”就行,“.api.com.......”不需要修改)。

同理,程序中“conn = http.client.HTTPSConnection("westus.tts.speech.microsoft.com")”做同样的修改。若您的终结点不是westus,则把程序中的westus替换为您的终结点名称。

终结点有3个:

美国西部 https://westus.tts.speech.microsoft.com/cognitiveservices/v1
东亚 https://eastasia.tts.speech.microsoft.com/cognitiveservices/v1
北欧 https://northeurope.tts.speech.microsoft.com/cognitiveservices/v1

这一条若不理解,可参看https://docs.microsoft.com/zh-cn/azure/cognitive-services/speech-service/how-to-text-to-speech。

(3)根据https://docs.microsoft.com/zh-cn/azure/cognitive-services/speech-service/rest-apis#authentication的说明,修改程序中X-Microsoft-OutputFormat和输出音频的属性(男声还是女声)。暂时输出音频只支持24khz的采样率。

(4)程序中的“voice.text”后的内容就是希望转成音频的文字内容,可以根据实际需求做修改。

(5)这时就能运行TTSSample.py。程序正常运行的返回值应该为"200 OK"。如果发生错误,则会有以下状态代码:

代码 Description 问题
400 错误的请求 必需参数缺失、为空或为 null。 或者,传递给必需参数或可选参数的值无效。 常见问题是标头太长。
401 未授权 请求未经授权。 请检查确保订阅密钥或令牌有效。
413 请求实体太大 SSML 输入超过了 1024 个字符。
502 错误的网关 网络或服务器端问题。 也可能表示标头无效。

假设前面的操作都没问题,也得到了200的返回值,那么转换后的音频在哪?答案是在程序的"data"这个变量中。"data"中的数据就是TTS转换后的音频,我们需要把它写为wav格式才能得到最终的音频。具体的操作见文末的代码。


附件:修改后的TTSSample.py文件(当然,您需要把apiKey修改为您的密钥;检查Python是否含有"wave"这个包),output.wav就是文本转换后的音频。

#! /usr/bin/env python3

# -*- coding: utf-8 -*-

###
#Copyright (c) Microsoft Corporation
#All rights reserved. 
#MIT License
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
###
import http.client, urllib.parse, json
from xml.etree import ElementTree
import wave
# Note: new unified SpeechService API key and issue token uri is per region
# New unified SpeechService key
# Free: https://azure.microsoft.com/en-us/try/cognitive-services/?api=speech-services
# Paid: https://go.microsoft.com/fwlink/?LinkId=872236
apiKey = "Your api key goes here"

params = ""
headers = {"Ocp-Apim-Subscription-Key": apiKey}

#AccessTokenUri = "https://westus.api.cognitive.microsoft.com/sts/v1.0/issueToken";
AccessTokenHost = "westus.api.cognitive.microsoft.com"
path = "/sts/v1.0/issueToken"

# Connect to server to get the Access Token
print ("Connect to server to get the Access Token")
conn = http.client.HTTPSConnection(AccessTokenHost)
conn.request("POST", path, params, headers)
response = conn.getresponse()
print(response.status, response.reason)

data = response.read()
conn.close()

accesstoken = data.decode("UTF-8")
print ("Access Token: " + accesstoken)

body = ElementTree.Element('speak', version='1.0')
body.set('{http://www.w3.org/XML/1998/namespace}lang', 'en-us')
voice = ElementTree.SubElement(body, 'voice')
voice.set('{http://www.w3.org/XML/1998/namespace}lang', 'en-US')
voice.set('{http://www.w3.org/XML/1998/namespace}gender', 'Male')
voice.set('name', 'Microsoft Server Speech Text to Speech Voice (en-US, Guy24KRUS)')
voice.text = 'This is a demo to call microsoft text to speech service in Python.'

headers = {"Content-type": "application/ssml+xml", 
			"X-Microsoft-OutputFormat": "riff-24khz-16bit-mono-pcm",
			"Authorization": "Bearer " + accesstoken, 
			"X-Search-AppId": "07D3234E49CE426DAA29772419F436CA", 
			"X-Search-ClientID": "1ECFAE91408841A480F00935DC390960", 
			"User-Agent": "TTSForPython"}
			
#Connect to server to synthesize the wave
print ("\nConnect to server to synthesize the wave")
conn = http.client.HTTPSConnection("westus.tts.speech.microsoft.com")
conn.request("POST", "/cognitiveservices/v1", ElementTree.tostring(body), headers)
response = conn.getresponse()
print(response.status, response.reason)

data = response.read()
conn.close()
print("The synthesized wave length: %d" %(len(data)))

f = wave.open(r"output.wav", "wb")
f.setnchannels(1)#单声道
f.setframerate(24000)#采样率
f.setsampwidth(2)#sample width 2 bytes(16 bits)
f.writeframes(data)
f.close()

 

你可能感兴趣的:(Python基础,语音相关)