|
|
@ -339,25 +339,26 @@ async def handle_phone_stream_ws(request): |
|
|
logger.info("🎙️ Started Live Speech Session: %s", current_session_id) |
|
|
logger.info("🎙️ Started Live Speech Session: %s", current_session_id) |
|
|
|
|
|
|
|
|
elif msg_type == "stop": |
|
|
elif msg_type == "stop": |
|
|
logger.info("⏹️ Stop received for %s. Draining audio queue...", sid) |
|
|
|
|
|
|
|
|
logger.info("⏹️ Stop received for %s. Draining audio queue (%d pending)...", sid, audio_queue.qsize()) |
|
|
|
|
|
|
|
|
# 1. Drain audio queue to Soniox with timeout |
|
|
|
|
|
|
|
|
# 1. Drain audio queue to Soniox with generous timeout for long speech |
|
|
try: |
|
|
try: |
|
|
await asyncio.wait_for(audio_queue.join(), timeout=2.0) |
|
|
|
|
|
|
|
|
await asyncio.wait_for(audio_queue.join(), timeout=3.0) |
|
|
except Exception: |
|
|
except Exception: |
|
|
pass |
|
|
pass |
|
|
|
|
|
|
|
|
# 2. Send finalize |
|
|
|
|
|
|
|
|
# 2. Send finalize and wait for Soniox to transcribe 100% of the speech |
|
|
if active_soniox_ws and is_ws_open(active_soniox_ws): |
|
|
if active_soniox_ws and is_ws_open(active_soniox_ws): |
|
|
await active_soniox_ws.send(json.dumps({"type": "finalize"})) |
|
|
await active_soniox_ws.send(json.dumps({"type": "finalize"})) |
|
|
try: |
|
|
try: |
|
|
await asyncio.wait_for(stop_event.wait(), timeout=0.45) |
|
|
|
|
|
|
|
|
# Generous 3.5s wait so long speech (e.g. 30-40s) is never truncated prematurely |
|
|
|
|
|
await asyncio.wait_for(stop_event.wait(), timeout=3.5) |
|
|
except asyncio.TimeoutError: |
|
|
except asyncio.TimeoutError: |
|
|
logger.info("Finalize wait completed (timeout reached)") |
|
|
logger.info("Finalize wait completed (timeout reached)") |
|
|
|
|
|
|
|
|
raw_final = "".join(full_final_tokens) + current_non_final |
|
|
raw_final = "".join(full_final_tokens) + current_non_final |
|
|
clean_final = sanitize_text(raw_final, allow_multiline=False, preserve_trailing_space=True) |
|
|
clean_final = sanitize_text(raw_final, allow_multiline=False, preserve_trailing_space=True) |
|
|
logger.info("⚡ Session %s final text: '%s'", sid, clean_final) |
|
|
|
|
|
|
|
|
logger.info("⚡ Session %s final text (%d chars): '%s'", sid, len(clean_final), clean_final) |
|
|
|
|
|
|
|
|
# Return final speech text to phone (phone updates UI and broadcasts full state to Mac) |
|
|
# Return final speech text to phone (phone updates UI and broadcasts full state to Mac) |
|
|
if is_ws_open(ws): |
|
|
if is_ws_open(ws): |
|
|
|