/** * TtsPlayer — Text-to-Speech playback controls for classroom narration. * * Uses the browser's built-in SpeechSynthesis API. * Provides play/pause, speed, and volume controls. */ import { useState, useEffect, useCallback, useRef } from 'react'; import { Volume2, VolumeX, Pause, Play, Gauge } from 'lucide-react'; interface TtsPlayerProps { text: string; autoPlay?: boolean; onEnd?: () => void; } export function TtsPlayer({ text, autoPlay = false, onEnd }: TtsPlayerProps) { const [isPlaying, setIsPlaying] = useState(false); const [isPaused, setIsPaused] = useState(false); const [rate, setRate] = useState(1.0); const [isMuted, setIsMuted] = useState(false); const utteranceRef = useRef(null); const speak = useCallback(() => { if (!text || typeof window === 'undefined') return; window.speechSynthesis.cancel(); const utterance = new SpeechSynthesisUtterance(text); utterance.lang = 'zh-CN'; utterance.rate = rate; utterance.volume = isMuted ? 0 : 1; utterance.onend = () => { setIsPlaying(false); setIsPaused(false); onEnd?.(); }; utterance.onerror = () => { setIsPlaying(false); setIsPaused(false); }; utteranceRef.current = utterance; window.speechSynthesis.speak(utterance); setIsPlaying(true); setIsPaused(false); }, [text, rate, isMuted, onEnd]); const togglePlay = useCallback(() => { if (isPlaying && !isPaused) { window.speechSynthesis.pause(); setIsPaused(true); } else if (isPaused) { window.speechSynthesis.resume(); setIsPaused(false); } else { speak(); } }, [isPlaying, isPaused, speak]); const stop = useCallback(() => { window.speechSynthesis.cancel(); setIsPlaying(false); setIsPaused(false); }, []); // Auto-play when text changes useEffect(() => { if (autoPlay && text) { speak(); } return () => { if (typeof window !== 'undefined') { window.speechSynthesis.cancel(); } }; }, [text, autoPlay, speak]); // Cleanup on unmount useEffect(() => { return () => { if (typeof window !== 'undefined') { window.speechSynthesis.cancel(); } }; }, []); if (!text) return null; return (
{/* Play/Pause button */} {/* Stop button */} {isPlaying && ( )} {/* Speed control */}
{/* Mute toggle */} {/* Status indicator */} {isPlaying && ( {isPaused ? '已暂停' : '朗读中...'} )}
); }