📝 Note
pro/translatert/architecture
translatertaudiowebrtclivekitopenai-realtimeffmpegdebounce
Architecture — TranslateRT
Liens : Decisions · Journal
Vue d’ensemble
Plateforme LAN-only. Contraintes : latence < 3s bout-en-bout, 1 événement simultané, HTTPS obligatoire.
Composants principaux
| Composant | Tech | Port |
|---|---|---|
| Backend | Node.js 22 + Fastify 5 + TypeScript | :3001 |
| SFU | LiveKit Server | :7880 |
| Reverse proxy | Caddy 2 TLS DNS-01 | :8443 |
| Frontend | Next.js 15 export statique | via Caddy |
| IA | OpenAI Realtime API (5 sessions WS) | sortant |
Monorepo pnpm : backend/ · frontend/ · shared/ · config/ · deploy/ · src-tauri/
Flux de données
Pipeline audio bout-en-bout
Dante 48kHz (réseau AV)
└─ CoreAudio / DVS [avfoundation device 2]
└─ ffmpeg → PCM16 24kHz mono
└─ gpt-realtime-whisper → transcription source (FR)
└─ gpt-realtime-translate → EN ─┐
└─ gpt-realtime-translate → DE ─┤ PCM16 24kHz
└─ gpt-realtime-translate → IT ─┼─→ LiveKit (1 track Opus/langue)
└─ gpt-realtime-translate → ES ─┘ └─ WebRTC → navigateur
Flux transcript WS (backend → frontend)
TranslateStream → "output-transcript" { delta, full }
delta = texte CUMULATIF OpenAI (rolling) → metrics.outputTranscript = delta [2026-06-01]
→ pipeline.emitAdmin({ text: e.full }) ← texte complet courant
→ WS /api/listener/events?lang=xx
→ debounce 400ms → setSegments(segmentText(event.text)) [2026-06-01]
Flux DisplayView (page /display)
WS /api/listener/events (toutes langues)
→ debounce 200ms par langue → segmentText(event.text) direct [2026-06-01]
→ timeout transcriptTimeoutMs (défaut 5000ms) → suppression entrée
Flux client (EventListener.tsx)
Clic langue → POST /api/listener/token
→ Room.connect({ autoSubscribe: true, webAudioMix: false }) [2026-06-01]
→ TrackSubscribed → attachPublisherAudio() → <audio hidden>
→ WebSocket events → debounce 400ms → segmentText(event.text)
Dépendances externes
| Service | Usage | Criticité |
|---|---|---|
| OpenAI Realtime API | Transcription + traduction S2S | Critique |
| LiveKit Server | SFU WebRTC | Critique |
| Dante / DVS | Source audio | Critique |
| Let’s Encrypt DNS-01 | TLS LAN | Haute |
Tauri V2 (branch tauri/mac-mini)
Sidecars embarqués dans .app (aarch64-apple-darwin) :
node (SEA) · livekit-server · caddy · libnode.127.dylib
Config : ~/Library/Application Support/com.translatert.app/
Logs : ~/Library/Application Support/com.translatert.app/logs/translatert.log
Schémas
VLAN A (Dante) Mac mini (10.130.26.13) VLAN B (Wi-Fi)
┌─────────────┐ ┌──────────────────────────┐ ┌────────────┐
│ Console audio│─DVS─▶ ffmpeg → Backend Fastify │ │ navigateur │
└─────────────┘ │ → OpenAI Realtime (5 WS) │─WebRTC→ spectateur│
│ → LiveKit SFU :7880 │ └────────────┘
│ → Caddy :8443 (TLS) │
└──────────────────────────┘
▲ QR code HTTPS