讯飞语音合成 如何选择发音人

问题描述

讯飞语音合成有多个发音人,如何选择一个合适的发音人呢?我的解决方法是,选择符合要求的,然后每个都听一遍.最后选出一个合适的.

我的要求

我是用来朗读技术文章的,文章中要英文也有中文,所以我要选择支持中英文的发音人。发音人列表
这里有一张图片
符合我条件的发音人如下:

名称 属性 语言 参数名称 引擎参数 备注
小燕 青年女声 中英文(普通话) xiaoyan 默认
小宇 青年男声 中英文(普通话) xiaoyu
小研 青年女声 中英文(普通话) vixy
小琪 青年女声 中英文(普通话) vixq xiaoqi
小峰 青年男声 中英文(普通话) vixf

无法直接循环下载

下面写个demo,要求输入一段文字,然后使用上述的多个发音人分别来合成.下载下来我再一个个的听,选出一个英文清晰,阅读节奏合适的发音人.
因为要批量下载,我首先想到的是,循环调用下载方法不就行了如下所示:

1
2
3
4
5
6
7
8
for (......)
{
// 3.创建一个SpeechSynthesizer对象
SpeechSynthesizer mTts = SpeechSynthesizer.createSynthesizer();
// 4.设置合成参数
......
mTts.synthesizeToUri(Input, fileName, synthesizeToUriListener);
}

但是我失败了,这样并不会合成多个音频。只会合成一个。经过测试之后,我发现,调用完毕下载方法后,主线程就结束了.
……最后经过一番思索解决方案如下.

创建下载线程

线程的知识我有点忘了,合成音频的方法最后会回调onSynthesizeCompleted这个方法,我在下载线程DemoListRunable中设置一个isEnd标记,当开始下载一个音频的时候,把isEnd设置为flase,下载完毕后设置为true.
在主线程中,通过不断的来查询这个标记,从而知道是否下载完毕。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package demo;
import com.iflytek.cloud.speech.SpeechConstant;
import com.iflytek.cloud.speech.SpeechError;
import com.iflytek.cloud.speech.SpeechSynthesizer;
import com.iflytek.cloud.speech.SynthesizeToUriListener;
public class DemoListRunable implements Runnable
{
public static boolean isEnd=false;
String fileName;
String Input;
String voiceName;
public DemoListRunable(String voiceName, String fileName, String Input)
{
this.voiceName = voiceName;
this.fileName = fileName;
this.Input = Input;
}
public void run()
{
// 3.创建一个SpeechSynthesizer对象
SpeechSynthesizer mTts = SpeechSynthesizer.createSynthesizer();
// 4.合成参数设置,详见《MSC Reference Manual》SpeechSynthesizer 类
// 设置发音人
// 小燕 青年女声 中英文(普通话) xiaoyan 默认
// 小研 青年女声 中英文(普通话) vixy
// 小琪 青年女声 中英文(普通话) vixq xiaoqi
// 小宇 青年男声 中英文(普通话) xiaoyu
// 小峰 青年男声 中英文(普通话) vixf
// 4-1 设置发音人
mTts.setParameter(SpeechConstant.VOICE_NAME, voiceName);//
// 设置要下载的文件名
mTts.setParameter(SpeechConstant.SPEED, "50");
// 设置语调,范围0~100
mTts.setParameter(SpeechConstant.PITCH, "50");
// 设置音量,范围0~100
mTts.setParameter(SpeechConstant.VOLUME, "50");
// TODO Auto-generated method stub
System.out.println(
" 正在合成 " + fileName.substring(0, fileName.lastIndexOf("."))
+ " 朗读样例" + " 下载位置:" + fileName);
mTts.synthesizeToUri(Input, fileName, synthesizeToUriListener);
}
// 1 设置合成监听器
static SynthesizeToUriListener synthesizeToUriListener = new SynthesizeToUriListener()
{
// progress为合成进度0~100
public void onBufferProgress(int progress)
{
}
// 会话合成完成回调接口
// uri为合成保存地址,error为错误信息,为null时表示合成会话成功
public void onSynthesizeCompleted(String uri, SpeechError error)
{
//表明下载完成
isEnd=true;
if(error==null)
System.out.println(" 合成成功");
else
System.out.println(" 合成失败");
}
@Override
public void onEvent(int arg0, int arg1, int arg2, int arg3, Object arg4,
Object arg5)
{
// TODO Auto-generated method stub
}
};
}

主线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package demo;
import java.util.Scanner;
import com.iflytek.cloud.speech.SpeechConstant;
import com.iflytek.cloud.speech.SpeechUtility;
import replace.Replace;
public class DemoList
{
static Scanner scanner = new Scanner(System.in);
public static void main(String[] args)
{
// 2 将“XXXXXXXX”替换成您申请的APPID
SpeechUtility.createUtility(SpeechConstant.APPID + "=XXXXXXXX");
// 5设置要合成的文本
System.out.println(
"######################################## 讯飞语音合成系统 ########################################");
System.out.println("输入要合成的文字(以: \"#exit\"作为结束符):");
StringBuffer sbBuffer = new StringBuffer(10240);
String line = null;
while (scanner.hasNext())
{
line = scanner.nextLine();
if ("#exit".equals(line))
{
break;
}
sbBuffer.append(line.concat("\r\n"));
}
System.out.println(
"---------------------------------- 特殊字符处理 ----------------------------------");
// 处理输入文本,替换容易读错的特殊字符.
String Input = Replace.replaceTitle(sbBuffer.toString());
Input = Replace.replaceEnglish(Input);
System.out.println(Input);
System.out.println(
"---------------------------------- 特殊字符处理 ----------------------------------");
String[] fileNameArr = new String[]
{"小燕xiaoyan.pcm", "小研vixy.pcm", "小琪vixq.pcm", "小宇xiaoyu.pcm",
"小峰vixf.pcm"};
String[] voiceNameArr = new String[]
{"xiaoyan", "vixy", "vixq", "xiaoyu", "vixf"};
for (int i = 0; i < fileNameArr.length; i++)
{
DemoListRunable runable=new DemoListRunable(voiceNameArr[i], fileNameArr[i], Input);
DemoListRunable.isEnd=false;
Thread thread=new Thread(runable);
thread.start();
//等待下载完毕
while(!DemoListRunable.isEnd)
{
try
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}

其中Replace这个类用来预处理朗读的文本.包括替换容易读错的字符,添加空格以加入停顿等。代码参见讯飞语音合成 发音不准确怎么解决

实验结果

下载好音频后,逐个听一半,比较一番,我的到如下结果:

发音人 连贯性 英文准确性
小燕xiaoyan 可以 英文准确
小研vixy 可以 英文准确
小琪vixq 英文可能不准确
小峰vixf 慢没有节奏 英文发音不全
小宇xiaoyu 可以 英文发音不好

通过比较我发现:

  • 女发音人中,
    • 小燕xiaoyan小研vixy这两个发音人可以用,还有就是小燕xiaoyan(默认)读的时候有写破音,最后我选择小研vixy这个发音人。
    • 小琪vixq读的有点慢,但是中英文之间切换比较好。
  • 而男发音人小峰vixf小宇xiaoyu读英文的时候声音小不清晰,读音不标准。

具体情况还是以实验为主.