|
@@ -521,15 +521,13 @@ class Worker:
|
|
|
tts_track = rtc.LocalAudioTrack.create_audio_track("tts", tts_src)
|
|
tts_track = rtc.LocalAudioTrack.create_audio_track("tts", tts_src)
|
|
|
await self.room.local_participant.publish_track(tts_track)
|
|
await self.room.local_participant.publish_track(tts_track)
|
|
|
play_q: "asyncio.Queue[tuple[int, np.ndarray]]" = asyncio.Queue()
|
|
play_q: "asyncio.Queue[tuple[int, np.ndarray]]" = asyncio.Queue()
|
|
|
- gen = 0 # turn generation; bumped to flush in-flight audio
|
|
|
|
|
- cur_gen = {"v": -1} # generation currently being played by _player
|
|
|
|
|
|
|
+ cur_gen = {"v": 0} # generation counter + currently playing gen
|
|
|
|
|
|
|
|
async def _player():
|
|
async def _player():
|
|
|
"""Drain TTS audio sequentially on the single track."""
|
|
"""Drain TTS audio sequentially on the single track."""
|
|
|
while True:
|
|
while True:
|
|
|
g, audio = await play_q.get()
|
|
g, audio = await play_q.get()
|
|
|
logger.info("PLAY start gen=%d samples=%d", g, len(audio))
|
|
logger.info("PLAY start gen=%d samples=%d", g, len(audio))
|
|
|
- cur_gen["v"] = g
|
|
|
|
|
for i in range(0, len(audio), 24000 // 50):
|
|
for i in range(0, len(audio), 24000 // 50):
|
|
|
if cur_gen["v"] != g:
|
|
if cur_gen["v"] != g:
|
|
|
break
|
|
break
|
|
@@ -539,13 +537,12 @@ class Worker:
|
|
|
num_channels=1, samples_per_channel=len(c),
|
|
num_channels=1, samples_per_channel=len(c),
|
|
|
))
|
|
))
|
|
|
await asyncio.sleep(0.018)
|
|
await asyncio.sleep(0.018)
|
|
|
- cur_gen["v"] = -1
|
|
|
|
|
logger.info("PLAY end gen=%d", g)
|
|
logger.info("PLAY end gen=%d", g)
|
|
|
|
|
|
|
|
player_task = asyncio.create_task(_player())
|
|
player_task = asyncio.create_task(_player())
|
|
|
|
|
|
|
|
async def _acc():
|
|
async def _acc():
|
|
|
- nonlocal busy, gen
|
|
|
|
|
|
|
+ nonlocal busy
|
|
|
stream = rtc.AudioStream(track, sample_rate=sr, num_channels=1)
|
|
stream = rtc.AudioStream(track, sample_rate=sr, num_channels=1)
|
|
|
fc = 0
|
|
fc = 0
|
|
|
async for ev in stream:
|
|
async for ev in stream:
|
|
@@ -565,12 +562,9 @@ class Worker:
|
|
|
|
|
|
|
|
if was_speech and vad.should_end() and vad.min_speech_met():
|
|
if was_speech and vad.should_end() and vad.min_speech_met():
|
|
|
logger.info("[%s] VAD END blen=%d", sid, len(buf.buffer))
|
|
logger.info("[%s] VAD END blen=%d", sid, len(buf.buffer))
|
|
|
- gen += 1
|
|
|
|
|
- cur_gen["v"] = -1 # stop current playback immediately
|
|
|
|
|
- _drain_queue(play_q)
|
|
|
|
|
busy = True
|
|
busy = True
|
|
|
try:
|
|
try:
|
|
|
- await self._transcribe_and_respond(buf, play_q, gen)
|
|
|
|
|
|
|
+ await self._transcribe_and_respond(buf, play_q, cur_gen)
|
|
|
except Exception:
|
|
except Exception:
|
|
|
logger.exception("[%s] transcribe failed", sid)
|
|
logger.exception("[%s] transcribe failed", sid)
|
|
|
busy = False
|
|
busy = False
|
|
@@ -579,12 +573,9 @@ class Worker:
|
|
|
|
|
|
|
|
if vad.in_speech and vad.total_samples >= int(MAX_SPEECH_S * sr):
|
|
if vad.in_speech and vad.total_samples >= int(MAX_SPEECH_S * sr):
|
|
|
logger.info("[%s] VAD MAX blen=%d", sid, len(buf.buffer))
|
|
logger.info("[%s] VAD MAX blen=%d", sid, len(buf.buffer))
|
|
|
- gen += 1
|
|
|
|
|
- cur_gen["v"] = -1
|
|
|
|
|
- _drain_queue(play_q)
|
|
|
|
|
busy = True
|
|
busy = True
|
|
|
try:
|
|
try:
|
|
|
- await self._transcribe_and_respond(buf, play_q, gen)
|
|
|
|
|
|
|
+ await self._transcribe_and_respond(buf, play_q, cur_gen)
|
|
|
except Exception:
|
|
except Exception:
|
|
|
logger.exception("[%s] max failed", sid)
|
|
logger.exception("[%s] max failed", sid)
|
|
|
busy = False
|
|
busy = False
|
|
@@ -606,7 +597,7 @@ class Worker:
|
|
|
except Exception:
|
|
except Exception:
|
|
|
pass
|
|
pass
|
|
|
|
|
|
|
|
- async def _transcribe_and_respond(self, buf: AudioBuffer, play_q, gen: int):
|
|
|
|
|
|
|
+ async def _transcribe_and_respond(self, buf: AudioBuffer, play_q, cur_gen: dict):
|
|
|
all_audio = buf.get_all()
|
|
all_audio = buf.get_all()
|
|
|
buf.clear()
|
|
buf.clear()
|
|
|
if len(all_audio) <= 1600:
|
|
if len(all_audio) <= 1600:
|
|
@@ -616,6 +607,11 @@ class Worker:
|
|
|
if not txt:
|
|
if not txt:
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
|
|
+ # Real utterance — stop previous TTS, start new generation
|
|
|
|
|
+ cur_gen["v"] += 1
|
|
|
|
|
+ gen = cur_gen["v"]
|
|
|
|
|
+ _drain_queue(play_q)
|
|
|
|
|
+
|
|
|
logger.info("ASR: %s", txt[:80])
|
|
logger.info("ASR: %s", txt[:80])
|
|
|
await self._send({"type": "utterance", "text": txt, "seq": 0})
|
|
await self._send({"type": "utterance", "text": txt, "seq": 0})
|
|
|
|
|
|