📝 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

ComposantTechPort
BackendNode.js 22 + Fastify 5 + TypeScript:3001
SFULiveKit Server:7880
Reverse proxyCaddy 2 TLS DNS-01:8443
FrontendNext.js 15 export statiquevia Caddy
IAOpenAI 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

ServiceUsageCriticité
OpenAI Realtime APITranscription + traduction S2SCritique
LiveKit ServerSFU WebRTCCritique
Dante / DVSSource audioCritique
Let’s Encrypt DNS-01TLS LANHaute

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