# Streaming Avatar 개발기 - v2: 시스템 아키텍처 설계 ## 개요 v1에서 분석한 기술들을 바탕으로, 우리만의 Streaming Avatar 시스템 아키텍처를 설계합니다. ## 전체 시스템 아키텍처 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ Streaming Avatar System Architecture │ └─────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────┐ │ Web Client │ │ (React/Next.js)│ └────────┬────────┘ │ WebRTC (Video/Audio) + WebSocket (Control) │ ┌────────▼────────┐ │ Edge Server │ │ (Cloudflare) │ └────────┬────────┘ │ ┌────────────────────────┼────────────────────────┐ │ │ │ ┌─────────▼─────────┐ ┌─────────▼─────────┐ ┌─────────▼─────────┐ │ Audio Pipeline │ │ Video Pipeline │ │ AI Pipeline │ │ │ │ │ │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ STT Engine │ │ │ │Avatar Store │ │ │ │ LLM API │ │ │ │ (Whisper) │ │ │ │ (Assets) │ │ │ │ (Gemini) │ │ │ └──────┬──────┘ │ │ └──────┬──────┘ │ │ └──────┬──────┘ │ │ │ │ │ │ │ │ │ │ │ ┌──────▼──────┐ │ │ ┌──────▼──────┐ │ │ ┌──────▼──────┐ │ │ │ VAD │ │ │ │ Lip Sync │ │ │ │ Context │ │ │ │(Voice Det.) │ │ │ │ (MuseTalk) │ │ │ │ Manager │ │ │ └─────────────┘ │ │ └──────┬──────┘ │ │ └─────────────┘ │ │ │ │ │ │ │ │ └───────────────────┘ │ ┌──────▼──────┐ │ └───────────────────┘ │ │ Encoder │ │ │ │ (H.264/VP9) │ │ │ └─────────────┘ │ │ │ └───────────────────┘ ┌─────────────────┐ │ TTS Engine │ │ (ElevenLabs/ │ │ Google TTS) │ └─────────────────┘ ``` ## 컴포넌트별 상세 설계 ### 1. 클라이언트 (Frontend) ```typescript // components/StreamingAvatar.tsx interface AvatarClientConfig { avatarId: string; serverUrl: string; iceServers: RTCIceServer[]; } class StreamingAvatarClient { private pc: RTCPeerConnection; private ws: WebSocket; private audioContext: AudioContext; // WebRTC 연결 설정 async connect(config: AvatarClientConfig): Promise; // 음성 입력 시작/중지 startVoiceInput(): void; stopVoiceInput(): void; // 텍스트 입력 sendText(text: string): void; // 아바타 제어 setEmotion(emotion: string): void; setGesture(gesture: string): void; } ``` ### 2. 시그널링 서버 ```python # server/signaling.py from fastapi import FastAPI, WebSocket from aiortc import RTCPeerConnection, RTCSessionDescription app = FastAPI() class SignalingServer: def __init__(self): self.connections: dict[str, RTCPeerConnection] = {} async def handle_offer(self, ws: WebSocket, offer: dict): """WebRTC Offer 처리""" pc = RTCPeerConnection() # 비디오 트랙 추가 (립싱크 출력) video_track = AvatarVideoTrack() pc.addTrack(video_track) # 오디오 트랙 추가 (TTS 출력) audio_track = TTSAudioTrack() pc.addTrack(audio_track) # Answer 생성 await pc.setRemoteDescription( RTCSessionDescription(sdp=offer['sdp'], type=offer['type']) ) answer = await pc.createAnswer() await pc.setLocalDescription(answer) return {'sdp': pc.localDescription.sdp, 'type': 'answer'} ``` ### 3. 오디오 파이프라인 ```python # server/audio_pipeline.py import asyncio from faster_whisper import WhisperModel import webrtcvad class AudioPipeline: def __init__(self): self.stt = WhisperModel("base", device="cuda") self.vad = webrtcvad.Vad(3) # Aggressiveness level 3 self.audio_buffer = bytearray() async def process_audio(self, audio_chunk: bytes) -> str | None: """음성 데이터 처리""" # VAD로 음성 구간 감지 is_speech = self.vad.is_speech(audio_chunk, 16000) if is_speech: self.audio_buffer.extend(audio_chunk) elif len(self.audio_buffer) > 0: # 음성 끝 - STT 실행 text = await self.transcribe(bytes(self.audio_buffer)) self.audio_buffer.clear() return text return None async def transcribe(self, audio: bytes) -> str: """Whisper로 음성→텍스트 변환""" segments, _ = self.stt.transcribe(audio) return " ".join([s.text for s in segments]) ``` ### 4. AI 파이프라인 ```python # server/ai_pipeline.py import google.generativeai as genai class AIPipeline: def __init__(self, api_key: str): genai.configure(api_key=api_key) self.model = genai.GenerativeModel('gemini-2.0-flash') self.context = [] async def generate_response(self, user_input: str) -> AsyncIterator[str]: """스트리밍 응답 생성""" self.context.append({"role": "user", "parts": [user_input]}) response = await self.model.generate_content_async( self.context, stream=True ) full_response = "" async for chunk in response: if chunk.text: full_response += chunk.text yield chunk.text self.context.append({"role": "model", "parts": [full_response]}) ``` ### 5. 비디오 파이프라인 (립싱크) ```python # server/video_pipeline.py from musetalk.inference import MuseTalkInference import numpy as np class VideoPipeline: def __init__(self, avatar_path: str): self.musetalk = MuseTalkInference() self.avatar_frames = self.load_avatar(avatar_path) self.current_frame = 0 async def generate_frame(self, audio_features: np.ndarray) -> np.ndarray: """오디오 특징에 맞는 립싱크 프레임 생성""" # MuseTalk으로 립싱크 프레임 생성 frame = self.musetalk.generate( source_image=self.avatar_frames[0], audio_features=audio_features ) return frame def encode_frame(self, frame: np.ndarray) -> bytes: """H.264로 프레임 인코딩""" # GPU 가속 인코딩 (NVENC) return self.encoder.encode(frame) ``` ## 데이터 흐름 ``` ┌─────────────────────────────────────────────────────────────────┐ │ Data Flow Diagram │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. 사용자 음성 입력 │ │ ┌──────┐ WebRTC ┌──────┐ │ │ │ Mic │ ──────────────▶│ VAD │ │ │ └──────┘ └──┬───┘ │ │ │ │ │ 2. 음성 인식 (STT) │ │ │ ┌──────▼──────┐ │ │ │ Whisper │ │ │ │ (STT) │ │ │ └──────┬──────┘ │ │ │ text │ │ 3. AI 응답 생성 │ │ │ ┌──────▼──────┐ │ │ │ Gemini │ │ │ │ (LLM) │ │ │ └──────┬──────┘ │ │ │ response (streaming) │ │ 4. 음성 합성 (TTS) │ │ │ ┌──────▼──────┐ │ │ │ TTS │ │ │ │ (ElevenLabs)│ │ │ └──────┬──────┘ │ │ │ audio │ │ 5. 립싱크 생성 │ │ │ ┌──────▼──────┐ │ │ │ MuseTalk │ │ │ │ (Lip Sync) │ │ │ └──────┬──────┘ │ │ │ video frames │ │ 6. 스트리밍 출력 │ │ │ ┌──────▼──────┐ WebRTC ┌────────┐ │ │ │ Encoder │ ──────────────▶│ Client │ │ │ │ (H.264/VP9) │ └────────┘ │ │ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ## 지연 시간 목표 | 단계 | 목표 지연 | 최적화 방법 | |------|----------|------------| | VAD | < 30ms | 로컬 처리 | | STT | < 150ms | Whisper Streaming | | LLM | < 300ms | Gemini Flash + Streaming | | TTS | < 100ms | Chunk 기반 스트리밍 | | Lip Sync | < 50ms | GPU 가속 (MuseTalk) | | Encoding | < 20ms | NVENC | | Network | < 50ms | Edge Server + WebRTC | | **Total** | **< 700ms** | | ## 기술 스택 요약 | 계층 | 기술 | |------|------| | Frontend | React/Next.js, WebRTC, Web Audio API | | Signaling | FastAPI, WebSocket | | STT | Faster-Whisper (GPU) | | LLM | Gemini 2.0 Flash | | TTS | ElevenLabs / Google TTS | | Lip Sync | MuseTalk | | Encoding | NVENC (H.264/VP9) | | Infra | Cloudflare (Edge), GPU Server (NVIDIA) | ## 다음 단계 (v3) 핵심 기술 스택을 선정하고, 각 컴포넌트의 구체적인 구현 계획을 수립합니다. --- *이 시리즈는 총 10개의 포스트로 구성되어 있습니다.*