Un participant serveur peut être configuré sans publier de micro —
il reçoit le mix du groupe et le sort sur un canal physique.
- ServerAudioUser: flag publish (défaut true), sendAudio no-op si false
- AudioBridgeManager: canPublish LiveKit selon flag, input_channel null si écoute
- AudioBridge: passe publish à ServerAudioUser, log adapté
- Electron UI: checkbox "Écoute seule" dans add/edit, badges 🎤/👂 dans table
- main.js IPC: persist publish + input_channel null en écoute
Le paradigme devient : pour brancher un canal physique sur un groupe,
créer un server audio user. Les matrices sont retirées de l'UI Electron,
de l'admin PWA, de l'API REST et du backend (GroupAudioRouter supprimé).
AudioBridgeManager ne génère plus de tokens per-group.
Option "aucune sortie" ajoutée pour les server audio users.
Chaque server audio user est un participant LiveKit indépendant géré par le serveur :
- publie un canal physique d'entrée comme track audio
- reçoit et mixe l'audio de tous les autres participants (mix-minus naturel)
- sort le mix vers un canal physique dédié
Nouvelle classe ServerAudioUser.js, intégration dans AudioBridge et AudioBridgeManager,
section server_audio_users dans config.yaml (vide par défaut, exemple commenté).
- Ajout du package yaml dans electron pour parser config.yaml
- Handlers IPC groups:list/create/update/delete lisent/écrivent config.yaml
directement depuis le Main Process (sans serveur requis)
- fetchGroups() utilise toujours IPC (plus d'appel REST pour la lecture)
- editGroup/deleteGroup/addGroup : REST API si serveur actif, IPC sinon
- loadViewData : onglet Groupes chargé même si serveur arrêté
- Note affichée quand le serveur est arrêté : modifications appliquées
au prochain démarrage
Electron bloque prompt() et confirm() dans le renderer process.
Ajout d'un showModal() générique (champs configurables, mode confirmation)
avec overlay, focus auto, Escape/Enter, et fermeture en cliquant l'overlay.
Tous les appels prompt/confirm dans editGroup, deleteGroup et addGroup
sont migrés vers showModal.
- Onglet Groupes : boutons Modifier et Supprimer fonctionnels via délégation
d'événements et data-attributes ; slugify() côté client synchronisé avec
le serveur ; classe CSS btn-danger pour Supprimer
- Export logs : bouton "Exporter JSON" dans l'onglet Logs (filtre niveau actif)
- Export/Import config.yaml : section dédiée dans Configuration avec dialog
système (backup automatique .bak avant import) via IPC Electron
(config:export / config:import dans main.js + preload.js)
Statut serveur :
- SERVER_URL utilisait "localhost", que le Node embarqué par Electron peut
résoudre en IPv6 (::1) en priorité ; le serveur n'écoutant qu'en IPv4
(host: 0.0.0.0), le ping de statut échouait silencieusement alors que le
serveur tournait. Bascule sur 127.0.0.1 (main.js + preload.js).
- L'erreur réelle de pingServer() n'était jamais remontée au renderer
(health.error perdu) ; elle est maintenant incluse dans la réponse IPC.
URL/QR code clients :
- L'URL affichée utilisait un remplacement de chaîne ("localhost" -> IP) qui
ne matchait plus rien depuis le passage à 127.0.0.1 ; remplacé par un
parsing d'URL qui ne réutilise que le protocole/port.
- Le QR code dépendait d'une lib chargée depuis un CDN externe, inadapté à
une app self-hosted censée fonctionner sans accès Internet sur le WiFi
d'un événement. Généré désormais côté Main Process avec la lib qrcode
(déjà en dépendance, jamais utilisée) et transmis au renderer en data URL ;
suppression du fichier placeholder et de la dépendance CDN.
- getNetworkIP() lisait /admin/config, qui renvoie la valeur YAML brute
"AUTO" (jamais résolue), donc retombait toujours sur "localhost".
Remplacé par la détection réseau du Main Process (même logique que pour
les certificats mkcert).
- Ajout d'un placeholder visuel (icône + message) tant qu'aucun QR code
n'est généré ou que le serveur est arrêté, en CSS pur.
ENABLE_HTTPS était lu depuis l'environnement sans jamais être positionné par le
flow Electron (start-desktop.sh → electron .), donc le serveur enfant tournait
toujours en HTTP malgré le setup mkcert automatique au premier lancement.
ENABLE_HTTPS est désormais activé par défaut (ENABLE_HTTPS=false pour revenir
en HTTP explicitement).
Corrections induites par ce changement de protocole par défaut :
- pingServer() utilisait le module http en dur même en HTTPS ; bascule sur
https avec rejectUnauthorized: false (ping local vers notre propre process
enfant, le module https de Node ne lisant pas le trousseau macOS où mkcert
installe sa CA, contrairement à Safari/Chrome/Electron renderer).
- Le dashboard (electron/ui/app.js) avait l'URL de l'API et celle du
WebSocket VU-mètres codées en dur en http/ws ; elles utilisent maintenant
l'URL réelle exposée par preload.js (serverUrl), cohérente avec le
protocole effectif du serveur.
AudioLevelsServer s'auto-attachait à l'événement 'upgrade' du serveur HTTP
via la lib ws (server + path), en plus du listener manuel du proxy LiveKit.
Pour toute connexion /livekit, les deux listeners s'exécutaient : le proxy
LiveKit aboutissait bien côté upstream, mais le listener ws (path
/audio-levels ne matchant pas) appelait abortHandshake(socket, 400) sur le
même socket juste après, cassant la connexion côté client en HTTPS prod.
AudioLevelsServer passe maintenant en noServer: true et expose
handleUpgrade(), appelée par un dispatcher 'upgrade' unique dans
server/index.js qui route explicitement par chemin (/livekit vs
/audio-levels).
Ajout de certs/ au .gitignore (clés privées SSL locales mkcert).
http-proxy-middleware ne gere pas correctement WebSocket upgrade avec HTTPS.
Utilisation de http-proxy natif pour proxy direct WSS vers WS.
Modifications:
- Remplacement createProxyMiddleware par httpProxy.createProxyServer
- Gestion native de l'upgrade WebSocket
- Reecriture URL /livekit -> / pour LiveKit
- Logs info niveau pour debug facilite
Correction detection du protocole pour utiliser le bon endpoint LiveKit.
Modifications:
- client/src/App.jsx: detection HTTPS au lieu de import.meta.env.DEV
- Si HTTPS: utiliser wss://host/livekit (proxy)
- Si HTTP: utiliser URL LiveKit directe
Probleme resolu:
- Mixed content error (HTTPS ne peut pas WS)
- Fonctionne maintenant en prod HTTPS build
Permet au client PWA charge en HTTPS de se connecter a LiveKit via proxy WSS.
Modifications:
- server/index.js: ajout proxy http-proxy-middleware
- Route /livekit proxie vers http://localhost:7880
- Upgrade WebSocket active pour le proxy
- server/package.json: ajout dependance http-proxy-middleware
Fonctionnement:
- Client HTTPS se connecte a wss://localhost:3000/livekit
- Serveur Express proxie vers ws://localhost:7880
- Resout probleme mixed content (HTTPS ne peut pas WS)
Ajout connexion WebSocket temps reel pour monitoring audio dans l'app Electron.
Modifications:
- electron/ui/app.js: connexion WebSocket /audio-levels
- Rendu VU-metres pour inputs/groups/outputs
- Reconnexion automatique en cas de deconnexion
- Gestion cycle de vie (demarrage/arret serveur)
- electron/ui/styles.css: styles pour VU-metres
- Barres horizontales avec couleurs (vert/jaune/rouge)
- Indicateur peak temps reel
- Animation clipping si saturation
- DESKTOP-APP.md: marque TODO comme complete
Fonctionnalites:
- Affichage niveaux RMS et peak en dBFS
- Detection clipping avec animation
- Status connexion WebSocket visible
- Mise a jour 20 fois/seconde (50ms)
- Sections separees: entrees, groupes, sorties
Problème : mainWindow.webContents.send() appelé avant que la page soit chargée
→ Events perdus, interface ne se met pas à jour
Solution :
- Nouveau flag rendererReady
- Event 'did-finish-load' pour détecter quand le renderer est prêt
- Tous les webContents.send() vérifient maintenant rendererReady
- Envoi de l'état initial du serveur quand interface charge
Résultat : Interface reçoit toujours les updates d'état serveur
Nouveau : setup-helper.js
- Détecte si mkcert est installé
- Installe mkcert automatiquement (Homebrew macOS, curl Linux)
- Installe CA locale (mkcert -install)
- Génère certificats pour localhost + IP réseau
- Détection automatique IP WiFi
Intégration dans main.js :
- Vérifie certificats au démarrage
- Si absents : dialog onboarding + setup auto
- Dialog progress "Configuration en cours..."
- Dialog success avec IP réseau
- Dialog error si échec (fallback manuel)
- Ne démarre serveur que si certificats OK
Expérience utilisateur :
1. Lancer l'app (première fois)
2. Dialog : "Première utilisation, configuration..."
3. Cliquer "Continuer"
4. Attendre 1-2 min (installation mkcert + CA + certificats)
5. Dialog : "Configuration terminée, IP: 192.168.x.x"
6. Serveur démarre automatiquement
Prochaines fois : détection certificats OK → démarre direct
L'utilisateur n'a RIEN à faire manuellement !
Les handlers ipcMain.handle() doivent être définis après app.whenReady()
sinon ipcMain est undefined
Résout: TypeError: Cannot read properties of undefined (reading 'handle')
- Logs LiveKit vont dans stderr (normal pour Go), ne pas traiter comme erreurs
- Transmettre tous les logs au renderer (stdout + stderr)
- Détecter "Serveur prêt" dans stdout pour confirmer démarrage
- Timeout augmenté à 15s avec health check avant de résoudre
- Suppression filtres logs verbeux qui cachaient les messages importants
Résout : serveur tué immédiatement après démarrage
Problème résolu : certificats self-signed bloqués par navigateurs
Solution : mkcert génère certificats automatiquement approuvés
- CA locale installée sur système
- Certificats signés par cette CA
- Navigateurs font confiance automatiquement
- Pas de warnings SSL
- 100% local, pas de cloud/domaine
Nouveau script : setup-certificates.sh
- Installe mkcert (Homebrew/apt)
- Installe CA locale (mkcert -install)
- Détecte IP réseau automatiquement
- Génère certificats localhost + IP + *.local
- Configure server/.env (SSL_CERT, SSL_KEY)
- Configure client/.env (VITE_SERVER_URL)
- Met à jour vite.config.js avec HTTPS
Serveur modifié : server/index.js
- Lit certificats depuis process.env.SSL_CERT/SSL_KEY
- Fallback : ../certs/localhost.pem
- Message erreur si certificats introuvables
Documentation :
- SSL-SETUP.md : guide complet installation manuelle/auto
- SSL-SOLUTION.md : résumé technique
- README.md : ajout étape setup-certificates.sh
Résultat :
- Cadenas vert sur desktop (Chrome/Safari/Firefox)
- WebRTC fonctionne en HTTPS
- Smartphones : accepter certificat une fois (normal)
- Valable 10 ans, pas de renouvellement
Usage : ./setup-certificates.sh (2 minutes)
Ensuite : ./start.sh --dev ou ./start-desktop.sh
- Ajout buffer d'accumulation dans PipeWireBackend (même pattern que CoreAudio)
- Ajout buffer d'accumulation dans JACKBackend
- pw-cat et jack_rec émettent aussi des chunks de taille variable
- Garantit frames fixes (960 samples) sur tous les backends
- Prévient audio haché/robotique sous Linux
Problème:
- Son complètement déformé (clipping massif)
- CoreAudio capture en 32-bit mais traité comme 16-bit
- Mixage additif sans normalisation
Solution:
1. Sox convertit 32→16 bit automatiquement
2. GroupAudioRouter divise gain par nombre de sources
Exemple: 2 inputs → groupe default = gain × 0.5 chacun
Résultat: Aucun clipping détecté, audio propre
- Conversion des routes groupes (GET/POST/PUT/DELETE) pour utiliser configManager
- Suppression de loadConfig() et saveConfig() locales (redondantes)
- Fix: les modifications de groupes sont maintenant persistées correctement
- Les groupes créés/modifiés/supprimés survivent au redémarrage du serveur
- Admin : regroupement des 3 dropdowns cartes son dans une seule section
- Admin : suppression du mode édition pour noms de canaux (directement éditables)
- Admin : unification des boutons de sauvegarde en bas de chaque section
- Admin : routing par hash URL pour persistance des onglets (#groups, #audio, etc.)
- AudioRoutingMatrix : bouton sauvegarde déplacé en bas de la matrice
- AudioRoutingMatrix : dropdowns de gain en nuance de bleu (cohérence visuelle)
- Settings : suppression paramètres inutiles (mode PTT continu, feedback audio non implémenté)
- Settings : conservation uniquement du paramètre vibrations (fonctionnel)
- PTTButton : suppression init mode continu par défaut (redondant avec geste verrouillage)
- PWAInstallPrompt : ajout fond semi-transparent et couleurs hardcodées pour lisibilité
- Admin : fix dropdowns audio qui se réinitialisaient (useRef au lieu de useState pour édition)
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.
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)
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.
Filtrage des logs :
- LIVEKIT_LOG_LEVEL=info au lieu de debug
- Suppression logs DEBUG, signal requests/responses
- Garde uniquement INFO, WARN, ERROR importants
Rend les logs bien plus lisibles pour le debug applicatif.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>
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>
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>
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>
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>
- AudioBridge passe inputTargetDevice et outputTargetDevice à PipeWire
- Fix: PipeWire utilisait targetDevice au lieu de input/outputTargetDevice
- Devrait maintenant démarrer les streams pw-cat correctement
- /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
- Linux : utilise server/bin/livekit-server (installé par install.sh)
- macOS : utilise livekit-server du PATH (Homebrew)
- Corrige erreur 'livekit-server: not found' sous Linux
- Mode dev : proxy Vite /livekit → ws://localhost:7880 (évite mixed content)
- Mode prod : HTTP direct, pas de HTTPS (auto-hébergé local)
- Détection automatique du mode via import.meta.env.DEV
- En production réelle, HTTPS sera géré par reverse proxy
- Création d'un apiRouter Express pour toutes les routes API
- Routes montées sous /api ET à la racine (rétrocompatibilité)
- QR code corrigé : HTTPS en mode production
- start.sh : affichage URL HTTPS corrigé
- Résout le problème de connexion en mode production
- Ajout .env.production avec VITE_API_URL=. (URLs relatives)
- Le client build utilise maintenant les routes directes (/config au lieu de /api/config)
- Rebuild client avec la bonne configuration pour HTTPS production
- start.sh teste maintenant https://localhost:3000 en production
- Ajout flag -k à curl pour accepter certificat auto-signé
- Correction timeout qui empêchait le démarrage
- Ajout support HTTPS au serveur Express avec certificats auto-signés
- Variable d'environnement ENABLE_HTTPS pour activer/désactiver HTTPS
- start.sh active automatiquement HTTPS en mode production (pas --dev)
- Messages d'aide clarifiés avec URLs HTTPS et avertissement certificat
- WebSocket Audio Levels supporte wss:// en mode HTTPS
Mode dev : HTTPS sur port 5173 (Vite) + HTTP API sur 3000
Mode prod : HTTPS sur port 3000 (Express sert client + API)
- Réinstallation qrcode-terminal dans server/ (utilisé par show-qr.sh)
- Script Node inline dans show-qr.sh qui utilise le package depuis server/
- QR code s'affiche correctement au lancement
- 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)
Selon CLAUDE.md : ne pas créer de fichiers récapitulatifs.
Suppression de CHANGELOG-PORTABLE.md et FEATURES-QR-HTTPS.md.
L'historique git suffit pour le changelog.
README-PORTABLE.md reste (documentation utilisateur).
Utilise 'tee' au lieu de redirection > pour :
- Afficher la sortie serveur dans le terminal (QR code visible)
- Conserver les logs dans server.log
Sans cela, le QR code n'était jamais visible pour l'utilisateur.
Guide complet des nouvelles fonctionnalités UX :
- QR code dans terminal (scan rapide smartphone)
- Redirection HTTP → HTTPS automatique
- Workflow avant/après
- Configuration nginx/Caddy production
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
1. Messages finaux install scripts
- Mise en avant de ./start.sh (recommandé)
- Méthode manuelle en alternatif
- Port production corrigé (3000 au lieu de 5173)
2. Serveur statique production (server/index.js)
- Sert client/dist/ si build existe
- Route / serve index.html en production
- Mode dev : retourne info API JSON
- Permet ./start.sh mode prod fonctionnel
Fix issues identifiés : messages obsolètes + production non fonctionnelle.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Récapitulatif complet de tous les changements pour la portabilité :
- Avant/après comparaison
- Changements détaillés par fichier
- Statistiques (4 commits, 10 fichiers modifiés, ~950 lignes)
- Guide d'utilisation simplifié
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
1. .gitignore mis à jour
- Ignore server/.env et client/.env (générés)
- Préserve .env.example (templates)
- Ignore server.log et PID files runtime
2. server/.env.example créé
- Template documenté pour mode local/cloud
- Instructions AUTO pour LIVEKIT_URL
- Clés par défaut devkey/secret documentées
Finalise la configuration portable zéro-config.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
1. README-PORTABLE.md
- Guide complet déploiement portable
- Installation zéro-config
- Configuration avancée (IP manuelle, devices, ports)
- Mode production (build, nginx)
- Dépannage détaillé (firewall, audio, réseau)
- Architecture portable expliquée
2. README.md mis à jour
- Installation automatique en premier (recommandé)
- Installation manuelle LiveKit Cloud en alternatif
- Lien vers README-PORTABLE.md
- Version bump 0.2.0 (Portable)
Documentation complète pour déploiement en conditions réelles.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changements pour rendre l'installation portable :
1. Config réseau auto-détectée
- config.yaml : LIVEKIT_URL = AUTO (au lieu de IP hardcodée)
- Devices audio : null par défaut (auto-détection)
2. Client .env dynamique
- Ajout client/.env.example avec documentation
- VITE_API_URL configurable pour dev/prod
3. Vite config dynamique
- Utilisation de loadEnv() pour variables d'environnement
- Proxies configurables via VITE_API_URL et VITE_LIVEKIT_URL
4. Install script amélioré
- Détection automatique IP réseau au moment install
- Génération .env client avec IP détectée
- Messages informatifs avec IP du serveur
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>
- 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>
- 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
- Ajout état isEditingAudio pour tracker quand utilisateur édite
- loadAudioDevices() ne réécrase plus les sélections si isEditingAudio=true
- Activation isEditingAudio sur onChange des 3 dropdowns
- Désactivation après sauvegarde réussie
- Corrige bug: dropdowns se réinitialisaient toutes les 3s (auto-refresh)
- 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
- 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
- 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
- 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
- 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
Probleme: AudioLevelsServer creait son propre port (3001) au lieu d'utiliser le serveur HTTP existant (3000)
Solution:
- Modification AudioLevelsServer pour accepter option 'server'
- Si serveur HTTP fourni, utilise WebSocket upgrade sur meme port avec path /audio-levels
- Sinon, fallback sur port standalone (3001)
- Client se connecte maintenant a ws://localhost:3000/audio-levels
Architecture WebSocket:
HTTP GET /config, POST /token (port 3000)
WebSocket ws://localhost:3000/audio-levels (upgrade HTTP)
Plus besoin de port separe pour WebSocket
Probleme: Client tentait de se connecter a ws://localhost:3001 mais serveur n'avait pas de WebSocket demarre
Solution:
- Ajout import AudioLevelsServer dans server/index.js
- Demarrage WebSocket sur meme port que l'API REST (3000)
- Correction port dans useAudioLevels.js (3000 au lieu de 3001)
Le WebSocket audio-levels fonctionne maintenant pour monitoring temps reel
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 !