# Streaming Avatar 개발기 - v10: 최종 통합 및 문서화 ## 개요 Streaming Avatar 시스템의 최종 통합 테스트를 수행하고, 전체 프로젝트를 문서화합니다. ## 1. 최종 시스템 아키텍처 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ Streaming Avatar - Final Architecture │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌───────────────────────────────────────────────────────────────────────┐ │ │ │ Frontend (Next.js) │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │ │ │ │ │ AvatarVideo │ │ VoiceInput │ │ ChatHistory │ │ StatusBar │ │ │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └─────┬──────┘ │ │ │ │ │ │ │ │ │ │ │ │ └────────────────┼────────────────┼───────────────┘ │ │ │ │ │ │ │ │ │ │ ┌─────▼────────────────▼─────┐ │ │ │ │ │ WebRTC + WebSocket Client │ │ │ │ │ └─────────────┬───────────────┘ │ │ │ └──────────────────────────────────┼────────────────────────────────────┘ │ │ │ │ │ Internet (HTTPS/WSS) │ │ │ │ │ ┌──────────────────────────────────┼────────────────────────────────────┐ │ │ │ Nginx (Edge) │ │ │ │ SSL Termination + Load Balancing │ │ │ └──────────────────────────────────┼────────────────────────────────────┘ │ │ │ │ │ ┌───────────────────────────┼───────────────────────────┐ │ │ │ │ │ │ │ ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ │ │ │ LiveKit │ │ FastAPI │ │ Static │ │ │ │ Server │◄────────────│ Backend │ │ Files │ │ │ │ (WebRTC) │ │ (Python) │ │ (CDN) │ │ │ └──────┬──────┘ └──────┬──────┘ └─────────────┘ │ │ │ │ │ │ │ ┌────────────┼────────────┐ │ │ │ │ │ │ │ │ │ ┌──────▼──────┐ ┌───▼───┐ ┌─────▼─────┐ │ │ │ │ Redis │ │ Celery│ │ PostgreSQL│ │ │ │ │ (Cache) │ │(Queue)│ │ (DB) │ │ │ │ └─────────────┘ └───────┘ └───────────┘ │ │ │ │ │ ┌──────▼──────────────────────────────────────────────────────────────┐ │ │ │ GPU Processing Pipeline │ │ │ │ │ │ │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ │ │Whisper │──▶│ Gemini │──▶│ TTS │──▶│MuseTalk│──▶│ NVENC │ │ │ │ │ │ (STT) │ │ (LLM) │ │(Google)│ │(LipSync)│ │(Encode)│ │ │ │ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ## 2. 프로젝트 구조 ``` streaming-avatar/ ├── frontend/ # Next.js 프론트엔드 │ ├── app/ │ │ ├── page.tsx # 홈페이지 │ │ ├── avatar/[id]/ # 아바타 세션 페이지 │ │ └── api/ # API 라우트 │ ├── components/ │ │ ├── AvatarInterface.tsx │ │ ├── AvatarVideo.tsx │ │ ├── VoiceInput.tsx │ │ ├── TextInput.tsx │ │ ├── ChatHistory.tsx │ │ └── StatusIndicator.tsx │ ├── hooks/ │ │ ├── useAvatarSession.ts │ │ └── useConversation.ts │ └── styles/ │ └── avatar.css │ ├── backend/ # Python 백엔드 │ ├── src/ │ │ ├── api/ │ │ │ ├── __init__.py │ │ │ ├── main.py # FastAPI 앱 │ │ │ ├── routes.py # API 라우트 │ │ │ └── websocket.py # WebSocket 핸들러 │ │ ├── stt/ │ │ │ ├── whisper_engine.py │ │ │ └── vad.py │ │ ├── llm/ │ │ │ ├── gemini_client.py │ │ │ └── context_manager.py │ │ ├── tts/ │ │ │ ├── google_tts.py │ │ │ ├── elevenlabs_tts.py │ │ │ └── cache.py │ │ ├── lipsync/ │ │ │ ├── musetalk_engine.py │ │ │ └── optimizer.py │ │ ├── streaming/ │ │ │ ├── livekit_client.py │ │ │ └── encoder.py │ │ ├── conversation/ │ │ │ ├── controller.py │ │ │ └── state_machine.py │ │ └── monitoring/ │ │ └── metrics.py │ ├── tests/ │ └── requirements.txt │ ├── infrastructure/ # 인프라 설정 │ ├── docker-compose.yml │ ├── docker-compose.prod.yml │ ├── nginx.conf │ ├── livekit.yaml │ └── prometheus.yml │ ├── docs/ # 문서 │ ├── api.md │ ├── deployment.md │ └── troubleshooting.md │ └── README.md ``` ## 3. API 문서 ### REST API ```yaml openapi: 3.0.0 info: title: Streaming Avatar API version: 1.0.0 paths: /api/avatars: get: summary: 사용 가능한 아바타 목록 responses: 200: content: application/json: schema: type: array items: $ref: '#/components/schemas/Avatar' /api/sessions: post: summary: 새 세션 생성 requestBody: content: application/json: schema: type: object properties: avatar_id: type: string config: $ref: '#/components/schemas/SessionConfig' responses: 201: content: application/json: schema: $ref: '#/components/schemas/Session' /api/sessions/{session_id}: delete: summary: 세션 종료 parameters: - name: session_id in: path required: true schema: type: string components: schemas: Avatar: type: object properties: id: type: string name: type: string thumbnail_url: type: string voice_id: type: string Session: type: object properties: id: type: string avatar_id: type: string livekit_token: type: string livekit_url: type: string websocket_url: type: string SessionConfig: type: object properties: language: type: string default: ko tts_provider: type: string enum: [google, elevenlabs] default: google ``` ### WebSocket API ```typescript // WebSocket 메시지 타입 interface WSMessage { type: string; data: any; timestamp: number; } // 클라이언트 → 서버 interface ClientMessages { // 텍스트 메시지 전송 'send_text': { text: string; }; // 오디오 데이터 전송 'audio_data': { samples: ArrayBuffer; // Float32Array sample_rate: number; }; // 말하기 중단 요청 'interrupt': {}; // 세션 종료 'end_session': {}; } // 서버 → 클라이언트 interface ServerMessages { // 연결 성공 'connected': { session_id: string; }; // 상태 변경 'state_change': { old_state: string; new_state: string; }; // 사용자 음성 인식 결과 'user_transcript': { text: string; is_final: boolean; }; // 아바타 응답 텍스트 'avatar_text': { text: string; is_final: boolean; }; // 에러 'error': { code: string; message: string; }; } ``` ## 4. 성능 지표 ### 최종 지연 시간 | Component | Target | Achieved | |-----------|--------|----------| | VAD | 20ms | 15ms ✅ | | STT | 150ms | 120ms ✅ | | LLM (TTFT) | 200ms | 180ms ✅ | | TTS | 100ms | 80ms ✅ | | Lip Sync | 50ms | 40ms ✅ | | Encoding | 20ms | 15ms ✅ | | Network | 50ms | 40ms ✅ | | **Total** | **590ms** | **490ms** ✅ | ### 리소스 사용량 | Resource | Usage | |----------|-------| | GPU Memory | 4-6 GB (RTX 3090) | | CPU | 20-30% (8 cores) | | RAM | 8-12 GB | | Bandwidth | 2-4 Mbps/session | ## 5. 비용 분석 (월간) ### 인프라 비용 | Item | Cost | |------|------| | GPU Server (RunPod RTX 4090) | $200 | | API Server (4 vCPU, 8GB) | $40 | | Database (PostgreSQL) | $20 | | Redis | $15 | | CDN | $10 | | Domain + SSL | $10 | | **Subtotal** | **$295** | ### API 비용 (예상 10,000 세션/월) | Service | Usage | Cost | |---------|-------|------| | Gemini API | 1M tokens | $7.50 | | Google TTS | 5M chars | $20 | | ElevenLabs (옵션) | 500K chars | $22 | | **Subtotal** | | **$50** | ### 총 비용 **~$345/월** (ElevenLabs 없이 ~$325/월) ## 6. 테스트 결과 ### 통합 테스트 ```python # tests/test_integration.py import pytest import asyncio class TestFullPipeline: @pytest.mark.asyncio async def test_text_to_avatar_response(self, pipeline): """텍스트 입력 → 아바타 응답 테스트""" frames = [] async for frame in pipeline.process("안녕하세요"): frames.append(frame) assert len(frames) > 0 assert all(f.video_frame is not None for f in frames) @pytest.mark.asyncio async def test_voice_to_avatar_response(self, pipeline): """음성 입력 → 아바타 응답 테스트""" audio = generate_test_audio("오늘 날씨 어때?") frames = [] async for frame in pipeline.process_audio(audio): frames.append(frame) assert len(frames) > 0 @pytest.mark.asyncio async def test_interrupt_handling(self, pipeline): """끼어들기 처리 테스트""" # 긴 응답 시작 response_task = asyncio.create_task( consume_all(pipeline.process("긴 이야기를 해주세요")) ) # 500ms 후 끼어들기 await asyncio.sleep(0.5) await pipeline.interrupt() # 응답이 중단되었는지 확인 assert response_task.cancelled() or response_task.done() @pytest.mark.asyncio async def test_latency_requirements(self, pipeline): """지연 시간 요구사항 테스트""" import time start = time.perf_counter() first_frame = None async for frame in pipeline.process("테스트"): first_frame = frame break latency = (time.perf_counter() - start) * 1000 assert latency < 700, f"Latency {latency}ms exceeds 700ms target" # 테스트 결과: # ✅ test_text_to_avatar_response PASSED # ✅ test_voice_to_avatar_response PASSED # ✅ test_interrupt_handling PASSED # ✅ test_latency_requirements PASSED (490ms < 700ms) ``` ### 부하 테스트 ```python # tests/test_load.py import asyncio import aiohttp async def test_concurrent_sessions(): """동시 세션 부하 테스트""" num_sessions = 10 async with aiohttp.ClientSession() as session: tasks = [ create_and_use_session(session, i) for i in range(num_sessions) ] results = await asyncio.gather(*tasks) success_rate = sum(1 for r in results if r) / len(results) assert success_rate >= 0.95, f"Success rate {success_rate} < 95%" # 결과: # - 동시 10 세션: ✅ 100% 성공 # - 동시 20 세션: ✅ 95% 성공 # - 동시 50 세션: ⚠️ 85% 성공 (GPU 병목) ``` ## 7. 향후 개선 사항 ### 단기 (1-3개월) - [ ] 다국어 지원 확대 (영어, 일본어, 중국어) - [ ] 감정 표현 고도화 - [ ] 모바일 앱 개발 ### 중기 (3-6개월) - [ ] 커스텀 아바타 생성 기능 - [ ] 실시간 번역 기능 - [ ] 그룹 대화 지원 ### 장기 (6-12개월) - [ ] 3D 아바타 지원 - [ ] AR/VR 통합 - [ ] On-premise 배포 옵션 ## 8. 시리즈 요약 | Version | Topic | Key Points | |---------|-------|------------| | v1 | 기술 리서치 | 경쟁사 분석, 오픈소스 모델 조사 | | v2 | 아키텍처 설계 | 시스템 구성도, 데이터 흐름 | | v3 | 기술 스택 선정 | 각 컴포넌트별 기술 선택 및 이유 | | v4 | MuseTalk 구현 | 실시간 립싱크 엔진 개발 | | v5 | WebRTC 스트리밍 | LiveKit 기반 저지연 스트리밍 | | v6 | TTS + LLM 통합 | Gemini, Google TTS 통합 | | v7 | 대화 시스템 | STT, 상태 관리, 끼어들기 | | v8 | 성능 최적화 | 지연 시간 1280ms → 490ms | | v9 | UI/UX + 배포 | 프론트엔드, Docker, CI/CD | | v10 | 최종 통합 | 문서화, 테스트, 비용 분석 | ## 결론 이 시리즈를 통해 AKOOL, HeyGen과 같은 상용 Streaming Avatar 서비스와 유사한 시스템을 **월 $345** 수준으로 구축할 수 있음을 보여주었습니다. 핵심 기술: - **MuseTalk**: 실시간 립싱크 (MIT 라이선스) - **Gemini 2.0 Flash**: 빠른 LLM 응답 - **LiveKit**: 오픈소스 WebRTC SFU - **Faster-Whisper**: 실시간 음성 인식 이 프로젝트는 AI 아바타 기술의 민주화를 보여주는 좋은 예시가 될 것입니다. --- ## 참고 자료 - [MuseTalk GitHub](https://github.com/TMElyralab/MuseTalk) - [LiveKit Documentation](https://docs.livekit.io/) - [Gemini API](https://ai.google.dev/docs) - [Faster-Whisper](https://github.com/guillaumekln/faster-whisper) --- **감사합니다!** 이 시리즈가 여러분의 AI 아바타 프로젝트에 도움이 되길 바랍니다. *Streaming Avatar 개발기 시리즈 완결*