使用商业TTS合成语音,再格式化,这样的录音没有爆破音、回音、底躁。
这里分享一个已经合成好的拼音集 baidu5003-sec-wav.tar.gz 百度网盘 请输入提取码,提取码:9f6f(下同),使用这个音调的拼音集可以跳过下述的 1~7 步直接执行第8、9步。如果要使用其他音调,需要执行 1~ 9步。
1、从 http://xh.5156edu.com
爬取拼音列表
htmlshell.jar - 使用jsoup编写的java组件包,见 htmlshell.jar(百度网盘 请输入提取码)
#!/bin/bash
pinyinfile=pinyin.txt
pinyinbase=http://xh.5156edu.com
pinyinurl=$pinyinbase/pinyi.html
pinyin=`java -jar htmlshell.jar $pinyinurl fontbox html out | awk -F '"' '{print "'"$pinyinbase/"'"$4}'`
echo -en > $pinyinfile
for url in $pinyin;
do
java -jar htmlshell.jar $url font_14 text | grep -v "未分类" >> $pinyinfile
done
爬取下来的拼音有1317个,其中有两组重复出现的拼音,即有效拼音为 1315 个。爬取的结果如下:
ā
á
ǎ
à
āi
ái
ǎi
ài
ān
án
2、脱敏某些拼音,并在每行上加上句号“。”,即:
bi 的拼音会识别为“敏感”音
bī
bí
bǐ
bì
# 把上面的拼音脱敏成以下内容
偪。
比。
笔。
闭。
shun 的拼音会识别为“敏感”音
shūn
shǔn
shùn
# 把上面的拼音脱敏成以下内容
楯。
吮。
顺。
“nun。o。” 的发出错,发成连音,不就方便语音切割
# 这样的组合会使百度发音出错,出现连音
nún。
ō。
# 改为即可
黁。
ō。
3、使用https://ai.baidu.com/tech/speech/tts_online
百度在线免费语音合成,每次最多可以合成200个UTF-8字符。
百度付费版 tts 支持直接返回二进制音频数据,百度在线免费版返回的是音频的 base64 编码数据。
使用百度在线免费试用版时,使用curl 命令如下:
curl 'https://ai.baidu.com/aidemo' \
-H 'Connection: keep-alive' \
-H 'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36' \
-H 'sec-ch-ua-platform: "Windows"' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Accept: */*' \
-H 'Origin: https://ai.baidu.com' \
-H 'Sec-Fetch-Site: same-origin' \
-H 'Sec-Fetch-Mode: cors' \
-H 'Sec-Fetch-Dest: empty' \
-H 'Referer: https://ai.baidu.com/tech/speech/tts_online' \
-H 'Accept-Language: zh-CN,zh;q=0.9' \
--data-raw 'type=tns&per=4003&spd=5&pit=5&vol=9&aue=6&tex=n%C3%BC%C3%A8%E3%80%82%0Anu%C3%B3%E3%80%82%0Anu%C3%B2%E3%80%82%0A%E9%BB%81%E3%80%82%0A%C5%8D%E3%80%82%0A%C3%B3%E3%80%82%0A%C5%8Du%E3%80%82%0A%C7%92u%E3%80%82%0A%C3%B2u%E3%80%82%0Ap%C4%81%E3%80%82%0Ap%C3%A1%E3%80%82%0Ap%C3%A0%E3%80%82%0Ap%C4%81i%E3%80%82%0Ap%C3%A1i%E3%80%82%0Ap%C7%8Ei%E3%80%82%0Ap%C3%A0i%E3%80%82%0Ap%C4%81n%E3%80%82%0Ap%C3%A1n%E3%80%82%0Ap%C7%8En%E3%80%82%0Ap%C3%A0n%E3%80%82%0Ap%C4%81ng%E3%80%82%0Ap%C3%A1ng%E3%80%82%0Ap%C7%8Eng%E3%80%82%0Ap%C3%A0ng%E3%80%82%0Ap%C4%81o%E3%80%82%0Ap%C3%A1o%E3%80%82%0Ap%C7%8Eo%E3%80%82%0Ap%C3%A0o%E3%80%82%0Ap%C4%93i%E3%80%82%0Ap%C3%A9i%E3%80%82%0Ap%C4%9Bi%E3%80%82%0A' \
--compressed
# tex 即是需要合成文本的URL编码
使用百度付费版 tts 时如下:
# cuid 用户唯一标识,用来计算UV值。建议填写能区分用户的机器 MAC 地址或 IMEI 码,长度为60字符以内。
# token 开放平台获取到的开发者access_token(见上面的“鉴权认证机制”段落)。参见:https://cloud.baidu.com/doc/SPEECH/s/Pk38y8m7k
# 其他参数说明请参见:https://cloud.baidu.com/doc/SPEECH/s/Qk38y8lrl
# tex 即是需要合成拼音的URL编码
curl "https://tsn.baidu.com/text2audio?lan=zh&vol=10&per=5003&cuid=$cuid&ctp=1&aue=3&tok=$token&tex=n%C3%BC%C3%A8%E3%80%82nu%C3%B3%E3%80%82nu%C3%B2%E3%80%82%E9%BB%81%E3%80%82%C5%8D%E3%80%82%C3%B3%E3%80%82%C5%8Du%E3%80%82%C7%92u%E3%80%82%C3%B2u%E3%80%82p%C4%81%E3%80%82p%C3%A1%E3%80%82p%C3%A0%E3%80%82p%C4%81i%E3%80%82p%C3%A1i%E3%80%82p%C7%8Ei%E3%80%82p%C3%A0i%E3%80%82p%C4%81n%E3%80%82p%C3%A1n%E3%80%82p%C7%8En%E3%80%82p%C3%A0n%E3%80%82p%C4%81ng%E3%80%82p%C3%A1ng%E3%80%82p%C7%8Eng%E3%80%82p%C3%A0ng%E3%80%82p%C4%81o%E3%80%82p%C3%A1o%E3%80%82p%C7%8Eo%E3%80%82p%C3%A0o%E3%80%82p%C4%93i%E3%80%82p%C3%A9i%E3%80%82p%C4%9Bi%E3%80%82%E3%80%82%0A" -o baidutts/mp3/25.mp3
将爬取的拼音拆分为长度小于150个字符,并将其转换成URL编码,我采用java程序开发,源码可参见BaiduTTS.java(百度网盘 请输入提取码) 。
将 BaiduTTS.jar 输出的 URL 编码集输出拷贝到 pinyin_url.txt 文件。用于做语音合成请求用。
语音合成请求采用的是shell脚本:
index=0
mkdir baidutts/mp3
cat pinyin_url.txt | while read line
do
id=`printf "%02d" index`
curl "https://tsn.baidu.com/text2audio?lan=zh&vol=10&per=5003&cuid=$cuid&ctp=1&aue=3&tok=$token&tex=$line" -o baidutts/mp3/$id.mp3
let "index=index+1"
done
注:本人使用的是付费版tts,每150个字符为一组进行识别,共花费了 ¥0.38 识别费用,生成 47 个语音文件。
.
├── 00.mp3
├── 01.mp3
……
├── 45.mp3
└── 46.mp3
4、使用 ffmpeg 将 mp3 转换成 wav。关于 ffmpeg 的安装与使用请参考《FFmpeg的安装与基础使用教程 - ZL Asica的博客》
mkdir -p baidutts/wav
cd baidutts/mp3
for file in `ls *.mp3`
do
ffmpeg -i $file -f wav ../wav/${file%%.*}.wav
done
cd -
5、进行语音检测
使用 libfvad(百度网盘 请输入提取码)进行有效语音检测
下载、编译
# 下载(可以直接使用百度云共享的zip包)
git clone https://github.com/dpirch/libfvad.git
# 编译
cd libfvad
# 创建编译目录
mkdir build
cd build
cmake ..
make
# 将编译出来的 libfvad.a 拷入 libfvad/examples/ 目录下
cp ./src/libfvad.a ../examples/
# 进入 examples 目录
cd ../examples
# 编译 examples
gcc -o fvadwav fvadwav.c -I../include -L. -lfvad -lsndfile
将编译生成的 examples/fvadwav
拷贝至 baidutts
目录下
使用 shell 命令进行 vad 检测
cd baidutts
mkdir -p dur
# vad检测
for ((i=0;$i<=46;i++))
do
id=`printf "%02d" $i`
# -l 表示输出检测结果写入文件
./fvadwav -l dur/$id.txt wav/$id.wav;
done
# 查看检测出来的有效语音和无效语音片段数
# grep "voice segments" | grep -v non
检测结果标签文件样式如下,1 代表“有效语音”,0 代表“无效语音”
0
0
0
1
1
1
1
0
0
6、爬取下来的拼音进行格式化,转换成 ascii 码拼音表示法。例:hāo
转换为 hao1
这个转换工具采用 java 语言编写,源码参见 RepleacePinyin.java
(百度网盘 请输入提取码)。
使用 shell 命令批转换原始拼音,shell URL编解码请参考shell 下 urlencode/urldecode 编码/解码的方法:
index=0
mkdir baidutts/subpinyin-format
cat pinyin_url.txt | while read line
do
pinyinfile=`printf "subpinyin-format/%02d.txt" $index`
printf $(echo -n "$line" | sed 's/\\/\\\\/g;s/\(%\)\([0-9a-fA-F][0-9a-fA-F]\)/\\x\2/g') > $pinyinfile;
# 转换后的拼音文件为后缀 “-conv.txt” 的文件
java -jar RepleacePinyin.jar $pinyinfile
let "index=index+1"
done
7、进行语音切割
确定wav语音数据的位置:以二进制方式查看 wav 文件。关于wav文件头定义说明参见《wav头文件详解》
00000000: 5249 4646 c690 0a00 5741 5645 666d 7420 RIFF....WAVEfmt
00000010: 1000 0000 0100 0100 803e 0000 007d 0000 .........>...}..
00000020: 0200 1000 4c49 5354 1a00 0000 494e 464f ....LIST....INFO
00000030: 4953 4654 0e00 0000 4c61 7666 3537 2e38 ISFT....Lavf57.8
00000040: 332e 3130 3000 6461 7461 8090 0a00 0000 3.100.data......
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
可以看出 0x0 ~ 0x4E 为wave文件头,即 78 个字节为wav文件的头。
wavcut 为使用c++开发的wav剪切工具,源码见wave-cut.cpp
(百度网盘 请输入提取码) 。编译命令:g++ -g -o wavcut wave-cut.cpp
,生成 wavcut
可执行程序。将可执行程序拷贝到 baidutts
目录下。
使用前步 vad 生成的 dur/*.txt 标签文件和wav语音文件切割成 pcm 片段
cd baidutts
for ((i=0;i<=46;i++))
do
id=`printf "%02d" $i`
echo "./wavcut dur/$id.txt wav/$id.wav subpinyin-format/$id.txt-conv.txt"
./wavcut "dur/$id.txt" "wav/$id.wav" "subpinyin-format/$id.txt-conv.txt"
done
生成的 pcm 语音片段文件位于 baidutts
目录下,使用 mv 命令进行整理
cd baidutts
mkdir pcm
mv *.pcm pcm/
使用 ffmpeg 将 pcm 转换成 wav 文件,并打包
cd baidutts
mkdir secs-wave
for file in `pcm/*.pcm`
do
name=${file##*/}
ffmpeg -i $file -f wav secs-wave/${name%%.*}.wav
done
tar -czvf baidu-secs-wave.tar.gz secs-wave
8、将第7步生成的子片段 wav 文件集移入 ekho 的 ekho-data 目录下
cd ekho/ekho-data
# 将 baidu-secs-wave.tar.gz 拷贝到当前目录下,然后解压
tar -xvf baidu-secs-wave.tar.gz
# 创建软链接
ln -s secs-wave pinyin
# 拷贝生成 de5.wav
cp pinyin/de1.wav pinyin/de5.wav -rf
9、删除 ekho-data 目录下的 pinyin.index、pinyin.voice文件,然后使用命令测试并初始化 ekho 组件。(可以参考:如何为Ekho添加新的声音)
cd ekho/ekho-data
rm -rf pinyin.*
cd ..
# 测试并初始化
./bin/ekho 0123456789 -vpinyin -o test.ogg -t ogg