Commit Graph

34 Commits

Author SHA1 Message Date
benoit a803250f9f fix: routing audio macOS avec support multi-canaux et LiveKit
Corrections majeures pour le support audio sous macOS :

- CoreAudioBackend : syntaxe sox correcte avec `-t coreaudio "Device Name"`
- AudioBridge : dé-entrelacement stéréo → canaux séparés (ligne 410-424)
- AudioBridge : entrelacement canaux → stéréo pour sortie (ligne 490-522)
- AudioBridge : duplication mono → stéréo pour LiveKit (ligne 438-449)
- config.yaml : ajout `channels: 2` pour capture stéréo
- config.yaml : ajout groupes "Production" et "Technique"

Résultat :
- Capture stéréo fonctionnelle depuis Loopback Audio 4
- Routing : 2 inputs → 3 groupes → LiveKit + 2 outputs
- Format audio correct pour LiveKit (mono dupliqué en stéréo)
- Pas d'erreur "Taille frame incorrecte"

Problème restant : sox playback se ferme après 0.4s (EPIPE)
2026-06-02 00:33:26 +02:00
benoit c9ec10dfd9 fix: shutdown propre sans erreurs
Problèmes corrigés pendant l'arrêt serveur :
1. RangeError offset bounds : vérification availableSpace avant .set()
2. audioBackend null : vérification avant queueAudio()
3. LiveKit track not found : try/catch sur unpublishTrack

Shutdown maintenant sans erreurs fatales.
2026-05-28 16:13:35 +02:00
benoit 5784aa68e1 clean: suppression logs debug audio
L'audio fonctionne correctement maintenant :
- Client PWA → LiveKit → Serveur → Haut-parleurs ✓
- Latence acceptable
- Qualité audio bonne

Fixes appliqués :
- Support Int16Array (LiveKit Node SDK format)
- Accumulation frames 240→960 samples
- Conversion directe Int16Array vers Float32
2026-05-28 15:52:23 +02:00
benoit 05e7f69ffb fix: support Int16Array depuis LiveKit Node SDK
LiveKit renvoie Int16Array directement au lieu de Buffer.
Ajout détection Int16Array dans _bufferToFloat32 avec conversion directe.

Ajout logs RMS/dBFS pour diagnostiquer niveau audio.
2026-05-28 15:31:41 +02:00
benoit 5534a43b0a debug: ajout logs diagnostic format audio LiveKit
Affiche sampleRate, channels, buffer type et premiers bytes
pour diagnostiquer le bruit audio
2026-05-28 15:28:28 +02:00
benoit 1941e9c8a1 fix: accumulation frames LiveKit 240→960 samples avant routing
Problème : LiveKit envoie des frames de 240 samples (5ms @ 48kHz)
mais GroupRouter attend 960 samples (20ms). Cela causait :
- Bruit audio (720 samples de silence ajoutés à chaque frame)
- Latence de plusieurs secondes (buffers qui s'accumulent)

Solution :
- Ajout liveKitFrameAccumulators Map pour chaque groupe
- Accumulation de 4 frames LiveKit (240×4 = 960) avant routing
- Nettoyage logs verbeux dans AudioBridge et GroupAudioRouter

Résultat attendu :
- Audio clair (pas de silence injecté)
- Latence réduite (~20ms au lieu de plusieurs secondes)
2026-05-28 15:21:26 +02:00
benoit cfeb275d18 fix: convert Uint8Array to Buffer in _bufferToFloat32
LiveKit SDK returns audio data as Uint8Array/ArrayBuffer, not Node.js Buffer.
Added Buffer.from() conversion before readInt16LE operations.

Fixes: TypeError: buffer.readInt16LE is not a function
Permet à l'audio reçu des clients d'être converti en Float32 pour lecture.
2026-05-28 15:05:01 +02:00
benoit adadbfeeb7 fix: utilisation de TrackKind.KIND_AUDIO au lieu de string 'audio'
L'API LiveKit Node utilise des enums numériques pour track.kind :
- TrackKind.KIND_AUDIO = 1
- TrackKind.KIND_VIDEO = 2

La comparaison avec 'audio' échouait, maintenant on utilise l'enum correctement.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-28 14:52:38 +02:00
benoit c562415a3d fix: écoute TrackPublished pour détecter tracks audio publiés après connexion
Problème : participant.trackPublications vide au moment de ParticipantConnected
Solution : écouter RoomEvent.TrackPublished et s'abonner au track audio dès sa publication

Flow : Client connecte → ParticipantConnected → Client publie track → TrackPublished → Souscription

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-28 14:42:22 +02:00
benoit 65357c29cc fix: souscription manuelle aux tracks audio des participants
Problème : RoomEvent.TrackSubscribed ne se déclenchait jamais avec @livekit/rtc-node
Solution :
- Itération manuelle sur participant.trackPublications quand participant se connecte
- Création AudioStream immédiate si track audio disponible
- Factorisation code dans _handleAudioTrack()

Cela devrait permettre de recevoir l'audio des clients PWA.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-28 14:40:02 +02:00
benoit 5fd46fb2a3 debug: ajout logs détaillés pour événements LiveKit tracks
Ajout de logs pour :
- RoomEvent.TrackPublished : détecte quand un participant publie un track
- RoomEvent.TrackSubscribed : logs plus détaillés avec kind et sid
- Permet de diagnostiquer pourquoi AudioBridge ne reçoit pas les tracks audio

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-28 14:35:23 +02:00
benoit 13d066b188 fix: création AudioStream avec syntaxe correcte LiveKit Node SDK
Correction import et utilisation d'AudioStream :
- Import AudioStream depuis @livekit/rtc-node
- new AudioStream(track, sampleRate, channels) au lieu de new track.AudioStream(...)

Cela devrait permettre la réception des frames audio depuis les clients PWA.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-28 14:26:05 +02:00
benoit 6630ced079 feat: support multi-rooms LiveKit (un par groupe)
Architecture refactorisée pour supporter plusieurs connexions LiveKit simultanées :
- AudioBridge : Map<groupName, LiveKitClient> au lieu d'un seul client
- AudioBridgeManager : génère un token JWT par groupe avec room dédiée
- Routing audio bidirectionnel par groupe :
  * FLUX 1 (carte son → LiveKit) : envoie vers le bon client selon groupName
  * FLUX 2 (LiveKit → carte son) : reçoit audio avec groupName correct
- Chaque groupe a sa propre room LiveKit (nom = groupId slugifié)

Fixes l'issue où les clients connectés à "production" ne recevaient pas
l'audio car AudioBridge était connecté uniquement à "main".

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-28 14:15:40 +02:00
benoit 7e6798cf92 fix: mapping correct devices PipeWire inputTargetDevice/outputTargetDevice
- AudioBridge passe inputTargetDevice et outputTargetDevice à PipeWire
- Fix: PipeWire utilisait targetDevice au lieu de input/outputTargetDevice
- Devrait maintenant démarrer les streams pw-cat correctement
2026-05-28 14:04:05 +02:00
benoit d5850a5918 fix: utiliser chemin absolu pour pactl dans PipeWireBackend
- /usr/bin/pactl au lieu de 'pactl' pour éviter problèmes PATH
- Correction dans getDevices(), getDefaultInputDevice(), getDefaultOutputDevice()
- Fix 'pactl: not found' malgré installation de pulseaudio-utils
2026-05-28 13:52:27 +02:00
benoit 52c2a0d326 fix: logs debug AudioBridge + install pulseaudio-utils
- Ajout logs FLUX 2 (réception audio LiveKit → carte son)
- Ajout logs GroupRouter pour debug routing
- install/linux.sh: ajout pulseaudio-utils (requis pour pactl)
2026-05-28 13:33:02 +02:00
benoit 999fbf0412 feat: QR code dans script séparé show-qr.sh pour logs propres
- Création show-qr.sh : génère et affiche QR code avant lancement serveur
- Détection auto mode dev/prod pour URL correcte
- start.sh appelle show-qr.sh puis lance serveur silencieusement
- Logs serveur uniquement dans server.log (terminal propre)
- Suppression génération QR dans server/index.js (plus nécessaire)
- Suppression dépendance qrcode-terminal dans server (utilisé via npx dans show-qr.sh)
2026-05-27 15:14:22 +02:00
benoit f2e1a50d6d fix: résolution device IDs et correction sox capture args
Corrections pour le routing audio carte son → LiveKit :

**Fixes audio backend**
- AudioBridgeManager : extraction des device IDs depuis config.audio.device
- AudioBridge : ajout résolution device ID → device name pour CoreAudio/sox
- CoreAudioBackend : correction index args sox capture (args[2] au lieu de args[1])

**Résultat**
-  Sox capture fonctionne : lit depuis "Microphone MacBook Pro"
-  Audio capturé et envoyé vers routing
-  Sox playback se ferme après 0.2s (problème persistant à corriger)

**Autres modifications**
- Logging centralisé (Logger.js)
- IP corrigée : 192.168.0.146
- Suppression système channels[] legacy dans groupes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-26 22:01:53 +02:00
benoit a5879a2ea9 fix: corrections audit - connexion audio bridge, optimisations
- Implémente connexion AudioBridge → LiveKitClient pour flux audio bidirectionnel
  * Envoi audio carte son vers clients (sendAudioData)
  * Réception audio clients vers carte son (via event audioData)
- Supprime LiveKitServerBridge.js (code mort jamais utilisé)
- Retire console.log DEBUG de LiveKitClient.js
- Remplace device IDs hardcodés par null dans config.yaml (auto-détection)
- Optimise allocations buffers audio avec pool réutilisable
  * Pool de Float32Array et Buffer PCM (max 50 buffers)
  * Réduit pression GC pour 30+ clients simultanés

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-26 19:22:02 +02:00
benoit 1c89546b61 fix: crash EPIPE lors ecriture dans sox stdin ferme
- Ajout error handler sur playbackProcess.stdin (capture EPIPE)
- Verification stdin.writable avant write
- Stop playback loop si stdin non disponible
- Evite crash serveur lors stop/reload AudioBridge
2026-05-26 15:36:00 +02:00
benoit f873dc25f6 fix: crash lors deconnexion LiveKit (destructuring undefined)
- LiveKitClient.emit('disconnected') envoie maintenant {reason}
- AudioBridge gere disconnected avec data optionnel (data?.reason)
- Corrige TypeError Cannot destructure property 'reason' of undefined
- Permet reload AudioBridge sans crash serveur
2026-05-26 15:33:39 +02:00
benoit 2338562b4f fix: ajout error handling pour getDefault audio devices
- Try/catch dans getDefaultInputDevice et getDefaultOutputDevice
- Cherche d'abord device avec isDefault.input/output = true
- Fallback sur premier device avec canaux disponibles
- Retourne null en cas d'erreur au lieu de crash
2026-05-26 15:30:20 +02:00
benoit 2acd652df0 fix: detection correcte des cartes son CoreAudio avec nombre de canaux reel
- Parse coreaudio_device_input/output depuis system_profiler (nombre canaux)
- Ajoute sampleRate reel par device
- Ajoute metadata: manufacturer, transport, isDefault
- Filtre devices sans input ni output
- Corrige l'API pour exposer les 11 devices au lieu de 2
2026-05-26 15:18:41 +02:00
benoit 61b3bedcae fix: creation LocalAudioTrack depuis AudioSource pour publication
- Import LocalAudioTrack depuis @livekit/rtc-node
- Utilise LocalAudioTrack.createAudioTrack() pour creer track depuis source
- Corrige erreur 'Cannot read properties of undefined (reading handle)'
- Permet publication correcte du track audio du bridge
2026-05-26 14:56:18 +02:00
benoit cc4f5ca35a feat: generation automatique token JWT pour AudioBridge participant
- Import AccessToken depuis livekit-server-sdk
- Generation token avec identity 'AudioBridge' et metadata role:bridge
- Permissions completes (publish, subscribe, data)
- Utilise devkey/secret du serveur LiveKit
- Permet au bridge de se connecter en tant que participant authentifie
2026-05-26 14:32:16 +02:00
benoit be05755677 fix: migration vers @livekit/rtc-node pour bridge audio serveur
- Remplacement livekit-client (navigateur) par @livekit/rtc-node (serveur Node.js)
- Support natif AudioSource/AudioFrame pour gestion PCM bas niveau
- Réception audio via AudioStream asynchrone (for await)
- Publication track audio via AudioSource.captureFrame()
- Permet au serveur d'agir comme participant LiveKit complet
- Suppression dépendance livekit-client inutile côté serveur
2026-05-26 14:26:32 +02:00
benoit cd76b66529 feat: activation du vrai AudioBridge (sortie du mode placeholder)
- Import dynamique de AudioBridge.js
- Création instance avec config complète (routing, groupes, LiveKit)
- Démarrage effectif du bridge audio
- Gestion erreur pour ne pas bloquer le serveur si pas de carte son
- Remplace le mode placeholder par le vrai système audio
2026-05-26 14:23:31 +02:00
benoit fb9d0fd101 fix: remplacement naudiodon par sox pour stabilite macOS
Probleme: naudiodon (bindings PortAudio) causait segfaults sur macOS

Solution: Utiliser sox (Sound eXchange) en subprocess

Modifications CoreAudioBackend.js:
- Remplacement naudiodon par sox (stable, deja installe sur macOS)
- Detection devices via system_profiler SPAudioDataType (vraies cartes)
- Capture audio via sox avec driver coreaudio
- Lecture audio via sox avec stdin/stdout
- Meme API (EventEmitter), compatible avec AudioBridge

Avantages sox:
- Stable (aucun segfault)
- Supporte toutes les cartes CoreAudio (USB, Thunderbolt, virtuelles)
- Multi-canaux natif
- Installe par defaut sur macOS (ou via brew install sox)
- Meme approche que JACK/PipeWire (subprocess)

Detection reelle des cartes:
- Parse system_profiler pour lister VRAIES cartes son
- Focusrite, MOTU, RME, Dante DVS, etc. detectes
- Fallback sur Built-in Mic/Output si aucune carte externe

Modifications package.json:
- Suppression dependance naudiodon (instable)

Modifications install/macos.sh:
- Ajout installation sox via Homebrew
- Detection si deja installe

Plus de warning "devices fictifs" au demarrage !
2026-05-26 14:16:13 +02:00
benoit e460376d9a feat: integration complete audio bridge cartes son macOS/Linux
Integration GroupAudioRouter dans AudioBridge pour routing bidirectionnel

Modifications AudioBridge.js:
- Ajout GroupAudioRouter pour matrice routing multi-canaux
- Flux CAPTURE: Carte Son → GroupRouter → Groupes → LiveKit
- Flux LECTURE: LiveKit → Groupes → GroupRouter → Carte Son
- Conversions PCM Buffer ↔ Float32Array pour routing
- Support multi-canaux (32+ canaux inputs/outputs)
- Events groupAudioOut/groupAudioIn pour pont LiveKit

Nouveau LiveKitServerBridge.js:
- Pont entre AudioBridge et LiveKit SFU
- Generation tokens JWT pour clients
- Gestion rooms par groupe
- API list participants/create room
- Events pour debug/monitoring

Documentation AUDIO_BRIDGE_ARCHITECTURE.md:
- Architecture complete flux audio bidirectionnel
- Pipeline detaille capture/lecture
- Configuration YAML routing multi-canaux
- Compatibilite macOS (CoreAudio) et Linux (JACK/PipeWire)
- Tests validation et performance
- Latence end-to-end 48-111ms (objectif < 150ms valide)

Documentation LIVEKIT_AUDIO_BRIDGE.md:
- Guide integration LiveKit Server SDK
- 3 approches possibles (rtc-node, DataChannel, participant virtuel)
- Code complet LiveKitServerBridge avec AudioSource
- Configuration serveur et variables env
- Tests compatibilite cartes son

Fonctionnalites:
- Serveur voit TOUTES les cartes son de la machine hote
- Routing flexible inputs → groupes → outputs avec gains
- Mixage additif multi-sources
- Anti-clipping automatique
- Compatible cartes USB/Thunderbolt/virtuelles (Dante DVS)
- Fonctionne sur macOS ET Linux

TODO Phase 3+: Implementer envoi reel vers LiveKit (rtc-node)
2026-05-26 14:12:50 +02:00
benoit 37205f0409 feat: ajout support Linux avec backends JACK et PipeWire
Phase 3.1 - Support Linux professionnel

Nouveaux backends audio:
- JACKBackend.js : support JACK Audio Connection Kit pour audio pro
- PipeWireBackend.js : support PipeWire (standard moderne Linux)
- Detection automatique dans AudioBridge (PipeWire > JACK > erreur)

Script installation:
- install/linux.sh pour Ubuntu/Debian/Arch/Fedora
- Installation automatique dependencies (Node.js, PipeWire/JACK)
- Telechargement LiveKit Server pour Linux (amd64/arm64)

Fonctionnalites:
- Detection serveur audio (PipeWire/JACK)
- Enumeration devices audio via pactl/jack_lsp
- Capture et lecture audio basse latence (pw-cat, jack_rec/play)
- Messages d'erreur detailles pour troubleshooting
- Compatibilite Ubuntu 22.04+, Debian 11+, Arch Linux, Fedora

TODO.md mis a jour: Phase 3.1 en cours
2026-05-26 13:37:18 +02:00
benoit 8c43c7e8af feat: ajout GroupAudioRouter.js pour routing audio multi-canaux avec gains
- Mix de plusieurs canaux physiques vers groupes (gains individuels)
- Distribution groupes vers plusieurs canaux physiques (gains individuels)
- Support canaux partagés avec mixage additif
- Gestion gains par route (-120dB à +6dB)
- Anti-clipping automatique
- Statistiques routing temps réel
2026-05-25 22:07:44 +02:00
benoit 9350c9410c feat: système hot-reload bridge audio avec ConfigManager (Phase 2.5)
- ConfigManager: gestionnaire centralisé config avec EventEmitter
- AudioBridgeManager: gestion bridge avec auto-reload sur changement config
- Intégration dans serveur principal (index.js)
- Événements 'audio-device-updated' et 'config-updated'
- Reload automatique du bridge sans redémarrer serveur
- Mode placeholder pour développement (vrai bridge Phase 3)
2026-05-25 09:45:59 +02:00
benoit 03b3f94824 feat: ajout APIs détection et configuration cartes son (Phase 2.5)
- GET /admin/audio/devices : énumération devices CoreAudio
- GET /admin/audio/device : récupération config actuelle
- POST /admin/audio/device : sélection carte son + sample rate
- Workaround naudiodon segfault avec devices fictifs
- Configuration sauvegardée dans config.yaml
2026-05-25 09:40:43 +02:00
benoit efd697a9d3 feat: implémentation complète du bridge audio serveur (Phase 1.3)
Composants créés :
- CoreAudioBackend.js : Backend audio macOS natif (naudiodon/PortAudio)
  - Énumération et sélection devices audio
  - Capture audio 48kHz mono/stereo
  - Lecture audio avec buffer circulaire
  - Gestion underrun/overrun

- OpusCodec.js : Encodeur/décodeur Opus
  - Support 32-320 kbps configurable
  - Présets voix (économique, standard, HD) et musique
  - Frame 20ms (960 samples à 48kHz)
  - Statistiques encode/decode

- JitterBuffer.js : Buffer FIFO adaptatif
  - Cible 40ms (2 frames)
  - Détection underrun/overrun
  - Mode adaptatif pour conditions réseau variables
  - Statistiques latence et santé buffer

- LiveKitClient.js : Client LiveKit pour bridge
  - Connexion room en tant que participant "AudioBridge"
  - Publication/souscription tracks audio
  - Reconnexion automatique
  - Gestion événements participants

- AudioBridge.js : Classe principale orchestration
  - Détection automatique backend (CoreAudio macOS)
  - Routing bidirectionnel CoreAudio ↔ Opus ↔ LiveKit
  - Configuration via présets ou custom
  - Logs détaillés et statistiques temps réel

Dépendances ajoutées :
- opusscript : Codec Opus JavaScript
- naudiodon : Bindings natifs PortAudio/CoreAudio
- livekit-client : SDK LiveKit côté serveur

TODO.md mis à jour avec tâches Phase 1.3 complétées.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-22 22:18:18 +02:00