Skip to content

fix(sse): iterate async TTS generator from sync context without async io.run; return proper SSE chunks#35

Open
DanTulovsky wants to merge 5 commits into
travisvn:mainfrom
DanTulovsky:fix/sse-async-generator
Open

fix(sse): iterate async TTS generator from sync context without async io.run; return proper SSE chunks#35
DanTulovsky wants to merge 5 commits into
travisvn:mainfrom
DanTulovsky:fix/sse-async-generator

Conversation

@DanTulovsky

Copy link
Copy Markdown

This is a fix for: #34

Full disclosure, fix provided by GPT5. It does seem to fix the error though. It said:

So the exact failure is: asyncio.run expects a coroutine object, but it was given an async generator (_generate_audio_stream(...)), producing “a coroutine was expected, got <async_generator ...>”, which your SSE wrapper then emits as a JSON error.

Status: Reviewed app/tts_handler.py and app/server.py and identified a type mismatch between an async generator and asyncio.run as the cause of the SSE error.

Cause: asyncio.run(_generate_audio_stream(...)) where _generate_audio_stream is an async generator.
Effect: SSE path emits {"type":"error","error":"a coroutine was expected, got <async_generator ...>"}.
The non-SSE path works because it runs a proper coroutine (_generate_audio) via asyncio.run.```

Before:

❯ curl -X POST http://localhost:5050/v1/audio/speech
-H "Content-Type: application/json"
-H "Authorization: Bearer your_api_key_here"
-d '{
"model": "tts-1",
"input": "This will stream as Server-Sent Events with JSON data containing base64-encoded audio chunks.",
"voice": "alloy",
"stream_format": "sse"
}'
data: {"type": "error", "error": "a coroutine was expected, got <async_generator object _generate_audio_stream at 0x2aaaae3a7450>"}


After:

❯ curl -X POST http://localhost:5050/v1/audio/speech
-H "Content-Type: application/json"
-H "Authorization: Bearer your_api_key_here"
-d '{
"model": "tts-1",
"input": "This will stream as Server-Sent Events with JSON data containing base64-encoded audio chunks.",
"voice": "alloy",
"stream_format": "sse"
}'
data: {"type": "speech.audio.delta", "audio": "//NkxAAAAANIAAAAAExBTUVVVVUJUpHz0MCZbJZCAIWIDA8LoAIg6d3phCbs8RRfXd4Bi+xNCSwAL3N4hV3PrvEU65EHFuaRHOIUQnRETriz8OBmUT3fiImiITz6l/SgZvu7nER+IhJuifXcy6f5Qk656JHghE3dyrn/C+U0LPQjQOOW504II/gAocXEqV3M//NkxHwAAANIAAAAACDBz/+mEI4INEPhE0pBB7soU7RZIzHRAZc0ngE1yFEZa0sP8fJbzKxWElxhqdvRCVHEv4W2XoTpcWQ3yq47fVlNRUelrrJm6WlaPD05bYfNkZqmTH5y9DeKxYgocHaFLXRmd2NL8Edm2FBgWGI3U7JcP/M4zxZE02rSHixQmRa2YQKX//NkxP8iG/H0FGGGbORLWJDynunjRwirAssflthdiZuzlDlhpmGNTZwuawpeu8YEvzNe4V9NjiRLxYWmW1607Kjh4tJG/eD6RrJZXQsJ2s9swbOS0neq1VCYbhp5/5mlPx4YopiS2WXIQpetsPtrjEtRnrnwbFvrIarG165epebqNNUylpOhI3RJnwtiXZ1t//NkxPk6VDn0CsPYUCykisiSDbIoygabAaCg6ZHaJJ6ZVsRyOxUyGCSxjvR1O3uYHmpN2DMVTSkB/YylWaQ5xqifJHacyWPBE0pPRHfKGFuXZcEMn6s9D3RZ+nV1lGL3sCb21vhpm5dLnUM59SsmfUkyNnxPpVYgMRkKltwwomm6YOQOR2LZ2mo2BMyntT2r//NkxJIrXCIQNHqMgZ5Voyfg/E93GaZAghLcnw1zG5EQhJrwozQR4ZVPCKo7rBsIFisTQabxhcjCBo0TCUzp+aFGgbMknJrIT8klpqR8vM+KGJHUGc7uEl2uLMj4x2tkpGZkz6YKOWRlTXJiKq2RdO0RD/jRjKwlcjIiJ6TsTMwixQaKM1cOpA4aL/GRzagP"}

data: {"type": "speech.audio.delta", "audio": "//NkxGckNBoMAMJGXTVTJYb2rSunnv65otiHDMqMYJSI6hvbHpq68bDDMeXK0sI1Rp0XUzQEVZMrYmib2pZqor+VunW8c9uDZGMoLuGqO+uRWYZssQKmHpF20DNiPkbc3omGFpUlveuTr4u8EWeSO5kRPRgbucnLCyWeRkSGmh2FgyJjgT8oTXvpWsnSZtiK//NkxFkiOmoQAMJGtbdWF5EZrAu+A93gCV2vpWNafZ2rJv00Xu69zjQ/3VWcy7ncVDqkR3b49EJpJyfWNjBYHBIEMIBoyswDp08NDEcwyEAoIAMIBwBGDgIgBGgM3JMSHWdt/jL5qvHr1er0PAcEAGgsKuAwaHJJQSA4HAlig/QFiDQ+BoDcF5ZY0O3U6DxK//NkxFMt4+IYAVxAAeQhlMKCg3HC558pYy5u5yUQx4FEqrey3tKmOd5sodUcPaTLkGUgyv7fIRK9rWhpf46bnlEMP4pYRBTnt9h3on8dW93dR9xwQnVb9zJ8vT8IiTBby98/c39W+/Zdlx70O058/WpKwZVQp/v+aISb7OCajQv/PqsDX+gtNRKkT09AYYjD//NkxB4k7DqYAZhoAJzb9zdBiMbAkAXseH/dBheEzJA8J2E4/3ZDkiThxl9FJf/6t0EDcuFpMIAwo8is3//W6akDRP5RLxqOYeI7xMBzlIlGNf////9AlyTN3OGhuXy+ShSDkDwHcMj///+yC3fb/5cNx2E0oF0tPpIoskZMxrTWkaWBSCIAT+OOoaFQigx1//NkxA0doba9k9lgAGzKV5Ekp2phhc1utJWmRTH/xp7/zVpZTrQlRXz+sL7LKLC2BA8BmXCQnLiowWP8/A4s1dEVz8z42LDR4xTr5Sm/2zOzPTefpX7z0NuMLOc4uj/qbSLqNbLnxjF1qGqcGf1UAH96KVNZstXkgN8BfPvVX9tiAIcZfugXyaImEiNERtUI"}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant