网易首页 > 网易号 > 正文 申请入驻

基于python3实现Azure机器学习最接近人声的文本转语音功能

0
分享至

上期文章,我们介绍了如何使用Azure来创建一个语音服务API,哪里,我们得到了API的key,以及语音服务的基本信息,包含地区等,这些都是本期代码需要的参数

听了那么多AI合成的语音,Azure机器学习的文本转语音最接近人声

下图是Azure官方的一个语音合成流程图,大致包含如下步骤

  1. 准备需要合成语音的text文件或者SSML文件

  2. 向API发送请求

  3. API服务提供文本转语音功能(本步骤直接在Azure服务器上执行)

  4. 用户端检查服务状态,若提示为succeeded,说明服务完成(由于是长语言转换功能,服务器需要时间较长,程序可以循环判断目前的转换状态)

  5. 下载转换完成的语言

文本准备

对于文本的要求如下:

文件是纯文本文件 (.txt) 或 SSML 文本 (.txt)。

文件已编码为UTF-8 格式。

文件是单个文件,而不是 zip 文件。

文件包含 400 多个字符(对于纯文本),或 400 个可计费字符(对于 SSML 文本),并且少于 10,000 个段落。

对于纯文本,通过点击 Enter/Return 来分隔每个段落。

对于 SSML 文本,每个 SSML的每个部分都被视为一个段落。按不同段落分隔 SSML 部分。

——2——

获取支持的语音列表

由于不同的API服务会使用不同的地区与付费标准,Azure API 在进行访问之前,我们首先查看一下自己API对应的语音列表,我们后期需要合成的语音只能从语音列表中选取,否则API会返回错误信息


import json
import ntpath
import requests

input_file_path_text = 'input_text.txt'
TTS_voicename = "zh-CN-XiaoxiaoNeural"
TTS_KEY = 'your key'
TTS_region = 'eastus'
TTS_locale = "zh-CN"
#获取受支持语音列表
def get_voices():
region = TTS_region
key = TTS_KEY
url = 'https://{}.customvoice.api.speech.microsoft.com/api/texttospeech/v3.0/longaudiosynthesis/voices'.format(region)
header = {
'Ocp-Apim-Subscription-Key': key
}
response = requests.get(url, headers=header)
print(response.text)
get_voices()

首先我们加载第三方库,由于我已经运行过代码,因此这里定义了一些常量,方便后面的代码统一使用,这里需要配置自己的

TTS_voicename = "zh-CN-XiaoxiaoNeural" 合成语音的名称,这里我们通过以上代码便可以知道自己API支持的语音列表

TTS_KEY = 'your key' 这里替换成自己的API key

TTS_region = 'eastus' 这里替换成自己API语音资源的区域

TTS_locale = "zh-CN" 这里需要设置需要转换的源文本

脚本成功运行提示如下:


"values": [
"locale": "ko-KR",
"voiceName": "ko-KR-SunHiNeural",
"description": "{\"Version\":\"20211130133950\"}",
"gender": "Female",
"createdDateTime": "2021-11-30T15:12:34.717Z",
"properties": {
"publicAvailable": true
},
"locale": "de-DE",
"voiceName": "de-DE-KatjaNeural",
"description": "{\"Version\":\"20211130133950\"}",
"gender": "Female",
"createdDateTime": "2021-11-30T13:48:10.387Z",
"properties": {
"publicAvailable": true
},
"locale": "zh-CN",
"voiceName": "zh-CN-XiaoyouNeural",
"description": "{\"Version\":\"20211130133950\"}",
"gender": "Male",
"createdDateTime": "2021-11-30T16:55:21.760Z",
"properties": {
"publicAvailable": true

这里只截取了部分语音列表,详细的列表可以根据自己的API 进行代码的输出

如果
properties.publicAvailable 为 true,则是公共神经语音。否则,它是自定义神经语音。

——3——

将文本转换为语音

将文本转换为语音

def submit_synthesis():
region = TTS_region
key = TTS_KEY
input_file_path = input_file_path_text
locale = TTS_locale
url = 'https://{}.customvoice.api.speech.microsoft.com/api/texttospeech/v3.0/longaudiosynthesis'.format(region)
header = {
'Ocp-Apim-Subscription-Key': key

voice_identities = [
{
'voicename': TTS_voicename
}
]

payload = {
'displayname': 'long audio synthesis sample',
'description': 'sample description',
'locale': locale,
'voices': json.dumps(voice_identities),
'outputformat': 'riff-16khz-16bit-mono-pcm',
'concatenateresult': True,
}

filename = ntpath.basename(input_file_path)
files = {
'script': (filename, open(input_file_path, 'rb'), 'text/plain')
}

response = requests.post(url, payload, headers=header, files=files)
print('response.status_code: %d' % response.status_code)
print(response.headers['Location'])

submit_synthesis()

将 TTS_KEY 替换为语音服务API的自己key

将TTS_region 替换为创建语音资源的区域

将input_file_path_text 替换为准备进行文本转语音的文本文件的路径。

将 TTS_locale 替换为所需的输出区域设置。

通过第二步,我们已经得到了自己API所支持的语音list,这里选择自己的喜欢的语音名称,替换TTS_voicename

concatenateResult 是一个可选参数。如果未设置此参数,则将按段落生成音频输出。你还可以通过加入该参数,将音频连接成一个输出。

outputFormat 也是可选的。默认情况下,音频输出设置为 riff-16khz-16bit-mono-pcm,支持的语音输出格式如下

riff-8khz-16bit-mono-pcm
riff-16khz-16bit-mono-pcm
riff-24khz-16bit-mono-pcm
riff-48khz-16bit-mono-pcm
audio-16khz-32kbitrate-mono-mp3
audio-16khz-64kbitrate-mono-mp3
audio-16khz-128kbitrate-mono-mp3
audio-24khz-48kbitrate-mono-mp3
audio-24khz-96kbitrate-mono-mp3
audio-24khz-160kbitrate-mono-mp3

成功运行后,代码提示如下:

response.status_code: 202
https:///api/texttospeech/v3.0/longaudiosynthesis/

其中202 代表请求成功, print(response.headers['Location'])会输出一个URL,通过这个URL,我们可以访问此API合成语音的进度,参考下面第四步,uid 是我们第五步下载合成音频的参数

获取有关已提交请求的状态

通过第三步,我们已经成功提交了API请求,并API 返回了URL,通过此URL,我们来获取API的运行状态

获取有关已提交请求的详细信息

def get_synthesis():
url = URL
key = TTS_KEY
header = {
'Ocp-Apim-Subscription-Key': key
response = requests.get(url, headers=header)
print(response.text)

get_synthesis()
这里的URL 需要替换成第三步中代码返回的URL 链接
输出如下
{
"models": [
{
"voiceName": "zh-CN-XiaoxiaoNeural"
}
],
"properties": {
"outputFormat": "riff-16khz-16bit-mono-pcm",
"concatenateResult": true,
"totalDuration": "PT0S",
"billableCharacterCount": 0
},
"id": "7e3d9994-d319-44f3-9b35-02fe253a7643",
"lastActionDateTime": "2022-03-24T05:33:48.440Z",
"status": "Running",
"createdDateTime": "2022-03-24T05:28:50.267Z",
"locale": "zh-CN",
"displayName": "long audio synthesis sample",
"description": "sample description"
}

status 属性从 NotStarted 状态变更为 Running,最后变更为 Succeeded 或 Failed。可以使用循环轮询此 API,直到状态变为 Succeeded 或 Failed。最后Succeeded ,说明服务已经完成,我们就可以把合成的语音下载下来了

——5——

下载已经完成的语音服务

##下载音频结果
def get_files():
id = ID
region = TTS_region
key = TTS_KEY
url = 'https://{}.customvoice.api.speech.microsoft.com/api/texttospeech/v3.0/longaudiosynthesis/{}/files'.format(region, id)
header = {
'Ocp-Apim-Subscription-Key': key

response = requests.get(url, headers=header)
print('response.status_code: %d' % response.status_code)
print(response.text)

get_files()
这里的ID 需要替换成第三步中URL 最后的UID,输出如下
response.status_code: 200
{
"values": [
{
"name": "3e322b4a-0aed-49e3-874e-5066c12e15a2.txt",
"kind": "LongAudioSynthesisScript",
"properties": {
"size": 4668
},
"createdDateTime": "2022-03-24T05:28:50.190Z",
"links": {
"contentUrl": "https://cvoiceprodeus.blob.core.windows.net/bestor-c6e3ae79-1b48-41bf-92ff-940bea3e5c2d/VoiceSynthesisData/3e322b4a-0aed-49e3-874e-5066c12e15a2.txt?sv=2019-07-07&sr=b&sig=iGHOI1h%2BiCT%2Brb%2F3rDE1GH2FyOFK8ALr%2FkhoMuVxqDY%3D&st=2022-03-24T05:35:32Z&se=2022-03-24T17:40:32Z&sp=rl"
}
},
{
"name": "voicesynthesis_waves.zip",
"kind": "LongAudioSynthesisResult",
"properties": {
"size": 8877068
},
"createdDateTime": "2022-03-24T05:35:38.140Z",
"links": {
"contentUrl": "https://cvoiceprodeus.blob.core.windows.net/bestor-c6e3ae79-1b48-41bf-92ff-940bea3e5c2d/VoiceSynthesisData/8a8cb7b2-2fc6-4102-b57c-06d0cf0a7740?sv=2019-07-07&sr=b&sig=8SG%2BGAOx0UV2BslaI5xi5xEqZO%2BZ5IhPVPyd5lHVa1s%3D&st=2022-03-24T05:35:32Z&se=2022-03-24T17:40:32Z&sp=rl"
}
}
]
}

response.status_code: 200 说明成功

此示例输出包含两个文件的信息。包含 "kind": "LongAudioSynthesisScript" 文件是已提交的输入脚本。

包含 "kind": "LongAudioSynthesisResult" 的另一个文件是此请求的结果。

结果是 zip 文件,其中包含生成的音频输出文件,以及输入文本的副本。

可以从其 links.contentUrl 属性的 URL 中下载这两个文件。

得到2个链接后,直接输入到浏览器里面,会自动下载文件,当然也可以使用
urllib.request.urlretrieve(URL1, "123.txt"),第一个链接返回一个输入的源文本文件


urllib.request.urlretrieve(URL2, "123.zip"),第二个链接返回一个压缩包,里面有合成的wav的语音

——6——

REST API 中的 HTTP 响应代码和消息

下表详细介绍了 REST API 中的 HTTP 响应代码和消息。

API HTTP 状态代码 说明 解决方案

400 此区域未启用语音合成。 使用受支持区域更改语音订阅密钥。
400 只有此区域的标准语音订阅才有效。 将语音订阅密钥更改为“标准”定价层。
400 超过 Azure 帐户的 20,000 个请求限制。 在提交新请求之前需删除一些请求。 服务器将为每个 Azure 帐户最多保留 20,000 个请求。 请在提交新请求之前删除一些请求。
400 此模型不能用于语音合成:{modelID}。 请确保 {modelID} 的状态正确。
400 请求区域与模型区域不一致:{modelID}。 请确保 {modelID} 区域与请求区域匹配。
400 语音合成仅支持使用包含字节顺序标记的 UTF-8 编码中的文本文件。 请确保输入文件使用包含字节顺序标记的 UTF-8 编码。
400 语音合成请求中只允许有效的 SSML 输入。 请确保输入 SSML 表达式正确。
400 在输入文件中找不到语音名称 {voiceName}。 输入 SSML 语音名称与模型 ID 不对齐。
400 输入文件中的段落数应小于 10,000。 请确保文件中的段落数小于 10,000。
400 输入文件应超过 400 个字符。 请确保输入文件超过 400 个字符。
404 找不到语音合成定义中声明的模型:{modelID}。 请确保 {modelID} 正确。
429 超出活动语音合成限制。 请耐心等待,直至一些请求处理完成。 对于每个 Azure 帐户,服务器最多可以运行 120 个请求并将其排入队列。 请耐心等待,避免在某些请求处理完成之前提交新请求。
全部 429 请求太多。 对于每个 Azure 帐户,客户端每秒最多可以向服务器提交 5 个请求。 请减少每秒请求数量。
Delete 400 语音合成任务仍在使用中。 只能删除“已完成”或“已失败”的请求。
GetByID 404 找不到指定的实体。 请确保合成 ID 正确。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
越看越气!钟汉良新剧热度登顶,观众纷纷弃剧,痛斥三观炸裂

越看越气!钟汉良新剧热度登顶,观众纷纷弃剧,痛斥三观炸裂

一盅情怀
2026-04-14 13:56:41
《疯狂动物城2》付费仅限48小时内观看,视频平台回应

《疯狂动物城2》付费仅限48小时内观看,视频平台回应

大象新闻
2026-04-14 07:09:05
1500 万青年抢岗!大学生为了保留应届生的身份,宁愿去打零工也不找正式工作?

1500 万青年抢岗!大学生为了保留应届生的身份,宁愿去打零工也不找正式工作?

王姐懒人家常菜
2026-04-13 06:24:30
第一次直观感受到了基因的公平……

第一次直观感受到了基因的公平……

木子爱娱乐大号
2026-04-14 10:51:15
全红婵不再隐瞒!坦言身材发胖原因,原来高敏4年内提醒过2次

全红婵不再隐瞒!坦言身材发胖原因,原来高敏4年内提醒过2次

青橘罐头
2026-04-01 17:09:37
走马上任!马龙回归国乒亮相新岗位,樊振东弃赛原因曝光贬褒不一

走马上任!马龙回归国乒亮相新岗位,樊振东弃赛原因曝光贬褒不一

曹说体育
2026-04-15 16:31:04
印度首富小儿媳:弃帅模前男友,嫁300斤阿南特,如今成家族门面

印度首富小儿媳:弃帅模前男友,嫁300斤阿南特,如今成家族门面

照见古今
2026-04-12 19:32:51
建设方急用钱,他花85万元买5套“工抵房”,领钥匙装修时开发商称多支付工程款不给交房

建设方急用钱,他花85万元买5套“工抵房”,领钥匙装修时开发商称多支付工程款不给交房

大风新闻
2026-04-15 11:36:05
成都一电瓶车在高速逆行 LED屏实时预警引热议:大屏已经发展成这样了?

成都一电瓶车在高速逆行 LED屏实时预警引热议:大屏已经发展成这样了?

掌上金牛
2026-04-15 10:52:04
4月13日国务院放大招,乡镇卫生院终于不用再当“摆设”了

4月13日国务院放大招,乡镇卫生院终于不用再当“摆设”了

李博世财经
2026-04-14 10:02:08
CBA焦点战!15日19点35分!CCTV5+直播表,潘江力争季后赛资格

CBA焦点战!15日19点35分!CCTV5+直播表,潘江力争季后赛资格

米果说识
2026-04-15 17:05:48
1920年,一位俄罗斯医生突发奇想,把猴子的睾丸,植入到老头体内

1920年,一位俄罗斯医生突发奇想,把猴子的睾丸,植入到老头体内

岁月有情1314
2026-04-07 07:26:46
认罪不到24小时,许家印过往被扒,倒霉的3个女人只是冰山一角

认罪不到24小时,许家印过往被扒,倒霉的3个女人只是冰山一角

李橑在北漂
2026-04-15 11:17:14
西红柿立大功!医生研究发现:老人吃西红柿,或能缓解4种症状

西红柿立大功!医生研究发现:老人吃西红柿,或能缓解4种症状

医学原创故事会
2026-01-21 21:50:30
胡宗南明知熊向晖是中共卧底却不抓他,沈醉晚年回忆说出背后原因

胡宗南明知熊向晖是中共卧底却不抓他,沈醉晚年回忆说出背后原因

饭小妹说历史
2026-01-07 09:30:45
体坛名记批许家印:耻辱 恒大破坏中国足球媒体生态 重金收买记者

体坛名记批许家印:耻辱 恒大破坏中国足球媒体生态 重金收买记者

风过乡
2026-04-15 13:20:12
逐玉庆功宴曝咖位!张凌赫靠边站,业内大佬都到场,全给她让C位

逐玉庆功宴曝咖位!张凌赫靠边站,业内大佬都到场,全给她让C位

橙星文娱
2026-04-14 16:32:10
历史性突破!人民币首次跃居全球原油贸易第二大结算货币

历史性突破!人民币首次跃居全球原油贸易第二大结算货币

允华说
2026-04-15 10:35:42
美媒曝光东契奇伤病情况,雷迪克公开表态,詹姆斯恐难复刻2018年

美媒曝光东契奇伤病情况,雷迪克公开表态,詹姆斯恐难复刻2018年

鸣哥说体育
2026-04-15 17:15:43
夜袭阳明堡飞机场一战,我军共牺牲多少战士,击毁敌军多少飞机?

夜袭阳明堡飞机场一战,我军共牺牲多少战士,击毁敌军多少飞机?

云霄纪史观
2026-04-14 18:20:46
2026-04-15 19:23:00
人工智能研究所AI
人工智能研究所AI
python人工智能,大数据,人生苦短,我用python
153文章数 775关注度
往期回顾 全部

科技要闻

ChatGPT十亿用户又怎样?Anthropic直接贴脸

头条要闻

男生遭欺凌其父在调解室猝死 母亲:一家人都快抑郁了

头条要闻

男生遭欺凌其父在调解室猝死 母亲:一家人都快抑郁了

体育要闻

三球准绝杀戴大金链:轰30+10自我救赎

娱乐要闻

曾志伟办73岁生日派对,逾百艺人到场

财经要闻

业绩失速的Lululemon:"健康"人设崩塌?

汽车要闻

空间丝毫不用妥协 小鹏GX首发评测

态度原创

旅游
家居
本地
时尚
公开课

旅游要闻

德州黑板报丨春假带娃去哪玩?这些景区有活动

家居要闻

简而不减 暖居之道

本地新闻

12吨巧克力有难,全网化身超级侦探添乱

比性缘脑更可怕的东西,出现了

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版