100 lines
2.6 KiB
TypeScript
100 lines
2.6 KiB
TypeScript
import { useState } from 'react'
|
|
import { useToast } from '@/components/shared/Toast'
|
|
|
|
interface UseTTSPlayerReturn {
|
|
isPlayingWord: boolean
|
|
isPlayingExample: boolean
|
|
toggleWordTTS: (text: string, lang?: string) => void
|
|
toggleExampleTTS: (text: string, lang?: string) => void
|
|
stopAllTTS: () => void
|
|
}
|
|
|
|
export const useTTSPlayer = (): UseTTSPlayerReturn => {
|
|
const toast = useToast()
|
|
const [isPlayingWord, setIsPlayingWord] = useState(false)
|
|
const [isPlayingExample, setIsPlayingExample] = useState(false)
|
|
|
|
// 檢查瀏覽器支援
|
|
const checkTTSSupport = (): boolean => {
|
|
if (!('speechSynthesis' in window)) {
|
|
toast.error('您的瀏覽器不支援語音播放')
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// 停止所有語音播放
|
|
const stopAllTTS = () => {
|
|
speechSynthesis.cancel()
|
|
setIsPlayingWord(false)
|
|
setIsPlayingExample(false)
|
|
}
|
|
|
|
// 創建語音播放實例
|
|
const createUtterance = (text: string, lang: string = 'en-US', rate: number = 0.8) => {
|
|
const utterance = new SpeechSynthesisUtterance(text)
|
|
utterance.lang = lang
|
|
utterance.rate = rate
|
|
utterance.pitch = 1.0
|
|
utterance.volume = 1.0
|
|
return utterance
|
|
}
|
|
|
|
// 詞彙發音播放
|
|
const toggleWordTTS = (text: string, lang: string = 'en-US') => {
|
|
if (!checkTTSSupport()) return
|
|
|
|
// 如果正在播放詞彙,則停止
|
|
if (isPlayingWord) {
|
|
stopAllTTS()
|
|
return
|
|
}
|
|
|
|
// 停止所有播放並開始新播放
|
|
stopAllTTS()
|
|
setIsPlayingWord(true)
|
|
|
|
const utterance = createUtterance(text, lang, 0.8) // 詞彙播放稍慢
|
|
|
|
utterance.onend = () => setIsPlayingWord(false)
|
|
utterance.onerror = () => {
|
|
setIsPlayingWord(false)
|
|
toast.error('語音播放失敗')
|
|
}
|
|
|
|
speechSynthesis.speak(utterance)
|
|
}
|
|
|
|
// 例句發音播放
|
|
const toggleExampleTTS = (text: string, lang: string = 'en-US') => {
|
|
if (!checkTTSSupport()) return
|
|
|
|
// 如果正在播放例句,則停止
|
|
if (isPlayingExample) {
|
|
stopAllTTS()
|
|
return
|
|
}
|
|
|
|
// 停止所有播放並開始新播放
|
|
stopAllTTS()
|
|
setIsPlayingExample(true)
|
|
|
|
const utterance = createUtterance(text, lang, 0.9) // 例句播放正常語速
|
|
|
|
utterance.onend = () => setIsPlayingExample(false)
|
|
utterance.onerror = () => {
|
|
setIsPlayingExample(false)
|
|
toast.error('語音播放失敗')
|
|
}
|
|
|
|
speechSynthesis.speak(utterance)
|
|
}
|
|
|
|
return {
|
|
isPlayingWord,
|
|
isPlayingExample,
|
|
toggleWordTTS,
|
|
toggleExampleTTS,
|
|
stopAllTTS
|
|
}
|
|
} |