|
@@ -71,69 +71,42 @@ SAMPLE_RATE = 16000
|
|
|
@app.websocket("/ws/transcribe")
|
|
@app.websocket("/ws/transcribe")
|
|
|
async def ws_transcribe(ws: WebSocket):
|
|
async def ws_transcribe(ws: WebSocket):
|
|
|
await ws.accept()
|
|
await ws.accept()
|
|
|
-
|
|
|
|
|
logger.info("WebSocket connecté !")
|
|
logger.info("WebSocket connecté !")
|
|
|
|
|
|
|
|
- audio_buffer = []
|
|
|
|
|
- start_time = time.time()
|
|
|
|
|
-
|
|
|
|
|
try:
|
|
try:
|
|
|
while True:
|
|
while True:
|
|
|
data = await ws.receive_bytes()
|
|
data = await ws.receive_bytes()
|
|
|
|
|
|
|
|
- logger.debug(f"Audio reçu: {len(data)} bytes")
|
|
|
|
|
|
|
+ logger.debug(f"Chunk reçu: {len(data)} bytes")
|
|
|
|
|
|
|
|
- # PCM int16 → float32
|
|
|
|
|
pcm = np.frombuffer(data, dtype=np.int16).astype(np.float32) / 32768.0
|
|
pcm = np.frombuffer(data, dtype=np.int16).astype(np.float32) / 32768.0
|
|
|
|
|
|
|
|
- # silence pur → on reset le buffer
|
|
|
|
|
|
|
+ # silence gate léger
|
|
|
if np.abs(pcm).mean() < 0.001:
|
|
if np.abs(pcm).mean() < 0.001:
|
|
|
- audio_buffer.clear()
|
|
|
|
|
- continue
|
|
|
|
|
-
|
|
|
|
|
- audio_buffer.append(pcm)
|
|
|
|
|
-
|
|
|
|
|
- audio_len = sum(len(chunk) for chunk in audio_buffer) / SAMPLE_RATE
|
|
|
|
|
-
|
|
|
|
|
- logger.debug(f"Buffer audio: {audio_len:.2f}s")
|
|
|
|
|
-
|
|
|
|
|
- # Sécurité : reset si trop long
|
|
|
|
|
- if audio_len > MAX_AUDIO_SEC:
|
|
|
|
|
- logger.warning("Buffer trop long, reset")
|
|
|
|
|
- audio_buffer.clear()
|
|
|
|
|
- start_time = time.time()
|
|
|
|
|
|
|
+ logger.debug("Chunk silencieux ignoré")
|
|
|
continue
|
|
continue
|
|
|
|
|
|
|
|
- # Transcription dès qu'on a assez d'audio
|
|
|
|
|
- if audio_len >= MIN_AUDIO_SEC:
|
|
|
|
|
- logger.info(f"Transcription ({audio_len:.2f}s)")
|
|
|
|
|
-
|
|
|
|
|
- audio = np.concatenate(audio_buffer)
|
|
|
|
|
- audio_buffer.clear()
|
|
|
|
|
|
|
+ duration = len(pcm) / SAMPLE_RATE
|
|
|
|
|
+ logger.info(f"Transcription chunk {duration:.2f}s")
|
|
|
|
|
|
|
|
- segments, _ = model.transcribe(
|
|
|
|
|
- audio,
|
|
|
|
|
- language="fr",
|
|
|
|
|
- vad_filter=VAD_ENABLED
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ segments, _ = model.transcribe(
|
|
|
|
|
+ pcm,
|
|
|
|
|
+ language="fr",
|
|
|
|
|
+ vad_filter=VAD_ENABLED
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
- text = " ".join(seg.text for seg in segments).strip()
|
|
|
|
|
|
|
+ text = " ".join(seg.text for seg in segments).strip()
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- logger.info(f"Texte: '{text}'")
|
|
|
|
|
|
|
+ logger.info(f"Texte: '{text}'")
|
|
|
|
|
|
|
|
- if text:
|
|
|
|
|
- await ws.send_json({
|
|
|
|
|
- "type": "final",
|
|
|
|
|
- "text": text
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- logger.info("Résultat envoyé")
|
|
|
|
|
|
|
+ if text:
|
|
|
|
|
+ await ws.send_json({
|
|
|
|
|
+ "type": "final",
|
|
|
|
|
+ "text": text
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
except WebSocketDisconnect:
|
|
except WebSocketDisconnect:
|
|
|
logger.info("WebSocket déconnecté")
|
|
logger.info("WebSocket déconnecté")
|
|
|
- except Exception as e:
|
|
|
|
|
- logger.exception("Erreur de WebSocket")
|
|
|
|
|
-
|
|
|
|
|
- await ws.send_json({"error": str(e)})
|
|
|
|
|
|
|
+ except Exception:
|
|
|
|
|
+ logger.exception("Erreur WebSocket")
|
|
|
await ws.close()
|
|
await ws.close()
|