Maintenant que l'amplification ne sert qu'à la détection (l'audio transcrit
reste propre), on peut rendre le VAD bien plus généreux aux bords sans coût
sur la qualité :
- pré-enregistrement 300 ms -> 750 ms (capture l'attaque de la 1re syllabe)
- VAD plus sensible (agressivité 2 -> 1), déclenchement plus rapide (0.6 -> 0.35)
- silence de fin 700 ms -> 950 ms (capture les fins de mots)
Validé : lead-in 0.5 s + trailing 1.1 s capturés, phrases distinctes non fusionnées.
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
L'AGC sur-amplifiait (jusqu'à x60) l'audio envoyé au moteur -> signal
déformé/bruité -> mauvaise reconnaissance. Désormais :
- Le VAD détecte sur l'audio amplifié, mais le segment stocke l'audio BRUT
- Le segment est normalisé proprement (mise à l'échelle linéaire unique vers
crête ~22000, sans saturation) juste avant le moteur
- Segment max ramené de 25 s à 15 s pour un retour plus rapide
Validé bout en bout : micro faible -> détecté -> audio propre -> transcrit.
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
- Timeout de 5 s sur l'identification du locuteur (asyncio.wait_for) : si le
modèle ECAPA tarde ou se bloque sur CPU, on ignore le locuteur mais le
texte est transcrit et affiché quand même
- AGC du segmenteur protégé : une trame problématique renvoie l'audio brut
au lieu d'interrompre le découpage
Testé : texte transcrit malgré un diariseur qui se bloque indéfiniment.
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
Captation micro :
- Plus AUCUN test/bascule de micro automatique (choix manuel uniquement)
- Amplification adaptative (AGC) déplacée dans le segmenteur, AVANT la
détection de parole : un micro faible (casque) était sous le seuil du VAD,
aucune phrase n'était détectée. Validé : signal crête 1473 -> 16600, capté.
- Le client envoie l'audio brut (plus de gain navigateur qui se battait avec) ;
vumètre affiché amplifié pour rester lisible
Diarisation (locuteurs éclatés en 3, 4, 5... pour une même personne) :
- Seuil abaissé (0.70 -> 0.35) + zone morte large : un nouveau locuteur n'est
créé que si le score est nettement bas ET le segment assez long (>=1.2s)
- Centroïde plus stable (EMA alpha 0.15) + adhérence au dernier locuteur
- Validé : 1 personne reste 1 locuteur même très bruitée ; 2-3 voix séparées
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
- L'app ne change plus jamais de micro toute seule : choix manuel dans la
liste uniquement, simple alerte si aucun son n'est capté
- Gain automatique : seuil d'amplification élargi (signal < 12000), montée
plus rapide (x1.3/250 ms), plafond x80, et gain mémorisé entre réunions
pour être efficace dès la première seconde
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
Un silence en cours de réunion (normal) déclenchait des bascules de micro
intempestives qui cassaient la capture. Désormais : recherche uniquement
tant qu'aucun son n'a jamais été capté ; dès qu'un micro a fait ses preuves,
on n'y touche plus (sauf changement manuel).
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
Les micros faibles (casques) passaient sous le seuil du VAD : la plupart
des phrases n'étaient jamais découpées en segments. Un GainNode adaptatif
(jusqu'à x40, ajusté toutes les 250 ms, repli en cas de saturation) amène
le signal à un niveau exploitable avant le rééchantillonnage et le VAD.
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
Cette branche intègre déjà les apports de main (diarisation ECAPA-TDNN,
pause/reprise, sélecteur de micro) tout en conservant ce que main avait
perdu : authentification, décodeurs audio vLLM (correctif des 400),
basculement automatique de micro, amplification des segments faibles,
filtre CJK, CI sans filtre de chemins.
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
- diarizer.py (ECAPA-TDNN + clustering incrémental) repris tel quel de main
- Hooks dans le pipeline : colonne speaker, identification par segment dans
un thread, locuteur dans l'interface (étiquettes colorées) et les exports
- Pause/reprise : bouton ⏸, le client coupe l'envoi, le serveur clôt le
segment en cours
- Case « Locuteurs » pour désactiver la diarisation par réunion
- DIARIZATION=on par défaut dans les compose, PyTorch CPU dans l'image
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
- Select dropdown peuplé via enumerateDevices() au chargement
- Mise à jour automatique quand un périphérique est branché/débranché (devicechange)
- Le deviceId sélectionné est passé à getUserMedia() via exact constraint
- Option 'Micro par défaut' pour le comportement d'origine
Si le micro actif reste muet 5 s, l'app bascule à chaud sur les autres
micros un par un jusqu'à en trouver un qui capte du son, puis le mémorise.
Le sélecteur permet aussi de changer de micro en cours d'enregistrement.
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
- Sélecteur de micro intégré à l'interface (persisté, deviceId exact)
- Amplification serveur des segments trop faibles (mode mains-libres BT)
- Alerte visible si aucun son n'est capté pendant 5 s
- Niveau crête de chaque segment dans les logs
- Cache-Control: no-cache sur les fichiers statiques (fini le vieux JS en cache)
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
- Page de connexion, session 7 jours par cookie HMAC signé (secret persisté)
- Protection de l'API (401) et du WebSocket (code 4401), / redirige vers /login
- Bouton de déconnexion, redirection automatique à l'expiration de session
- Identifiants configurables via LIVEFLOW_USER / LIVEFLOW_PASSWORD
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
vLLM avec Qwen3-ASR peut répondre 400 quand 'language' est fourni. L'app
retente alors en détection automatique, et les erreurs ASR remontent
désormais avec le corps de la réponse pour faciliter le diagnostic.
Ajout du favicon (404 dans la console).
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
- Workflow build-image.yml : construit et pousse ghcr.io/r0m1k3/liveflow à
chaque modification de app/
- Compose Unraid : image préconstruite au lieu du build local, service
watchtower scopé par label pour redéployer l'app automatiquement
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
Par défaut vLLM réserve le contexte max du modèle (65k tokens = 7 Go de KV
cache), ce qui dépasse la mémoire restante après chargement des poids sur
les GPU modestes. 8192 tokens sont très largement suffisants pour des
segments audio de 25 s.
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
Un conteneur de moins. Le HTTPS reste nécessaire pour l'accès micro
(getUserMedia) depuis un autre appareil : certificat auto-signé généré au
démarrage pour LIVEFLOW_HOST, servi par uvicorn.
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe
Un site catch-all :443 avec tls internal ne génère aucun certificat, ce qui
fait échouer la négociation TLS. Le Caddyfile prend désormais l'adresse via
LIVEFLOW_HOST (+ default_sni pour les connexions par IP, sans SNI).
https://claude.ai/code/session_01YHMp3EKzr4s6o8w1ygxuUe