Add debug logging to synthesis pipeline to trace hang
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m11s

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-08 19:34:18 -04:00
parent 8272b6a8c9
commit 067a853d3b

View File

@@ -119,32 +119,40 @@ class KokoroEventHandler(AsyncEventHandler):
try:
chunk_queue: asyncio.Queue = asyncio.Queue()
loop = asyncio.get_event_loop()
loop = asyncio.get_running_loop()
def _generate():
chunk_count = 0
try:
_LOGGER.debug("Pipeline thread started")
for _, _, audio in self.pipeline(text, voice=voice_name, speed=speed):
if audio is None:
continue
# float32 [-1, 1] → int16
audio_np = audio.cpu().numpy() if hasattr(audio, 'cpu') else audio
pcm = (np.clip(audio_np, -1.0, 1.0) * 32767).astype(np.int16)
asyncio.run_coroutine_threadsafe(
chunk_queue.put(pcm.tobytes()), loop
)
chunk_count += 1
_LOGGER.debug("Queueing chunk %d (%d bytes)", chunk_count, len(pcm.tobytes()))
fut = asyncio.run_coroutine_threadsafe(chunk_queue.put(pcm.tobytes()), loop)
fut.result() # propagate any queue errors
_LOGGER.debug("Pipeline finished, %d chunks generated", chunk_count)
except Exception as exc:
asyncio.run_coroutine_threadsafe(chunk_queue.put(exc), loop)
_LOGGER.exception("Pipeline thread error")
asyncio.run_coroutine_threadsafe(chunk_queue.put(exc), loop).result()
finally:
asyncio.run_coroutine_threadsafe(chunk_queue.put(None), loop)
asyncio.run_coroutine_threadsafe(chunk_queue.put(None), loop).result()
self.executor.submit(_generate)
chunks_sent = 0
while True:
item = await chunk_queue.get()
if item is None:
break
if isinstance(item, Exception):
raise item
chunks_sent += 1
_LOGGER.debug("Sending audio chunk %d", chunks_sent)
await self.write_event(
AudioChunk(
rate=KOKORO_SAMPLE_RATE,
@@ -153,6 +161,7 @@ class KokoroEventHandler(AsyncEventHandler):
audio=item,
).event()
)
_LOGGER.info("Synthesis complete, sent %d chunks", chunks_sent)
except Exception:
_LOGGER.exception("Error during synthesis")
finally:
@@ -168,7 +177,7 @@ async def main() -> None:
args = parser.parse_args()
logging.basicConfig(
level=logging.DEBUG if args.debug else logging.INFO,
level=logging.DEBUG,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)