【实战】基于TFlite实现TensorFlowTTS语音合成
源码地址:https://github.com/TensorSpeech/TensorFlowTTS
一、配置环境
Requirements:
- Python 3.7+
- Tensorflow 2.2/2.3/2.4/2.5/2.6
二、案例实现
1、将源码下载并解压在TensorFlowTTS-master路径下
2、下载所需要的模型和lib静态库:
下载路径:https://github.com/luan78zaoha/TTS_tflite_cpp/releases/tag/0.1.0
下载以上两个文件,并解压
3、将lib.zip、models.zip解压并放在TensorFlowTTS-master/examples/cpptflite路径下:
4、输入以下指令,编译中文的语音合成可执行文件
cd example/cpptflite
mkdir build && cd build
// 编译中文的可执行文件
cmake .. -DMAPPER=BAKER
make
// 若想编译英文的可执行文件
cmake .. -DMAPPER=LJSPEECH
make
5、运行可执行文件
./demo "这是一个开源的端到端语音合成项目" test.wav
出现以上信息,说明已经成功生成合成的音频文件test.wav;
6、在合成语音中加入停顿
下图表示我们未加停顿前音频的频谱图:
从图中可以看出,中间的停顿几乎没有,会使人的听感产生疲劳;
使用#3生成带有停顿的音频:
./demo "这是一个开源的#3端到端#3语音合成项目" test.wav
由频谱图可以清楚的看出,加入停顿后有明显的的间隔,音频也相对人性化一些;
三、代码解读
main.cpp:
int main(int argc, char* argv[])
{
if (argc != 3)
{
fprintf(stderr, "demo text wavfile\n");
return 1;
}
const char* cmd = "python3 ../demo/text2ids.py"; // 执行python命令,其中是将文本转换成音律
Processor proc;
#if LJSPEECH
proc.mapperJson = "../../../tensorflow_tts/processor/pretrained/ljspeech_mapper.json";
proc.sampleRate = 22050;
#elif BAKER
proc.mapperJson = "../../../tensorflow_tts/processor/pretrained/baker_mapper.json";
proc.sampleRate = 24000;
#endif
// 加载模型
const char* melgenfile = "../models/fastspeech2_quan.tflite";
const char* vocoderfile = "../models/mb_melgan.tflite";
// Init
TTSFrontend ttsfrontend(proc.mapperJson, cmd);
TTSBackend ttsbackend(melgenfile, vocoderfile);
// Process
ttsfrontend.text2ids(argv[1]); // 输入文本,输出分割的音素
std::vector<int32_t> phonesIds = ttsfrontend.getPhoneIds(); // 获取包含音素的容器
ttsbackend.inference(phonesIds); // 输入音素容器,输出梅尔频谱、音频波形
MelGenData mel = ttsbackend.getMel(); // 获取梅尔频谱
std::vector<float> audio = ttsbackend.getAudio(); // 获取音频波形
std::cout << "********* Phones' ID *********" << std::endl; // 打印每个音素的韵律
for (auto iter: phonesIds)
{
std::cout << iter << " ";
}
std::cout << std::endl;
std::cout << "********* MEL SHAPE **********" << std::endl; // 打印梅尔频谱的shape
for (auto index : mel.melShape)
{
std::cout << index << " ";
}
std::cout << std::endl;
std::cout << "********* AUDIO LEN **********" << std::endl;
std::cout << audio.size() << std::endl;
VoxUtil::ExportWAV(argv[2], audio, proc.sampleRate);
std::cout << "Wavfile: " << argv[2] << " creats." << std::endl;
return 0;
}
前端处理分为以下几步:
文本转拼音——拼音转韵律——韵律通过map生成id
大家好——[‘da4’,‘jia1’,‘hao3’]——{d a4 j ia1 h ao3}——[151, 174, 155, 226, 154, 193]
具体代码实现可以看py脚本处理部分;
四、总结
-
该项目不涉及训练部分,对于声学模型以及声码器部分没有过多的涉及,详情可以看相关的训练代码;
-
该项目可以实现在安卓和一些开发板上的部署,目前只在服务器上跑通,部署的话还需要用c++重写python的预处理代码;
-
目前采用提供的预训练模型进行推理,可用自己的数据集进行训练,并得到适用于自己场景下的模型;