dramaling-vocab-learning/frontend/hooks/shared/useTTSPlayer.ts

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
}
}