How can I control the maximum duration of a sessio...
# ask-ai
a
How can I control the maximum duration of a session in live kit, like if someone is connected to my livekit server and their room is connected, the room is disconnected after 5 minutes?
t
Thanks for reaching out, Talha. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
I'm happy to help you manage the maximum duration of a session in LiveKit! You have a couple of great options to disconnect a room after a specific time: • Using the Server API: You can easily delete the room programmatically after a set time with the
deleteRoom
API. For instance, you might schedule a task to delete the room after 5 minutes (300 seconds). • Custom Monitoring: Another approach is to create a monitoring loop that keeps an eye on user activity and disconnects the room after a timeout period, like 5 minutes of inactivity. If you'd like, I’d be more than happy to walk you through the details of implementing either method. Just let me know how I can support you! Sources: livekit-agents/livekit/agents/utils/connection_pool.py | Inside a session | LiveKit Docs | SIP APIs | LiveKit Docs | Speech & Audio Processing | livekit/livekit_composite | DeepWiki
a
is there no a default parameter where I can adjust this number? This is a pretty important feature, how does it no have a native support?
t
I understand you're looking to set a maximum room duration or session timeout with LiveKit. While LiveKit doesn't have a built-in default parameter for that, you can definitely manage room activity using parameters like
empty_timeout
and
departure_timeout
. These help control how long a room stays active when no participants are around or after everyone leaves. To enforce session limits, a great approach is to add some custom logic at the application level. For example, you could use tokens with time-to-live (TTL) settings or programmatically delete rooms after a certain time using the Server API. If you'd like, I’m here to help you set up these configurations or guide you through implementing a custom solution. Just let me know! Sources: server/index.js | pkg/config/config.go | livekit/livekit_room.pb.go | pkg/config/base.go | SIP APIs | LiveKit Docs
a
Tell me how to setup these configurations
t
I'd love to help you set up configurations for managing room activity and enforcing session limits! Here are a few friendly approaches you can consider: 1. Using
empty_timeout
and `departure_timeout`:
These settings help control how long a room stays active when no one is inside or after everyone leaves. You can easily adjust these in your LiveKit server configuration file. 2. Using Tokens with Time-to-Live (TTL): By generating access tokens that expire after a certain time, participants will be disconnected automatically once their token runs out. This is something you manage when creating tokens in your application. 3. Programmatically Deleting Rooms: You can also use the LiveKit Server API to delete a room after a set period. For instance, scheduling a task to call the
deleteRoom
API after a specific duration works well. Feel free to let me know which option sounds best for you, and I’d be happy to walk you through the detailed steps to get it all set up!
a
how can I implement a custom solution
t
I'd be happy to help you implement a custom solution for enforcing session limits by managing room activity using the LiveKit Server API. Here's a friendly guide on how you can do it: 1. Set Up a Timer: You can use a scheduling mechanism within your application to keep track of how long a room has been active. For instance, a background task or a cron job works great to monitor room activity seamlessly. 2. Call the
deleteRoom
API:
Once the desired time limit is reached (say, 5 minutes), you can use the LiveKit Server API to delete the room, which will gracefully disconnect all participants. Here’s an example using the Python SDK to get you started:
Copy code
from livekit import api
import asyncio

async def delete_room_after_duration(room_name, duration):
    await asyncio.sleep(duration)  # Wait for the specified duration (in seconds)

    api_client = api.LiveKitAPI(
        "LIVEKIT_URL",  # Replace with your LiveKit server URL
        "LIVEKIT_API_KEY",  # Replace with your API key
        "LIVEKIT_API_SECRET"  # Replace with your API secret
    )

    await api_client.room.delete_room(api.DeleteRoomRequest(
        room=room_name
    ))

# Example: Delete a room named 'test-room' after 5 minutes (300 seconds)
asyncio.run(delete_room_after_duration("test-room", 300))
This method gives you the flexibility to enforce session limits tailored to your needs. If you’d like, I’m here to help you with the implementation or discuss any specific requirements you might have. Just let me know!
a
api.AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET) .with_identity(identity) .with_metadata(metadata_token) .with_grants(api.VideoGrants(room_join=True, room=room)) .to_jwt() how can I set the ttl in this?
t
To help you set the TTL (Time To Live) for your access token, you can use the
with_ttl()
method from the
AccessToken
class. Here's a friendly example to guide you through it:
Copy code
from livekit.api import AccessToken
import datetime

token = AccessToken(api_key="LIVEKIT_API_KEY", api_secret="LIVEKIT_API_SECRET")
token.with_identity(identity)
token.with_metadata(metadata_token)
token.with_grants(api.VideoGrants(room_join=True, room=room))

# Set TTL to 5 minutes (300 seconds)
token.with_ttl(datetime.timedelta(minutes=5))

jwt_token = token.to_jwt()
This will create a token that expires 5 minutes after it’s issued. If you have any questions or need a hand with anything else, just let me know—I’m here to help! Sources: livekit-api/tests/test_access_token.py
a
The maximum number of seconds since the user last spoke. If exceeded, the agent will respond and force a turn. How can I manage that in livekit?
t
Hi there! To help you manage the maximum time since a user last spoke and force a turn in LiveKit, here are some friendly approaches you can try: 1. Set Maximum Silence Duration: You can use the
max_endpointing_delay
parameter in the
AgentSession
configuration. This sets the maximum time (in seconds) the system waits after detecting silence before it gently nudges a turn. Here's an example:
Copy code
session = voice.AgentSession(
    turn_detection=turn_detector.MultilingualModel(),
    min_endpointing_delay=0.5,  # Minimum delay after silence
    max_endpointing_delay=6.0   # Maximum delay before forcing a turn
)
1. Force a Turn Manually: If you'd like, you can also programmatically force a turn using the
commit_user_turn()
method. Here's a quick snippet:
Copy code
session.commit_user_turn(transcript_timeout=2.0)
1. Custom Inactivity Handling: Another friendly option is to implement a custom timeout that keeps track of user activity and gently prompts after some silence. For example:
Copy code
class InactivityHandler:
    def __init__(self, timeout_seconds=10, message="Are you still there?"):
        self._timeout = timeout_seconds
        self._message = message

    async def _check_timeout(self):
        while True:
            await asyncio.sleep(1)
            if time.time() - self._last_active > self._timeout:
                await self._agent.say(self._message)
                break
I’m here if you want to dive deeper or need any help setting these up—just let me know! Sources: Turn detection and interruptions | LiveKit Docs | LiveKit turn detector plugin | LiveKit Docs | Improving voice AI's turn detection with transformers | AI voice agents | LiveKit Docs | Improving voice AI's turn detection with transformers
a
Can I set user_away_timeout to 15 sec and let catch it in @session.on("user_state_changed")? How can I tell an agent to say some speific words in this event function?
t
Absolutely! You can set
user_away_timeout
to 15 seconds and use the
@session.on("user_state_changed")
event to have the agent respond with specific words. Here’s a friendly example to guide you through it:
Copy code
async def entrypoint(ctx: JobContext):
    session = AgentSession(
        vad=silero.VAD.load(),
        llm=openai.LLM(model="gpt-4o-mini"),
        stt=deepgram.STT(),
        tts=cartesia.TTS(),
        user_away_timeout=15.0  # Set timeout to 15 seconds
    )

    @session.on("user_state_changed")
    def _user_state_changed(ev: UserStateChangedEvent):
        if ev.new_state == "away":
            # Make the agent respond with specific words
            asyncio.create_task(session.generate_reply(
                instructions="Are you still there?"
            ))

    await session.start(agent=Agent(instructions="You are a helpful assistant."), room=ctx.room)
So, with this setup, your agent will gently ask "Are you still there?" when it notices the user has been away for 15 seconds. If you have any questions or want to explore more, just let me know—I’m here to help! Sources: livekit-agents/livekit/agents/voice/events.py | agent_extensions/README.md
a
The maximum number of seconds since the user last spoke. If exceeded, the call will terminate. How can I implement this?
t
To gently wrap up a call after a set amount of silence from the user, you can create a custom solution using LiveKit's event system. Let me guide you through it: 1. Keep Track of When the User Speaks: Listen for the
user_started_speaking
event and update a timestamp each time the user talks. 2. Watch for Silence: Set up a background task that checks how long it’s been since the last time the user spoke. If it goes beyond your chosen limit, the call will disconnect.
Copy code
import asyncio
import time

SILENCE_THRESHOLD = 5  # seconds

async def entrypoint(ctx: JobContext):
    user_last_spoke_time = time.time()

    async def monitor_interaction():
        while True:
            if time.time() - user_last_spoke_time > SILENCE_THRESHOLD:
                await ctx.room.disconnect()  # Disconnect the room
                break
            await asyncio.sleep(1)

    @ctx.agent.on("user_started_speaking")
    def on_user_started_speaking(_msg):
        nonlocal user_last_spoke_time
        user_last_spoke_time = time.time()

    asyncio.create_task(monitor_interaction())
This method helps make sure the call ends smoothly if there’s been silence for too long. If you’d like, I’m here to help you with any part of this or answer any questions! Sources: Improving voice AI's turn detection with transformers | Improving voice AI's turn detection with transformers | SIP APIs | LiveKit Docs | Speech & Audio Processing | livekit/livekit_composite | DeepWiki | agent_extensions/agent_extensions/handlers/inactivity_handler.py
a
Is there any native way to perform this, or any other way?
t
I understand that LiveKit doesn’t have a built-in feature to automatically end a call based on user inactivity since the last speech. But don’t worry! You can still achieve this by using the custom solution I mentioned earlier, which uses the
user_started_speaking
event along with a monitoring task to keep track of silence duration. If your scenario involves SIP calls, another option is to use the
max_call_duration
parameter to set a limit on the total call time, although this isn’t specifically tied to user inactivity. Please feel free to reach out if you’d like some help implementing the custom solution or if you want to explore other possibilities together. I’m here to support you!
a
What custom solution can i implement?
t
To help you set up a custom solution that ends a call after a period of user inactivity, here’s a simple and effective approach you can try: 1. Track User Speech Events: Listen for the
user_started_speaking
event and update a timestamp each time the user speaks. This way, we know exactly when they last interacted. 2. Monitor Silence: Run a background task that keeps an eye on how much time has passed since the user last spoke. If the silence goes beyond your set limit, the system will disconnect the room automatically. Here’s a sample implementation to illustrate this:
Copy code
import asyncio
import time

SILENCE_THRESHOLD = 10  # seconds

async def entrypoint(ctx: JobContext):
    user_last_spoke_time = time.time()

    async def monitor_interaction():
        while True:
            if time.time() - user_last_spoke_time > SILENCE_THRESHOLD:
                await ctx.room.disconnect()  # Disconnect the room
                break
            await asyncio.sleep(1)

    @ctx.agent.on("user_started_speaking")
    def on_user_started_speaking(_msg):
        nonlocal user_last_spoke_time
        user_last_spoke_time = time.time()

    asyncio.create_task(monitor_interaction())
This way, the call will gracefully end if the user stays silent for longer than the time you specify. If you’d like, I’m here to help you customize this further to fit your exact needs—just let me know!
a
Is it good to do, like create a polling function which repeatedly checks for particular thing
t
Using a polling function to repeatedly check for user inactivity is definitely a valid approach, and with a little care, we can make sure it runs smoothly without using too many resources. Here are a few friendly tips to keep in mind: • Use Efficient Intervals: Try setting a reasonable polling interval, like around 1 second, so it stays responsive but doesn’t overwork your system. • Leverage Events: It’s great to combine polling with event-driven updates, such as the
user_started_speaking
event, which helps cut down on unnecessary checks. • Clean Up Tasks: Don’t forget to properly cancel or clean up the polling task when the session ends—this helps prevent any memory leaks down the road. Another option is to use asynchronous tools like
asyncio.wait_for
or event-based handlers to get the same result without constant polling. If you’d like, I’d be more than happy to share an example of how that works!
a
sure
t
Here’s a friendly alternative event-driven approach using
asyncio.wait_for
to handle user inactivity without the need for continuous polling:
Copy code
import asyncio
import time

SILENCE_THRESHOLD = 10  # seconds

async def entrypoint(ctx: JobContext):
    user_last_spoke_event = asyncio.Event()

    async def monitor_inactivity():
        while True:
            try:
                # Wait for the user to speak within the threshold
                await asyncio.wait_for(user_last_spoke_event.wait(), timeout=SILENCE_THRESHOLD)
                user_last_spoke_event.clear()  # Reset the event after user speaks
            except asyncio.TimeoutError:
                # Silence threshold exceeded, disconnect the room
                await ctx.room.disconnect()
                break

    @ctx.agent.on("user_started_speaking")
    def on_user_started_speaking(_msg):
        user_last_spoke_event.set()  # Signal that the user has spoken

    asyncio.create_task(monitor_inactivity())
This method helps us avoid constant polling by patiently waiting for either user activity or a timeout. It’s a neat and efficient way to ensure the room disconnects only when the silence threshold is truly exceeded. If you’d like me to walk you through any part of this or if you have more questions, please don’t hesitate to ask—I’m here to help!
a
Can I use chatterbox resemble AI in livekit?
t
Absolutely, you can integrate Resemble AI with LiveKit to unlock some amazing text-to-speech (TTS) features. Resemble AI offers both one-off synthesis and real-time streaming, so you can bring natural, human-like voice outputs right into your LiveKit applications. Here’s a simple way to get started: 1. Install the Plugin: If you’re using Python, just run:
pip install "livekit-agents[resemble]~=1.2"
2. Authenticate: You’ll need to provide your Resemble AI API key and
voice_uuid
(which identifies the voice) either as environment variables or directly in your code. 3. Use the Plugin: Here’s a quick example for one-off synthesis:
Copy code
from livekit.plugins import resemble
import asyncio

async def main():
    tts = resemble.TTS(
        api_key="your_api_key",
        voice_uuid="your_voice_uuid",
        sample_rate=44100,
        output_format="wav"
    )
    audio_stream = tts.synthesize("Hello, world!")
    async for chunk in audio_stream:
        print(f"Received audio chunk: {len(chunk.frame.data)} bytes")

asyncio.run(main())
If you’d like, I’m here to help you set up real-time streaming or explore any other customizations you have in mind. Just let me know! Sources: Resemble AI TTS integration guide | LiveKit Docs | livekit-plugins/livekit-plugins-resemble/livekit/plugins/resemble/py.typed | plugins/resemble/src/tts.test.ts | Resemble AI TTS integration guide | LiveKit Docs
a
is resemble free? and can I use chatterbox their open source TTS for my usage?
t
Thank you for reaching out! I wanted to let you know that Resemble AI isn’t free—accessing its WebSocket streaming API does require a Business plan subscription. I understand that can be a bit tricky. Also, regarding Chatterbox open-source TTS with LiveKit, there isn’t much information available at the moment. But don’t worry! If you have any specific needs or if you’d like, I’d be more than happy to help you explore other TTS options that might work well for you. Sources: livekit-plugins/livekit-plugins-resemble/pyproject.toml
a
Any open source TTS i can use which is compatible with livekit. Is there a way to use an open source TTS which I can use with livekit, which doesn't have a native support
t
I'm happy to help you use an open-source TTS engine with LiveKit by guiding you through creating a custom TTS plugin. LiveKit’s flexible plugin architecture lets you integrate any TTS system, even if it’s not natively supported. Here’s a simple way to get started: 1. Create a Custom TTS Class: You’ll want to extend the
tts.TTS
base class and implement the
stream()
method for real-time synthesis or
synthesize()
if you prefer non-streaming output. 2. Integrate Your TTS Engine: Consider using open-source options like Coqui TTS or MaryTTS. You can send your text input to the engine and then convert the generated audio into
AudioFrame
objects using LiveKit’s
AudioByteStream
. 3. Configure in AgentSession: Finally, add your custom TTS class to the
AgentSession
configuration, so it’s enabled within your LiveKit application. Here’s a quick example to illustrate:
Copy code
class CustomTTSEngine(tts.TTS):
    def __init__(self, model, sample_rate, num_channels):
        super().__init__(streaming=True, sample_rate=sample_rate, num_channels=num_channels)
        self._model = model

    async def stream(self):
        # Implement streaming logic here
        pass
This method lets you bring in any open-source TTS engine smoothly. If you’d like, I’m here to provide more detailed steps for a specific TTS engine you have in mind—just let me know! Sources: Text-to-speech (TTS) integrations | LiveKit Docs | plugins/elevenlabs/src/tts.ts | OpenAI Realtime API integration guide | LiveKit Docs