Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

SpeakingRateStream blocks event loop 100–200ms on TTS audio bursts (TranscriptSynchronizer)

Open
#7,921 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@ninglinLiu is already working on this.

Since Oct 18, 2026.

  • #7927 by @ninglinLiu — open
  • #7938 by @longcw — open

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
20/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
python

Research direction

Start with voice/transcription/_speaking_rate.py, especially SpeakingRateStream._main_task, _stft, and _spectral_flux; trace how buffered audio windows are processed and inspect the event loop blocking reports in the issue. Compare the proposed yielding, thread, and vectorization approaches, then check interrupted-turn transcript behavior with sync_transcription enabled. Done means bursts no longer block the loop while synchronized transcripts remain accurate; two open pull requests are already linked.

Written by the indexing model from the issue text.

Description

Environment

  • livekit-agents 1.8.3 (voice/transcription/_speaking_rate.py unchanged through 1.8.8)
  • Python 3.14, Linux container (LiveKit Cloud agent)
  • sync_transcription left at default (enabled)

What happens

The event loop monitor reports repeated stalls while the agent is speaking, several per session:

event loop blocked for 184ms at ".../livekit/agents/voice/transcription/_speaking_rate.py", line 153, in _main_task
event loop blocked for 134ms at ".../_speaking_rate.py", line 220, in _stft
event loop blocked for 105ms at ".../_speaking_rate.py", line 242, in _spectral_flux

cpu_time roughly equals duration in every report, so this is pure CPU work on the loop thread, not I/O.

Cause

In SpeakingRateStream._main_task, the inner while True loop runs _compute_speaking_rate (STFT + spectral flux over a 1s window) once for every step_size (0.1s) of buffered audio, without yielding to the loop. TTS delivers audio faster than real time, so a single burst queues many windows, and they are all computed back-to-back on the event loop.

Current workaround and its cost

The only option on our side is RoomOptions(text_output=TextOutputOptions(sync_transcription=False)). That removes synchronized_transcript, so an interrupted agent turn is stored in the chat context with its full generated text, including words that were never played (agent_activity.py, around L3319). We rely on accurate transcripts, so this isn't a viable trade.

Suggested fixes

Any one of these would help:

  • run the window computation in a thread (asyncio.to_thread or an executor), batching pending windows
  • await asyncio.sleep(0) between windows so other tasks get scheduled
  • vectorise the STFT across all pending windows in a single numpy call
Dominant language
Python
Stars
14.6k
Forks
3.9k
Avg merge
3d 14h
Merged PRs (30d)
169

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from livekit/agents

All issues in livekit/agents

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.