Percy3822 commited on
Commit
cf40d2a
·
verified ·
1 Parent(s): a20b7d7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -16
app.py CHANGED
@@ -159,8 +159,10 @@ async def tts_say_stream_wav(
159
  write_event({"type":"tts_stream_get","len":len(text),"voice":voice,"ls":ls})
160
 
161
  async def gen():
162
- ws_url = _tts_ws_url()
163
- async with websockets.connect(ws_url, ping_interval=None, max_size=8_000_000) as ws:
 
 
164
  # init
165
  await ws.send(json.dumps({
166
  "event": "init",
@@ -170,11 +172,11 @@ async def tts_say_stream_wav(
170
  "noise_w": noise_w,
171
  }))
172
  sr, ch = 22050, 1
173
- # wait for ready -> send header
174
  while True:
175
  m = await ws.recv()
176
  if isinstance(m, (bytes, bytearray)):
177
- # unlikely before ready; ignore
178
  continue
179
  try:
180
  evt = json.loads(m)
@@ -196,20 +198,43 @@ async def tts_say_stream_wav(
196
  while True:
197
  try:
198
  msg = await ws.recv()
199
- except websockets.exceptions.ConnectionClosed:
 
 
200
  break
 
201
  if isinstance(msg, (bytes, bytearray)):
202
- yield msg
203
- else:
204
- try:
205
- evt = json.loads(msg)
206
- except Exception:
207
- continue
208
- if evt.get("event") in ("done", "end"):
209
- break
210
- if evt.get("event") == "error":
211
- yield f'ERROR: {evt.get("detail","tts error")}'.encode("utf-8")
212
- break
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
 
214
  return StreamingResponse(gen(), media_type="audio/wav",
215
  headers={"Cache-Control":"no-cache","Connection":"keep-alive"})
 
159
  write_event({"type":"tts_stream_get","len":len(text),"voice":voice,"ls":ls})
160
 
161
  async def gen():
162
+ ws = None
163
+ try:
164
+ ws_url = _tts_ws_url()
165
+ ws = await websockets.connect(ws_url, ping_interval=None, max_size=8_000_000)
166
  # init
167
  await ws.send(json.dumps({
168
  "event": "init",
 
172
  "noise_w": noise_w,
173
  }))
174
  sr, ch = 22050, 1
175
+ # wait for ready -> send header immediately so client can start
176
  while True:
177
  m = await ws.recv()
178
  if isinstance(m, (bytes, bytearray)):
179
+ # ignore stray audio until we know sr/ch
180
  continue
181
  try:
182
  evt = json.loads(m)
 
198
  while True:
199
  try:
200
  msg = await ws.recv()
201
+ except websockets.exceptions.ConnectionClosedOK:
202
+ break
203
+ except websockets.exceptions.ConnectionClosedError:
204
  break
205
+
206
  if isinstance(msg, (bytes, bytearray)):
207
+ # raw PCM16 frame from TTS; just yield
208
+ if msg:
209
+ yield msg
210
+ continue
211
+
212
+ # control event
213
+ try:
214
+ evt = json.loads(msg)
215
+ except Exception:
216
+ continue
217
+ kind = evt.get("event")
218
+ if kind in ("done", "end"):
219
+ break
220
+ if kind == "error":
221
+ # propagate as bytes (don’t raise; avoid chunk abort)
222
+ detail = evt.get("detail", "tts error")
223
+ yield f'ERROR: {detail}'.encode("utf-8")
224
+ break
225
+ # ignore logs
226
+
227
+ except Exception as e:
228
+ # Log, but don't raise (raising here aborts chunked stream & causes 'incomplete chunked read')
229
+ write_event({"type":"tts_stream_err","err":str(e)})
230
+ # a tiny trailing pad keeps some clients happy
231
+ yield b""
232
+ finally:
233
+ try:
234
+ if ws is not None:
235
+ await ws.close()
236
+ except Exception:
237
+ pass
238
 
239
  return StreamingResponse(gen(), media_type="audio/wav",
240
  headers={"Cache-Control":"no-cache","Connection":"keep-alive"})