前言
这是一个实验API,下面是来自MDN的兼容性表格,请注意,语音识别和语音合成兼容性不同,请注意区分.
![](http://101.201.83.132/wp-content/uploads/2021/02/image-1.png)
![](http://101.201.83.132/wp-content/uploads/2021/02/image-2.png)
![](http://101.201.83.132/wp-content/uploads/2021/02/image-3.png)
![](http://101.201.83.132/wp-content/uploads/2021/02/image-4.png)
![](http://101.201.83.132/wp-content/uploads/2021/02/image-5.png)
![](http://101.201.83.132/wp-content/uploads/2021/02/image-6.png)
语音合成
我们也看到了,语音合成浏览器支持的多一些,所以我们先学习语音合成.在我的随机抽号中,也使用了此API,具体效果如下(使用edge88):
我们首先要了解一个window.speechSynthesis
,它是一个只读对象,返回一个SpeechSynthesis
对象,该对象是使用Web Speech API语音合成功能的入口点.它有3个只读属性:
SpeechSynthesis.paused
只读
当SpeechSynthesis
处于暂停状态时, Boolean
值返回 true
。SpeechSynthesis.pending
只读
当语音播放队列到目前为止保持没有说完的语音时, Boolean
值返回 true
。SpeechSynthesis.speaking
只读
当语音谈话正在进行的时候,即使SpeechSynthesis
处于暂停状态, Boolean
返回 true
。
然后我们需要新建一个SpeechSynthesisUtterance
对象:
tts = new SpeechSynthesisUtterance(str);
str
是要转换的文本,最后,直接speak就是一个初级的tts了:
var say = window.speechSynthesis;
var tts = new SpeechSynthesisUtterance(str);
say.speak(tts);
接下来,就是优化加功能了.
首先,刚才三个SpeechSynthesis
的只读属性可以做判断,比如不允许播放之类(return
),然后,还有下面可以设置:
volume
– 声音的音量,区间范围是0
到1
,默认是1
。rate
– 语速,数值,默认值是1
,范围是0.1
到10
,表示语速的倍数,例如2
表示正常语速的两倍。pitch
– 表示说话的音高,数值,范围从0
(最小)到2
(最大)。默认值为1
。
都是在SpeechSynthesisUtterance
操作的.最后,就是声音了.
首先,window.speechSynthesis.getVoices()
是获取浏览器支持的语音列表,如在edge中,有以下内容:
![](http://101.201.83.132/wp-content/uploads/2021/02/屏幕截图-2021-02-19-225933.png)
所以,我们可以先新建一个<select>
,然后设置id
为TTSlist
,随后,var TTSlist = document.getElementById('TTSlist')
方便使用.目前代码为:
<html>
<body>
<select id="TTSlist"></select>
<script>
var TTSlist = document.getElementById('TTSlist')
var say = window.speechSynthesis;
function ttsReady(){
voices = say.getVoices();
}
ttsReady();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = ttsReady;
}
var tts = new SpeechSynthesisUtterance('hello javascript');
say.speak(tts);
</script>
</body>
</html>
因为后面可能还会执行这个函数,所以我们还需要TTSlist.innerHTML = '';
,接下来就是将刚刚获取到的列表输出即可
for(i = 0; i < voices.length ; i++) {
var option = document.createElement('option');
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
TTSlist.appendChild(option);
}
封装进函数ttsReady
,然后调用一次.但是不知道为什么会在edge上出错,所以还需一个保险:
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = ttsReady;
}
因为有一些浏览器不支持speechSynthesis.onvoiceschanged
,所以我们需要判断一次.他现在应该是这样的:
![](http://101.201.83.132/wp-content/uploads/2021/02/屏幕截图-2021-02-20-130131-edited.png)
![](http://101.201.83.132/wp-content/uploads/2021/02/屏幕截图-2021-02-20-130317.png)
我们不难发现,有两个online
的zh-CN
跑到了最后,所以我们需要提前.找到刚才的voices = say.getVoices()
,改成:
voices = say.getVoices().sort(function (a, b) {
const aname = a.lang.toUpperCase(), bname = b.lang.toUpperCase();
if(aname == 'ZH-CN' && bname != 'ZH-CN') return -1;
else if(aname != 'ZH-CN' && bname == 'ZH-CN') return 1;
else if(aname == 'ZH-CN' && bname == 'ZH-CN') return 0;
else if ( aname < bname ) return -1;
else if ( aname == bname ) return 0;
else return +1;
});
这下就可以了,接下来,就是把选择的语音应用.核心代码如下:
voice = TTSlist.selectedOptions[0].getAttribute('data-name');
for(i = 0; i < voices.length ; i++) {
if(voices[i].name === voice) {
tts.voice = voices[i];
console.log(voices[i])
break;
}
}
最后为了方便大家,我把整个代码贴在这里(请不要什么都不看直接无脑抄,有问题随时反馈,音高等自己设置):
<html>
<body>
<select id="TTSlist"></select>
<script>
var TTSlist = document.getElementById('TTSlist')
var say = window.speechSynthesis;
function ttsReady(){
voices = say.getVoices().sort(function (a, b) {
const aname = a.lang.toUpperCase(), bname = b.lang.toUpperCase();
if(aname == 'ZH-CN' && bname != 'ZH-CN') return -1;
else if(aname != 'ZH-CN' && bname == 'ZH-CN') return 1;
else if(aname == 'ZH-CN' && bname == 'ZH-CN') return 0;
else if ( aname < bname ) return -1;
else if ( aname == bname ) return 0;
else return +1;
});
for(i = 0; i < voices.length ; i++) {
var option = document.createElement('option');
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
TTSlist.appendChild(option);
}
}
ttsReady();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = ttsReady;
}
function testTTS(str) {
voice = TTSlist.selectedOptions[0].getAttribute('data-name');
if(str == '') {console.log('string is empty!');return;}
if(say.speaking) {
console.error('voice is speaking!');
return;
}
tts = new SpeechSynthesisUtterance(str);
for(i = 0; i < voices.length ; i++) {
if(voices[i].name === voice) {
tts.voice = voices[i];
console.log(voices[i])
break;
}
}
say.speak(tts);
}
</script>
</body>
</html>
语音识别下次写吧.
Comments | 2 条评论
该评论为私密评论
@TEST TEST