mirror of
https://github.com/R0m1k3/LiveFlow.git
synced 2026-10-14 10:48:58 +02:00
Adaptation aux micros instables (Bluetooth) sans changer la config du poste
- 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
This commit is contained in:
4 files changed
+90
-8
No files matched your search
+30
-3
@@ -1,4 +1,5 @@
|
||||
import asyncio
|
||||
import audioop
|
||||
import hashlib
|
||||
import hmac
|
||||
import io
|
||||
@@ -153,6 +154,21 @@ def pcm_to_wav(pcm: bytes) -> bytes:
|
||||
return buf.getvalue()
|
||||
|
||||
|
||||
QUIET_PEAK = 9000 # niveau crête en dessous duquel on amplifie (échelle int16)
|
||||
|
||||
|
||||
def boost_quiet_audio(pcm: bytes) -> tuple[bytes, int]:
|
||||
"""Amplifie les segments trop faibles (micros Bluetooth mains-libres...).
|
||||
|
||||
Retourne (audio, niveau crête d'origine).
|
||||
"""
|
||||
peak = audioop.max(pcm, 2)
|
||||
if 0 < peak < QUIET_PEAK:
|
||||
factor = min(6.0, 26000 / peak)
|
||||
return audioop.mul(pcm, 2, factor), peak
|
||||
return pcm, peak
|
||||
|
||||
|
||||
async def _post_transcription(data: dict, wav: bytes) -> httpx.Response:
|
||||
return await http.post(
|
||||
f"{ASR_BASE_URL}/audio/transcriptions",
|
||||
@@ -215,10 +231,12 @@ async def ws_transcribe(ws: WebSocket):
|
||||
seg = await queue.get()
|
||||
if seg is None:
|
||||
return
|
||||
pcm, peak = boost_quiet_audio(seg.pcm)
|
||||
print(f"[réunion {meeting_id}] segment {seg.t0:.1f}s → {seg.t1:.1f}s "
|
||||
f"({len(seg.pcm) / 2 / SAMPLE_RATE:.1f}s d'audio), transcription...", flush=True)
|
||||
f"({len(seg.pcm) / 2 / SAMPLE_RATE:.1f}s d'audio, niveau crête {peak}"
|
||||
f"{', amplifié' if pcm is not seg.pcm else ''}), transcription...", flush=True)
|
||||
try:
|
||||
text = await transcribe(seg.pcm)
|
||||
text = await transcribe(pcm)
|
||||
except Exception as exc:
|
||||
print(f"[réunion {meeting_id}] ERREUR ASR : {exc}", flush=True)
|
||||
await ws.send_json({"type": "error", "message": f"Transcription échouée : {exc}"})
|
||||
@@ -350,4 +368,13 @@ async def export_meeting(meeting_id: int, format: str = "txt"):
|
||||
)
|
||||
|
||||
|
||||
app.mount("/", StaticFiles(directory="static", html=True), name="static")
|
||||
class NoCacheStaticFiles(StaticFiles):
|
||||
"""Force la revalidation des fichiers statiques après chaque mise à jour."""
|
||||
|
||||
async def get_response(self, path, scope):
|
||||
resp = await super().get_response(path, scope)
|
||||
resp.headers["Cache-Control"] = "no-cache"
|
||||
return resp
|
||||
|
||||
|
||||
app.mount("/", NoCacheStaticFiles(directory="static", html=True), name="static")
|
||||
Reference in new issue
Block a user