Add debug logging to synthesis pipeline to trace hang
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m11s
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:
23
server.py
23
server.py
@@ -119,32 +119,40 @@ class KokoroEventHandler(AsyncEventHandler):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
chunk_queue: asyncio.Queue = asyncio.Queue()
|
chunk_queue: asyncio.Queue = asyncio.Queue()
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_running_loop()
|
||||||
|
|
||||||
def _generate():
|
def _generate():
|
||||||
|
chunk_count = 0
|
||||||
try:
|
try:
|
||||||
|
_LOGGER.debug("Pipeline thread started")
|
||||||
for _, _, audio in self.pipeline(text, voice=voice_name, speed=speed):
|
for _, _, audio in self.pipeline(text, voice=voice_name, speed=speed):
|
||||||
if audio is None:
|
if audio is None:
|
||||||
continue
|
continue
|
||||||
# float32 [-1, 1] → int16
|
# float32 [-1, 1] → int16
|
||||||
audio_np = audio.cpu().numpy() if hasattr(audio, 'cpu') else audio
|
audio_np = audio.cpu().numpy() if hasattr(audio, 'cpu') else audio
|
||||||
pcm = (np.clip(audio_np, -1.0, 1.0) * 32767).astype(np.int16)
|
pcm = (np.clip(audio_np, -1.0, 1.0) * 32767).astype(np.int16)
|
||||||
asyncio.run_coroutine_threadsafe(
|
chunk_count += 1
|
||||||
chunk_queue.put(pcm.tobytes()), loop
|
_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:
|
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:
|
finally:
|
||||||
asyncio.run_coroutine_threadsafe(chunk_queue.put(None), loop)
|
asyncio.run_coroutine_threadsafe(chunk_queue.put(None), loop).result()
|
||||||
|
|
||||||
self.executor.submit(_generate)
|
self.executor.submit(_generate)
|
||||||
|
|
||||||
|
chunks_sent = 0
|
||||||
while True:
|
while True:
|
||||||
item = await chunk_queue.get()
|
item = await chunk_queue.get()
|
||||||
if item is None:
|
if item is None:
|
||||||
break
|
break
|
||||||
if isinstance(item, Exception):
|
if isinstance(item, Exception):
|
||||||
raise item
|
raise item
|
||||||
|
chunks_sent += 1
|
||||||
|
_LOGGER.debug("Sending audio chunk %d", chunks_sent)
|
||||||
await self.write_event(
|
await self.write_event(
|
||||||
AudioChunk(
|
AudioChunk(
|
||||||
rate=KOKORO_SAMPLE_RATE,
|
rate=KOKORO_SAMPLE_RATE,
|
||||||
@@ -153,6 +161,7 @@ class KokoroEventHandler(AsyncEventHandler):
|
|||||||
audio=item,
|
audio=item,
|
||||||
).event()
|
).event()
|
||||||
)
|
)
|
||||||
|
_LOGGER.info("Synthesis complete, sent %d chunks", chunks_sent)
|
||||||
except Exception:
|
except Exception:
|
||||||
_LOGGER.exception("Error during synthesis")
|
_LOGGER.exception("Error during synthesis")
|
||||||
finally:
|
finally:
|
||||||
@@ -168,7 +177,7 @@ async def main() -> None:
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.DEBUG if args.debug else logging.INFO,
|
level=logging.DEBUG,
|
||||||
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user