how can i make use of _SpeechHandle._SPEECH_PRIORI...
# ask-ai
b
how can i make use of _SpeechHandle._SPEECH_PRIORITY_HIGH
✅ 1
t
Thanks for reaching out, Jura. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I can help with that. Quick clarifying questions so I give the right guidance: • Which SDK / language are you using (Android Java/Kotlin, iOS Swift/Obj-C, Web, or other)? • Where are you seeing
SpeechHandle.SPEECH_PRIORITY_HIGH
(library/class name or file)? • What do you want to achieve by using it (e.g., prioritize live speech audio, override other audio, reduce latency)? With those details I’ll show exact usage and a short example. , with interactive elements
b
versions/3.12.11/lib/python3.12/site-packages/livekit/agents/voice/speech_handle.py
t
Thanks — you're using the Python agent at that path. To give a precise example, could you share: • The goal you want to achieve with
SPEECH_PRIORITY_HIGH
(e.g., ensure one speaker is prioritized, reduce interruptions, change mixer behavior). • A short snippet of how you currently create or use
SpeechHandle
(paste 5–10 lines around where it’s referenced). • Whether you're running the agent standalone or inside another orchestration (so I can recommend runtime changes if needed). With that I’ll show a minimal code example and explain effects of using
SPEECH_PRIORITY_HIGH
. , with interactive elements
b
i was using AgentSession.say()
t
Thanks — you're using
AgentSession.say()
in the Python agent. Quick answer:
SpeechHandle.SPEECH_PRIORITY_HIGH
is not a documented/available constant in the Python agents. Speech prioritization via a
SPEECH_PRIORITY_HIGH
flag is not supported. What you can do instead: • Use
allow_interruptions
when calling
session.say()
or
session.generate_reply()
to control whether user speech can interrupt the agent. • Use the returned
SpeechHandle
to control flow: ◦
await handle
or
await handle.wait_for_playout()
to wait until speech finishes before continuing. ◦ Add a done callback on the handle to run logic after playout completes. • If you need custom priority behavior (e.g., one utterance should preempt others or be queued ahead), implement it in your application: ◦ Keep a speech queue and decide when to call
session.say()
. ◦ Cancel or skip currently playing speech by not awaiting it and starting the higher-priority
say()
(respecting
allow_interruptions
). ◦ For finer control over audio level/behavior, provide a custom
tts_node
that applies volume/SSML or mixes audio as you need. If you want, paste a short snippet of how you call
session.say()
and describe the exact priority behavior you need (preempt, queue, never interrupt, simultaneous mixing). I’ll provide a minimal code example tailored to that. Sources: Agent speech and audio | LiveKit Documentation | Audio customization | LiveKit Documentation, with interactive elements
b
i'm using .say(), but the speech always got play after the main llm pipeline even though i called it before the llm even return first token
t
Thanks — I see you call
session.say()
before the LLM returns but the speech still plays after the LLM output. Here’s why that happens and how to make your speech play immediately. Why this happens • The agent uses an internal speech queue and the LLM/preemptive generation can take precedence if it already started. •
SpeechHandle.SPEECH_PRIORITY_HIGH
is not a usable flag in the Python agent for changing playback order. Speech is scheduled with the same default priority. What you can do (practical options) • Interrupt current/preemptive speech before scheduling yours:
Copy code
session.interrupt()            # stop current/queued speech
await session.say("Urgent text")
• Disable or avoid preemptive LLM generation when you need immediate speech (so the pipeline doesn’t already own the turn). If your flow enables preemptive generation, call
session.interrupt()
first. • Await the handle so you control sequencing:
Copy code
handle = session.say("Before LLM")
await handle.wait_for_playout()   # ensure this finishes before continuing
# then run LLM or other logic
• Use
allow_interruptions=False
when you want the user not to interrupt this utterance (doesn’t force earlier playback, but prevents interruption once playing):
Copy code
await session.say("Critical message", allow_interruptions=False)
• Implement app-level priority queuing: keep a small speech queue in your code and call
interrupt()
+
session.say()
for high-priority items. If you want, paste a short snippet showing where you call
session.say()
and whether preemptive generation is enabled; I’ll give a minimal code example tailored to that flow. Sources: Agent speech and audio | LiveKit Documentation | The ReAct Pattern for Voice Agents and How AI Agents Think, Act, and Respon... | Turns overview | LiveKit Documentation, with interactive elements
b
does the main thread use session.say()
t
Short answer: No —
session.say()
runs only when your code calls it; the main thread does not automatically call
session.say()
for you. Details: •
session.say()
is invoked by your agent code (or by handlers you implement). It returns a
SpeechHandle
and enqueues TTS for playback. • The agent’s main LLM pipeline (e.g., preemptive generation or
generate_reply()
hooks) can independently produce speech or schedule TTS; that pipeline may already own the speech queue when it starts generating, which is why a
say()
you call can end up played later. • To make a
say()
play immediately from your code, explicitly control the queue: use
session.interrupt()
to stop current/preemptive speech,
await handle.wait_for_playout()
to sequence, or disable/prevent preemptive generation so the pipeline doesn’t preempt your call. If you want, paste the handler or snippet where you call
session.say()
and whether preemptive generation is enabled — I’ll show the minimal change to force immediate playback. , with interactive elements
b
after calling speechHandle.interrupt(), can i later play the speech?
t
Short answer: Calling
speechHandle.interrupt()
stops that playback and clears it — you cannot resume the same SpeechHandle afterward. To play the same text later you must call
session.say()
(or `generate_reply()`/your TTS node) again. Recommended patterns • If you need the ability to replay after interrupting, keep the text or SSML and re-call:
Copy code
handle = await session.say("Important message")
# interrupt current/queued speech somewhere else
handle.interrupt()

# later — replay
handle2 = await session.say("Important message")
await handle2.wait_for_playout()
• If you want to preempt currently playing speech with a higher-priority message: ◦ Call
session.interrupt()
to stop current speech, then immediately call
session.say()
for the urgent text. • If you want queuing instead of losing interrupted content, implement an app-level speech queue that stores messages and retries/re-enqueues any interrupted entries. If you share the snippet where you call
interrupt()
and your desired behavior (replay immediately, queue for later, or preempt and discard), I’ll suggest the smallest code change to implement it. , with interactive elements
b
can i just interrupt speechHandle, then extract the message from it ?
t
Short answer: No — you cannot extract the spoken text from a
SpeechHandle
after interrupting it.
SpeechHandle
controls playback state (wait, interrupt, callbacks) but does not expose the original message payload. What to do instead • Store the message/SSML when you call
session.say()
so you can re-play it later:
Copy code
text = "Important message"
handle = await session.say(text)
# later
handle.interrupt()
# replay
await session.say(text)
• If you need automatic replaying or persistent queueing, keep your own speech queue (store message + metadata) and on interrupt re-enqueue or resend the stored entry. • For preemption flows: call
session.interrupt()
then immediately
session.say()
your high-priority text so it plays right away. If you share a short snippet of your current code, I can show the minimal change to persist messages or implement a replay/queue pattern. , with interactive elements
b
how can i extract the speech message from the speechHandle?
t
Short answer: You can't.
SpeechHandle
does not expose the original text/SSML payload. What to do instead • Save the message when you call
session.say()
and reuse it later:
Copy code
text = "Important message"
handle = await session.say(text)

# interrupt
handle.interrupt()

# replay later
await session.say(text)
• For replay/queue behavior, keep an app-level queue of {text, metadata, timestamp} and re-enqueue entries when interrupted. • For preempting/forcing immediate play: call
session.interrupt()
then immediately
session.say()
the stored text. If you paste the snippet where you call
session.say()
, I’ll show the minimal change to persist messages or implement replay/queue logic. , with interactive elements