【PaddleSpeech进阶】语音合成-onnx模型使用

2023-11-04 08:59

本文主要是介绍【PaddleSpeech进阶】语音合成-onnx模型使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

很多同学对PaddleSpeech发布的语音合成onnx模型的使用比较感兴趣,这篇教程将教会你如何使用PaddleSpeech提供的语音合成预训练模型完成推理工作。

0. PaddleSpeech 介绍

🚀 PaddleSpeech 是 all-in-one 的语音算法工具箱,包含多种领先国际水平的语音算法与预训练模型。你可以从中选择各种语音处理工具以及预训练模型,支持语音识别,语音合成,声音分类,声纹识别,标点恢复,语音翻译等多种功能,PaddleSpeech Server模块可帮助用户快速在服务器上部署语音服务。PaddleSpeech团队发表的论文 An Easy-to-Use All-in-One Speech Toolkit 入选 NAACL2022 ,荣获 NAACL2022 Best Demo Award

喜欢的同学可以点个 ⭐️star⭐️ 支持我们,PaddleSpeech传送门:https://github.com/PaddlePaddle/PaddleSpeech

🎁 学习过程中你遇到任何问题,可以加入PaddleSpeech的交流群进行讨论。

 

1. 初步认识onnxruntime推理流程

使用onnxruntime推理PaddleSpeech提供的语音合成onnx模型只需要四个步骤:

  1. 文本前端
  2. 加载模型,创建Session
  3. 模型推理
  4. 音频保存

2. 配置PaddleSpeech开发环境

你可以通过PaddleSpeech的源码进行安装

In [ ]

# 安装PaddleSpeech
!git clone https://gitee.com/paddlepaddle/PaddleSpeech.git
%cd PaddleSpeech
!pip install pytest-runner
!pip install .

In [ ]

# aistudio会报错: paddlespeech 的 repo中存在失效软链接
# 执行下面这行命令!!
!find -L /home/aistudio -type l -delete

In [ ]

# 下载模型模型
%cd /home/aistudio/work
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_onnx_0.2.0.zip
!unzip fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip
!unzip mb_melgan_csmsc_onnx_0.2.0.zip

In [ ]


# 下载nltk数据包,如果项目中有就不用下载了
%cd /home/aistudio
!wget -P data https://paddlespeech.bj.bcebos.com/Parakeet/tools/nltk_data.tar.gz
!tar zxvf data/nltk_data.tar.gz

3. TTS文本前端

PaddleSpeech提供的文本前端可以帮助我们把中文文本转换成模型推理需要的音素序列

In [3]

phones_dict = "/home/aistudio/work/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/phone_id_map.txt"

In [ ]

from paddlespeech.t2s.frontend.zh_frontend import Frontendfrontend = Frontend(phone_vocab_path=phones_dict,tone_vocab_path=None)

In [ ]

text = "今天天气真的很不错,我想出去玩!"
input_ids = frontend.get_input_ids(text,merge_sentences=True, # 是否按符号拆分句子get_tone_ids=False)
input_ids = input_ids['phone_ids']
print(input_ids)

4. 加载模型,创建Onnxruntime Session

创建onnxruntime的session,用于推理

In [ ]

import onnxruntime as ort# 模型路径
onnx_am_encoder = "/home/aistudio/work/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/fastspeech2_csmsc_am_encoder_infer.onnx"
onnx_am_decoder = "/home/aistudio/work/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/fastspeech2_csmsc_am_decoder.onnx"
onnx_am_postnet = "/home/aistudio/work/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/fastspeech2_csmsc_am_postnet.onnx"
onnx_voc_melgan = "/home/aistudio/work/mb_melgan_csmsc_onnx_0.2.0/mb_melgan_csmsc.onnx"# 用CPU推理
providers = ['CPUExecutionProvider']# 配置ort session
sess_options = ort.SessionOptions()# 创建session
am_encoder_infer_sess = ort.InferenceSession(onnx_am_encoder, providers=providers, sess_options=sess_options)
am_decoder_sess = ort.InferenceSession(onnx_am_decoder, providers=providers, sess_options=sess_options)
am_postnet_sess = ort.InferenceSession(onnx_am_postnet, providers=providers, sess_options=sess_options)
voc_melgan_sess = ort.InferenceSession(onnx_voc_melgan, providers=providers, sess_options=sess_options)

5. 模型推理

In [7]

# 辅助函数 denorm, 训练过程中mel输出经过了norm,使用过程中需要进行denorm
import numpy as np
am_stat_path = r"/home/aistudio/work/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/speech_stats.npy"
am_mu, am_std = np.load(am_stat_path)

In [8]

from paddlespeech.server.utils.util import denorm
# 推理阶段封装
# 端到端合成:一次性把句子全部合成完毕
def inference(text):phone_ids = frontend.get_input_ids(text, merge_sentences=True, get_tone_ids=False)['phone_ids']orig_hs = am_encoder_infer_sess.run(None, input_feed={'text': phone_ids[0].numpy()})hs = orig_hs[0]am_decoder_output = am_decoder_sess.run( None, input_feed={'xs': hs})am_postnet_output = am_postnet_sess.run(None,input_feed={'xs': np.transpose(am_decoder_output[0], (0, 2, 1))})am_output_data = am_decoder_output + np.transpose(am_postnet_output[0], (0, 2, 1))normalized_mel = am_output_data[0][0]mel = denorm(normalized_mel, am_mu, am_std)wav = voc_melgan_sess.run(output_names=None, input_feed={'logmel': mel})[0]return wav

6. 音频保存

In [10]

# 保存为wav,播放体验
import soundfile as sf
import time
text = "欢迎使用飞桨语音合成系统,测试一下合成效果。"
t1 = time.time()
wav = inference(text)
print("合成耗时:", time.time() - t1)
sf.write("demo.wav", wav, samplerate=24000)
合成耗时: 6.246196746826172

In [11]

import IPython.display as dp
dp.Audio("demo.wav")
<IPython.lib.display.Audio object>

7. 流式语音合成

流式语音合成需要流式播放才能起到展示效果,思路上是把各个流程进行分片,然后再分块合成,播放器同时流式播放。

流式播放需要声卡支持,建议放到自己的笔记本上进行播放,aistudio 上不便于展示,只展示拼接在一起的结果,不进行流式播放展示

将 streaming_tts.py下载到本机,按上面的步骤下载好模型,安装好PaddleSpeech即可(注意nltk_data,下载速度较慢,建议按上面方式提前下载好)

需要安装 pyaudio

In [12]

# 配置流式参数
import math
from paddlespeech.server.utils.util import get_chunksvoc_block = 36
voc_pad = 14
am_block = 72
am_pad = 12
voc_upsample = 300def depadding(data, chunk_num, chunk_id, block, pad, upsample):""" Streaming inference removes the result of pad inference"""front_pad = min(chunk_id * block, pad)# first chunkif chunk_id == 0:data = data[:block * upsample]# last chunkelif chunk_id == chunk_num - 1:data = data[front_pad * upsample:]# middle chunkelse:data = data[front_pad * upsample:(front_pad + block) * upsample]return datadef inference_stream(text):input_ids = frontend.get_input_ids(text,merge_sentences=False,get_tone_ids=False)phone_ids = input_ids["phone_ids"]print(phone_ids)for i in range(len(phone_ids)):# 先分句# am voc_chunk_id = 0orig_hs = am_encoder_infer_sess.run(None, input_feed={'text': phone_ids[i].numpy()})orig_hs = orig_hs[0]# streaming voc chunk infomel_len = orig_hs.shape[1]voc_chunk_num = math.ceil(mel_len / voc_block)start = 0end = min(voc_block + voc_pad, mel_len)# streaming amhss = get_chunks(orig_hs, am_block, am_pad, "am")am_chunk_num = len(hss)for i, hs in enumerate(hss):am_decoder_output = am_decoder_sess.run(None, input_feed={'xs': hs})am_postnet_output = am_postnet_sess.run(None,input_feed={'xs': np.transpose(am_decoder_output[0], (0, 2, 1))})am_output_data = am_decoder_output + np.transpose(am_postnet_output[0], (0, 2, 1))normalized_mel = am_output_data[0][0]sub_mel = denorm(normalized_mel, am_mu, am_std)sub_mel = depadding(sub_mel, am_chunk_num, i,am_block, am_pad, 1)if i == 0:mel_streaming = sub_melelse:mel_streaming = np.concatenate((mel_streaming, sub_mel), axis=0)# streaming voc# 当流式AM推理的mel帧数大于流式voc推理的chunk size,开始进行流式voc 推理while (mel_streaming.shape[0] >= end andvoc_chunk_id < voc_chunk_num):voc_chunk = mel_streaming[start:end, :]sub_wav = voc_melgan_sess.run(output_names=None, input_feed={'logmel': voc_chunk})sub_wav = depadding(sub_wav[0], voc_chunk_num, voc_chunk_id,voc_block, voc_pad, voc_upsample)yield sub_wavvoc_chunk_id += 1start = max(0, voc_chunk_id * voc_block - voc_pad)end = min((voc_chunk_id + 1) * voc_block + voc_pad,mel_len)

In [13]

text = "欢迎使用飞桨语音合成系统,测试一下合成效果。"
wavs = []
t1 = time.time()
for sub_wav in inference_stream(text):print("响应时间:", time.time() - t1)t1 = time.time()wavs.append(sub_wav.flatten())
wav = np.concatenate(wavs)
print(wav.shape)
sf.write("demo_stream.wav",data=wav, samplerate=24000)
[Tensor(shape=[21], dtype=int64, place=Place(cpu), stop_gradient=True,[71 , 199, 126, 177, 115, 138, 69 , 46 , 151, 89 , 241, 120, 71 , 42 ,39 , 57 , 260, 75 , 182, 163, 179]), Tensor(shape=[16], dtype=int64, place=Place(cpu), stop_gradient=True,[38 , 44 , 177, 116, 73 , 260, 80 , 71 , 42 , 39 , 57 , 260, 99 , 70 ,232, 179])]
响应时间: 1.4043552875518799
响应时间: 1.4002647399902344
响应时间: 1.2040159702301025
响应时间: 0.8999142646789551
响应时间: 0.8972508907318115
响应时间: 1.100409746170044
响应时间: 0.19948339462280273
响应时间: 1.9018454551696777
响应时间: 1.303241491317749
响应时间: 0.9031462669372559
响应时间: 1.1989772319793701
响应时间: 0.7002658843994141
(110100,)

In [14]

dp.Audio("demo_stream.wav")
<IPython.lib.display.Audio object>

8. 总结

通过上面教程的学习,相信你已经熟练掌握了如何使用onnxruntime来推理PaddleSpeech提供的预训练onnx模型,希望本教程能对你有所帮助。

遇到问题,可以加入 PaddleSpeech 技术交流群,和 PaddleSpeech 的开发者们一起交流讨论。

 

这篇关于【PaddleSpeech进阶】语音合成-onnx模型使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/344681

相关文章

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

使用TomCat,service输出台出现乱码的解决

《使用TomCat,service输出台出现乱码的解决》本文介绍了解决Tomcat服务输出台中文乱码问题的两种方法,第一种方法是修改`logging.properties`文件中的`prefix`和`... 目录使用TomCat,service输出台出现乱码问题1解决方案问题2解决方案总结使用TomCat,

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

C++中使用vector存储并遍历数据的基本步骤

《C++中使用vector存储并遍历数据的基本步骤》C++标准模板库(STL)提供了多种容器类型,包括顺序容器、关联容器、无序关联容器和容器适配器,每种容器都有其特定的用途和特性,:本文主要介绍C... 目录(1)容器及简要描述‌php顺序容器‌‌关联容器‌‌无序关联容器‌(基于哈希表):‌容器适配器‌:(

使用Python实现高效的端口扫描器

《使用Python实现高效的端口扫描器》在网络安全领域,端口扫描是一项基本而重要的技能,通过端口扫描,可以发现目标主机上开放的服务和端口,这对于安全评估、渗透测试等有着不可忽视的作用,本文将介绍如何使... 目录1. 端口扫描的基本原理2. 使用python实现端口扫描2.1 安装必要的库2.2 编写端口扫

使用Python实现操作mongodb详解

《使用Python实现操作mongodb详解》这篇文章主要为大家详细介绍了使用Python实现操作mongodb的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、示例二、常用指令三、遇到的问题一、示例from pymongo import MongoClientf

SQL Server使用SELECT INTO实现表备份的代码示例

《SQLServer使用SELECTINTO实现表备份的代码示例》在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误,在SQLServer中,可以使用SELECTINT... 在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误。在 SQL Server 中,可以使用 SE

使用Python合并 Excel单元格指定行列或单元格范围

《使用Python合并Excel单元格指定行列或单元格范围》合并Excel单元格是Excel数据处理和表格设计中的一项常用操作,本文将介绍如何通过Python合并Excel中的指定行列或单... 目录python Excel库安装Python合并Excel 中的指定行Python合并Excel 中的指定列P

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可