Timeout audio stream if no first chunk

This commit is contained in:
Smittix
2026-02-04 10:53:03 +00:00
parent cf8b8a33a7
commit 908d159ca9
+29 -23
View File
@@ -914,29 +914,35 @@ def stream_audio() -> Response:
if not audio_running or not audio_process: if not audio_running or not audio_process:
return Response(b'', mimetype='audio/mpeg', status=204) return Response(b'', mimetype='audio/mpeg', status=204)
def generate(): def generate():
# Capture local reference to avoid race condition with stop # Capture local reference to avoid race condition with stop
proc = audio_process proc = audio_process
if not proc or not proc.stdout: if not proc or not proc.stdout:
return return
try: try:
while audio_running and proc.poll() is None: # First byte timeout to avoid hanging clients forever
# Use select to avoid blocking forever first_chunk_deadline = time.time() + 3.0
ready, _, _ = select.select([proc.stdout], [], [], 2.0) while audio_running and proc.poll() is None:
if ready: # Use select to avoid blocking forever
chunk = proc.stdout.read(4096) ready, _, _ = select.select([proc.stdout], [], [], 2.0)
if chunk: if ready:
yield chunk chunk = proc.stdout.read(4096)
else: if chunk:
break yield chunk
else: else:
# Timeout - check if process died break
if proc.poll() is not None: else:
break # If no data arrives shortly after start, exit so caller can retry
except GeneratorExit: if time.time() > first_chunk_deadline:
pass logger.warning("Audio stream timed out waiting for first chunk")
except Exception as e: break
logger.error(f"Audio stream error: {e}") # Timeout - check if process died
if proc.poll() is not None:
break
except GeneratorExit:
pass
except Exception as e:
logger.error(f"Audio stream error: {e}")
return Response( return Response(
generate(), generate(),