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 !
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
- Calcul RMS et peak par canal (dBFS)
- Détection clipping automatique
- Broadcast temps réel 20 fois/sec (configurable)
- Support inputs, groups, outputs
- Gestion multi-clients WebSocket
- API pour mise à jour depuis GroupAudioRouter
- Dropdown gain -12dB à +6dB pour chaque route active
- Interface visuelle améliorée (checkbox + gain)
- Gestion gains input->group et group->output
- Sauvegarde gains dans config.yaml
- Design responsive mobile
- 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
- Ajout React.Fragment avec keys pour éliminer warnings
- Import de React pour utiliser React.Fragment
- Meilleure gestion erreurs HTTP (status check)
- Messages d'erreur plus détaillés avec status code
- Logging amélioré pour debugging
- Ajout grid-template-columns dynamique basé sur nombre groupes
- Suppression display:contents qui causait le bug
- Utilisation de fragments React au lieu de div wrapper
- Matrice 1: 120px + N colonnes pour les groupes
- Matrice 2: 120px + 8 colonnes pour les outputs
- Nettoyage CSS classes inutilisées
- API GET/POST /admin/audio/routing
- Composant AudioRoutingMatrix avec 2 matrices :
* Inputs vers Groupes (8 inputs x N groupes)
* Groupes vers Outputs (N groupes x 8 outputs)
- Interface visuelle type grille cliquable
- Intégration noms de canaux personnalisés
- Stockage routing dans config.yaml
- Responsive design avec CSS Grid
- Style cohérent avec interface admin
- API GET /admin/audio/channels/names
- API PUT /admin/audio/channels/names
- Interface admin : nommage 8 inputs/outputs
- Mode édition avec sauvegarde/annulation
- Stockage dans config.yaml (section audio.channelNames)
- Formulaire organisé en 2 colonnes (inputs/outputs)