功能问题概述
项目中用到了谷歌内核浏览器的文字转语音功能,需要把要朗读的文字展示出来,因此出现了语音还未读完文字已经展示结束的问题(开始使用的setTimeout函数倒计时展示文字,这种方式并不好用,倒计时结束文字收起展示,但是语音还在朗读。)
问题修改
实现文字转语音需要用到 window.speechSynthesis 与 new SpeechSynthesisUtterance()这两个对象。
其中SpeechSynthesisUtterance提供了监听文字转语音开始于结束的函数,通过控制这两个函数来控制文字展示的时间。
//简单实现
handleSpeak(e) {
const msg = new SpeechSynthesisUtterance();
const synth = window.speechSynthesis
msg.text = e //要读的文字
msg.lang = 'zh-CN' //读汉语
msg.volume = 1 //音量
msg.rate = 0.9 //语速
msg.pitch = 0.8 //音色
msg.addEventListener('start', () => {
console.log("开始!!!!!!")
});
synth.speak(msg) //开始读
msg.addEventListener('end', this.handleEndEvent());
},
handleEndEvent() {
console.log("结束!!!!!!")
}
代码中的synth.speak(msg),当多个要转语音的文本进入队列时,它是阻塞的,排队队列的实现原则是先进先出的。
并且监听end函数一定要在speak函数后面。
同时建议使用edge浏览器或者低于7.6版本的谷歌浏览器来测试该功能!!!!!
具体代码
<script>
export default {
data() {
return {
textZC: [],
textZCZY: [],
msginfo: '',
divVisable: false,
urlTwo: 'http://localhost:8083',
}
},
methods: {
getMessages() {
uni.request({
url: this.urlTwo + '******',
method: 'GET',
dataType: 'json'
}).then((res) => {
var that = this
// 我这里是将请求响应回来的要读取的文字暂存到一个数组中,用于展示内容。
const item = res[1].data.data.message
that.textZC.push(item.message)
that.textZCZY.push(item.message)
setTimeout(() => {
that.handleSpeak(item.message)
},100)
})
},
handleSpeak(e) {
const synth = window.speechSynthesis
let voice = undefined
// setTimeout(() => {
// voice = synth.getVoices(); //获取浏览器自带的语音包
// console.log(voice)
// }, 50);
setTimeout(() => {
const msg = new SpeechSynthesisUtterance()
const msgHK = new SpeechSynthesisUtterance()
msg.text = e //要读的文字
msg.lang = 'zh-CN' //读汉语
msg.volume = 1 //音量
msg.rate = 0.9 //语速
msg.pitch = 0.8 //音色
msgHK.text = e //要读的文字
msgHK.lang = 'zh-HK' //读汉语
msgHK.volume = 1 //音量
msgHK.rate = 0.9 //语速
msgHK.pitch = 0.8 //音色
// if (this.voice[0] !== undefined) {
// msg.voice = this.voice[0]; //设置语音包
// }
msg.addEventListener('start', () => {
console.log("开始!!!!!!")
//将数组第一位的文本赋值给要展示的弹出框
this.msginfo = this.textZC[0]
this.divVisable = true
});
synth.speak(msg) //开始读
msg.addEventListener('end', this.handleEndEvent(msgHK,synth));
}, 50);
},
handleEndEvent(msgHK,synth) {
synth.speak(msgHK)
msgHK.addEventListener('end', this.handleEndEventHK);
},
handleEndEventHK() {
this.divVisable = false
this.textZC.shift()
this.textZCZY.shift()
},
}
</script>
因为项目是在广东那边上线的所以他们要求先普通话再粤语来读语音,所以以上代码顺便实现了先普通话再粤语的功能。
如果不需要 可以将msgHK相关的内容删除掉,并将handleEndEventHK里的内容放在handleEndEvent内,msgHK的end监听函数以及synth.speak(msgHK)删除即可。
谢谢大家的观看!!希望对您的项目有所帮助,同时如果您有更好的方法实现此功能或者代码有需要优化的地方,希望提出宝贵意见,不胜感激!!!