# APNG Lip Sync Tool 개발기 - v13: 스트리밍 효과 구현 ## 개요 AI 챗봇처럼 텍스트가 한 글자씩 나타나면서 캐릭터가 말하는 듯한 스트리밍 효과를 구현합니다. ## 스트리밍 데이터 생성 ```python def create_streaming_response(character_name: str, text: str) -> dict: """Create streaming-ready response for lip sync.""" session = LipsyncSession(character_name) speech_result = generate_speech_with_timing(text) return { "text": text, "duration_ms": speech_result["duration_ms"], "audio_url": speech_result["path"], "timings": speech_result["timings"], "viseme_urls": { name: f"/characters/{character_name}/{name}.png" for name in session.visemes.keys() } } ``` ## 클라이언트 스트리밍 효과 ```javascript async function streamLipsync(character, text) { // 타이밍 데이터 가져오기 const response = await fetch('/api/stream', { method: 'POST', body: JSON.stringify({ character, text }) }); const data = await response.json(); // 오디오 재생 시작 const audio = new Audio(data.audio_url); audio.play(); // 텍스트 스트리밍 + 립싱크 const textElement = document.getElementById('text-output'); const imageElement = document.getElementById('character-image'); let charIndex = 0; audio.addEventListener('timeupdate', () => { const currentTime = audio.currentTime * 1000; // 현재 시간에 해당하는 문자까지 표시 while (charIndex < data.timings.length && data.timings[charIndex].start_ms <= currentTime) { textElement.textContent += data.timings[charIndex].char; charIndex++; } // viseme 업데이트 const viseme = getVisemeAtTime(data.timings, currentTime); imageElement.src = data.viseme_urls[viseme]; }); } ``` ## 타이핑 효과와 립싱크 동기화 텍스트가 나타나는 타이밍과 입모양 변화가 자연스럽게 맞춰집니다: 1. 음성 재생 시작 2. 현재 재생 시간에 맞는 글자까지 텍스트 표시 3. 동시에 해당 음소의 viseme로 이미지 전환 ## 결과 마치 AI가 실시간으로 생각하면서 말하는 듯한 자연스러운 UX를 제공합니다. --- *다음: v14 - 전체 통합 및 테스트*