使用百度tts合成音频融入Ekho方案

使用商业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、脱敏某些拼音,并在每行上加上句号“。”,即:

  1. bi 的拼音会识别为“敏感”音

    bī
    bí
    bǐ
    bì
    # 把上面的拼音脱敏成以下内容
    偪。
    比。
    笔。
    闭。
  1. shun 的拼音会识别为“敏感”音

    shūn
    shǔn
    shùn
    # 把上面的拼音脱敏成以下内容
    楯。
    吮。
    顺。
  2. “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、进行语音检测

  1. 使用 libfvad(百度网盘 请输入提取码)进行有效语音检测

    1. 下载、编译

      # 下载(可以直接使用百度云共享的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
    2. 将编译生成的 examples/fvadwav 拷贝至 baidutts 目录下

    3. 使用 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
    4. 检测结果标签文件样式如下,1 代表“有效语音”,0 代表“无效语音”

      0
      0
      0
      1
      1
      1
      1
      0
      0

6、爬取下来的拼音进行格式化,转换成 ascii 码拼音表示法。例:hāo 转换为 hao1

  1. 这个转换工具采用 java 语言编写,源码参见 RepleacePinyin.java(百度网盘 请输入提取码)。

  2. 使用 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、进行语音切割

  1. 确定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文件的头。

  2. wavcut 为使用c++开发的wav剪切工具,源码见wave-cut.cpp(百度网盘 请输入提取码) 。编译命令:g++ -g -o wavcut wave-cut.cpp,生成 wavcut 可执行程序。将可执行程序拷贝到 baidutts 目录下。

  3. 使用前步 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
  4. 生成的 pcm 语音片段文件位于 baidutts 目录下,使用 mv 命令进行整理

    cd baidutts
    mkdir pcm
    mv *.pcm pcm/
  5. 使用 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

你可能感兴趣的:(语音合成,ekho,libfvad,语音合成,Ekho语音合成,百度TTS)