应用场景
在开发业务系统时,有时候可能需要使用语音播报一段文字,比如下面的场景:
当需要系统自动播报收款的金额,其中付款金额是不固定时或者车辆平台需要播报预警等等
如果是相对固定的场景,并且语音有限的情况下,可以采用录制的方式,即先录制好所有的音频资源,然后根据业务场景播放相应的音频即可;但是如果场景不固定,需要的语音也不一样时,采用录制的方式的话,音频资源将会非常多,而且还可能会出现不全的问题,那么这个时候利用语音合成技术是一个较好的办法,即实时将文字转换成语音。
目前文字转语音即语音合成技术现在已经很成熟了,像百度、讯飞等都提供了相关的服务,支持将文字转换成各种形式的语音,通常这些服务都需要付费使用,如果对语音要求不高,并且又想节约成本,那么可以直接使用浏览器的语音合成功能。
语音合成主要涉及到两个对象:SpeechSynthesis
和 SpeechSynthesisUtterance
。
SpeechSynthesis语言合成
SpeechSynthesis
接口是语音服务的控制接口;它可以用于获取设备上关于可用的合成声音的信息,开始、暂停语音,或除此之外的其他命令
实例属性
属性 | 解释 |
---|---|
paused | 当处于暂停状态时值返回true |
pending | 当语音播放队列到目前为止保持没有说完的语音时为true |
speaking | 当语音谈话正在进行的时候为true |
注:这个三个属性都是只读,不可进行修改 改变状态需要用到以下几个方法
实例方法
方法 | 解释 |
---|---|
cancel | 移除所有语音谈话队列中的谈话。 |
pause | 把对象置为暂停状态 |
resume | 把对象置为一个非暂停状态:如果已经暂停了则继续 |
getVoices | 返回当前设备所有可用声音的 |
speak | 添加一个语音谈话队列中 |
example
let synthesis=window.speechSynthesis // 暂停 pause() { synthesis.pause(); } // 继续播放 resume() { synthesis.resume(); } // 移除所有语音 //添加新的语音时,如果需要立即播放刚添加的语音需要先清空语音队列否则还是会把队列存在的语音播放完在播放刚添加的 cancel() { synthesis.cancel(); } // 取消播放 cancel() { synthesis.cancel(); } // 获取系统可用的语音列表 getVoices() { synthesis.getVoices(); } // 添加一个语音到队列中 const utterance = new SpeechSynthesisUtterance( "浏览器实现语音合成", ); speak() { synthesis.speak(utterance); }
SpeechSynthesisUtterance语音合成话语
SpeechSynthesisUtterance
是HTML5中新增的API,用于将指定文字合成为对应的语音.也包含一些配置项,指定如何去阅读(语言,音量,音调)等
实例属性
属性 | 解释 |
---|---|
pitch | 获取并设置话语的音调(值越大越尖锐,越低越低沉) |
rate | 获取并设置说话的速度(值越大语速越快,越小语速越慢) |
volume | 获取并设置说话的音量 |
lang | 获取并设置播放语言类型 |
text | 获取并设置语音播放内容 |
voice | 获取并设置说话的声音 |
example
let speech = new SpeechSynthesisUtterance(); speech.pitch = 1; // 获取并设置话语的音调(值越大越尖锐,越低越低沉) speech.rate = 1.5; // 获取并设置说话的速度(值越大语速越快,越小语速越慢) speech.volume = 10; // 获取并设置说话的音量 speech.lang = "zh-CN"; // 设置播放语言(如果设置了voice会有先使用voice对象中的lang) speech.voice = "ZhangJing"; // 获取并设置说话的声音 speech.text = text //文字或者SSML语音标签
实例事件
事件 | 解释 |
---|---|
onboundary | 在语音语句达到单词或句子边界时触发 |
onend | 在语音结束时触发 |
onerror | 当发生阻止成功朗读语句的错误时触发 |
onmark | 语音标记事件 结合ssml标签语言中mark使用 |
onpause | 在话语中途暂停时触发 |
onresume | 在语音恢复播放时触发 |
onstart | 在开始说出话语时触发 |
example
let speech = new SpeechSynthesisUtterance(); // 语音播报边界 speech.onboundary = () => { //中英文监听不一致 //eg: how are you 触发四次 // 这是一段语音播放 触发六次 // console.log("语音播报边界") } // 错误语音播报事件 speech.onerror = () => { // console.log("错误语音播报事件") } // 标记语音播报事件 speech.onmark = () => { // 结合ssml语音标签测试发现没有效果 可能是azure废弃了bookmark // console.log("标记语音播报事件") } // 语音开始播报 speech.onstart = () => { // console.log("语音开始播报") } // 语音暂停播报 speech.onpause = () => { // console.log("语音暂停播报") } // 语音恢复播报 speech.onresume = () => { // console.log("语音恢复播报") } // 语音结束播报 speech.onend = () => { // console.log("语音播报结束") }
遇到的一些问题
1.为什么SpeechSynthesis不能在直接Chrome上播放语音
Chrome浏览器在18年4月起,全面禁止了音视频的自动播放功能。从Chrome 66开始,限制了video和audio元素的自动播放,从Chrome 71开始,还限制了Web Audio API的自动播放。
<html> <head> </head> <body> if ( 'speechSynthesis' in window ) { var to_speak = new SpeechSynthesisUtterance('Hello world!'); window.speechSynthesis.speak(to_speak); } else { alert('not support '); } </script> </body> </html>
a.问题原因是Chrome自动播放策略始不允许自动播放需要用户交互才能够允许播放
<form> <input type='text' id="input"></input> <select id='voiceSelect'></select> <button type="button" id="button">Speak</button> </form> button.addEventListener('click', () => { if ( 'speechSynthesis' in window ) { const to_speak = new SpeechSynthesisUtterance(input.value || 'Hello world!'); speechSynthesis.cancel(); speechSynthesis.speak(to_speak); } else { alert('not supported'); } });
b.进行chrome浏览器设置,右击chrome快捷图标-->属性-->快捷方式-->目标加入"--autoplay-policy=no-user-gesture-required"
2.为什么直接获取语音列表为空,这是因为允许使用远程服务器进行语音合成,而SpeechSynthesis向服务器请求语音列表。 要解决此问题,需要等待语音将被加载,然后再次请求它们
a.官网的做法speechSynthesis.onvoiceschanged ,当由SpeechSynthesis.getVoices()方法返回的SpeechSynthesisVoice列表改变时触发
if (speechSynthesis.onvoiceschanged !== undefined) { speechSynthesis.onvoiceschanged = getVoices() //获取语音列表的方法 }
b.延时获取语音列表
setTimeout(()=>{ seepchSynthesis.getVoices() },10)
3.speechSynthesis.getVoice()获取的语音列表为什么有些语音不能够正常播放
a.因为获取的语音列表大部分是远程异步服务,不能播放的因素有网络宽带或需要支付费用才能使用,本地可使用的音频localService==true
参考文献
1.语音合成 - 网络接口 |多核 (mozilla.orghttps://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis)