fix: 중국어 TTS → Google Translate TTS로 변경 (고품질 발음)

This commit is contained in:
Nan Kyung Lee 2026-03-24 15:57:37 +09:00
부모 2c4535e57e
커밋 4ab7990e5d

파일 보기

@ -143,32 +143,19 @@ export function OpsGuideModal({ ships, onClose, onFlyTo, onRouteSelect }: Props)
navigator.clipboard.writeText(text).then(() => { setCopiedIdx(idx); setTimeout(() => setCopiedIdx(null), 1500); });
};
const audioRef = useRef<HTMLAudioElement | null>(null);
const speakChinese = useCallback((text: string, idx: number) => {
if (typeof window === 'undefined' || !window.speechSynthesis) return;
window.speechSynthesis.cancel();
const utter = new SpeechSynthesisUtterance(text);
utter.lang = 'zh-CN';
utter.rate = 0.8;
utter.pitch = 1.0;
utter.volume = 1;
const voices = window.speechSynthesis.getVoices();
const zhVoice = voices.find(v => v.lang === 'zh-CN') || voices.find(v => v.lang.startsWith('zh'));
if (zhVoice) utter.voice = zhVoice;
// Chrome bug workaround: pause/resume keepalive to prevent cutoff
let keepAlive: ReturnType<typeof setInterval> | null = null;
utter.onstart = () => {
// Stop previous
if (audioRef.current) { audioRef.current.pause(); audioRef.current = null; }
setSpeakingIdx(idx);
keepAlive = setInterval(() => {
if (window.speechSynthesis.speaking && !window.speechSynthesis.paused) {
window.speechSynthesis.pause();
window.speechSynthesis.resume();
}
}, 5000);
};
const cleanup = () => { setSpeakingIdx(null); if (keepAlive) clearInterval(keepAlive); };
utter.onend = cleanup;
utter.onerror = cleanup;
window.speechSynthesis.speak(utter);
const encoded = encodeURIComponent(text);
const url = `https://translate.google.com/translate_tts?ie=UTF-8&client=tw-ob&tl=zh-CN&q=${encoded}`;
const audio = new Audio(url);
audioRef.current = audio;
audio.onended = () => setSpeakingIdx(null);
audio.onerror = () => setSpeakingIdx(null);
audio.play().catch(() => setSpeakingIdx(null));
}, []);
const handleSuspectClick = (s: SuspectVessel) => {