62 lines
1.8 KiB
JavaScript
62 lines
1.8 KiB
JavaScript
|
import Speech from 'speak-tts'
|
|||
|
import { useSpeakStore } from '@/store/speak'
|
|||
|
|
|||
|
let speechInstance = null
|
|||
|
let lastVoice = ''
|
|||
|
|
|||
|
export async function speakText(text) {
|
|||
|
if (!text) return
|
|||
|
const speakStore = useSpeakStore()
|
|||
|
if (!speechInstance) {
|
|||
|
speechInstance = new Speech()
|
|||
|
if (!speechInstance.hasBrowserSupport()) {
|
|||
|
console.warn('当前浏览器不支持语音合成')
|
|||
|
return
|
|||
|
}
|
|||
|
await speechInstance.init({
|
|||
|
lang: 'zh-CN',
|
|||
|
volume: speakStore.ttsVolume,
|
|||
|
rate: speakStore.ttsRate,
|
|||
|
pitch: speakStore.ttsPitch,
|
|||
|
splitSentences: true,
|
|||
|
voice: speakStore.ttsVoice || undefined
|
|||
|
})
|
|||
|
lastVoice = speakStore.ttsVoice || ''
|
|||
|
}
|
|||
|
// 切换voice或参数时重新init
|
|||
|
if ((speakStore.ttsVoice || '') !== lastVoice
|
|||
|
|| speechInstance._volume !== speakStore.ttsVolume
|
|||
|
|| speechInstance._rate !== speakStore.ttsRate
|
|||
|
|| speechInstance._pitch !== speakStore.ttsPitch) {
|
|||
|
await speechInstance.init({
|
|||
|
lang: 'zh-CN',
|
|||
|
volume: speakStore.ttsVolume,
|
|||
|
rate: speakStore.ttsRate,
|
|||
|
pitch: speakStore.ttsPitch,
|
|||
|
splitSentences: true,
|
|||
|
voice: speakStore.ttsVoice || undefined
|
|||
|
})
|
|||
|
lastVoice = speakStore.ttsVoice || ''
|
|||
|
}
|
|||
|
speakStore.setTTSStatus('playing')
|
|||
|
speechInstance.speak({
|
|||
|
text,
|
|||
|
onend: () => speakStore.setTTSStatus('idle'),
|
|||
|
onerror: () => speakStore.setTTSStatus('idle')
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
export async function getTTSVoices() {
|
|||
|
// 兼容speak-tts 2.x,使用浏览器原生API
|
|||
|
return new Promise((resolve) => {
|
|||
|
let voices = window.speechSynthesis.getVoices();
|
|||
|
if (voices.length) {
|
|||
|
resolve(voices);
|
|||
|
} else {
|
|||
|
window.speechSynthesis.onvoiceschanged = () => {
|
|||
|
voices = window.speechSynthesis.getVoices();
|
|||
|
resolve(voices);
|
|||
|
};
|
|||
|
}
|
|||
|
});
|
|||
|
}
|