In a LiveKit server outbound voice call, how can a...
# ask-ai
b
In a LiveKit server outbound voice call, how can an agent end the call once the conversation is done?
t
Thanks for reaching out, MOHAN. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
b
I want to do this in NodeJS
t
If you want to end a LiveKit server outbound voice call, the agent can simply use the
delete_room
API to wrap things up for everyone on the call. Here’s a quick rundown: 1. First, make sure the agent finishes any ongoing speech so everything feels natural and smooth. 2. Then, call the
delete_room
API to close out the call session. Here’s a handy example to show you how it works:
Copy code
async def end_call(self, ctx: RunContext):
    """Called when the user wants to end the call"""
    <http://logger.info|logger.info>(f"ending the call for {self.participant.identity}")

    # Let the agent finish speaking
    current_speech = ctx.session.current_speech
    if current_speech:
        await current_speech.wait_for_playout()

    # Delete the room to end the call for all participants
    await ctx.api.room.delete_room(
        api.DeleteRoomRequest(room=ctx.room.name)
    )
Doing this helps make sure the call ends smoothly for everyone involved. Sources: Agents telephony integration | LiveKit Docs | Agents telephony integration | LiveKit Docs | agent.py | basics/exit_message.py
b
I want to do this in NodeJS. Where exactly should I use this method ?
t
When you’re working with a Node.js app, a great way to end a call is by using the
deleteRoom
method from the
RoomServiceClient
. This usually happens once the conversation wraps up and the agent confirms it’s time to hang up. Here are a couple of friendly examples of where you might use this: 1. In a Webhook or API Endpoint: If your app has an API endpoint that lets agents end calls, you can call
deleteRoom
right inside that endpoint’s handler. 2. In a Button Click Handler: If agents are using a web interface, you can trigger the
deleteRoom
method when they click an "End Call" button. Here’s an example for an API endpoint:
Copy code
const express = require('express');
const { RoomServiceClient } = require('@livekit/server-sdk');

const app = express();
const roomClient = new RoomServiceClient('YOUR_LIVEKIT_HOST', 'YOUR_API_KEY', 'YOUR_API_SECRET');

<http://app.post|app.post>('/end-call', async (req, res) => {
  const { roomName } = req.body;

  try {
    await roomClient.deleteRoom(roomName);
    res.status(200).send(`Room ${roomName} deleted successfully`);
  } catch (error) {
    console.error(`Error deleting room ${roomName}:`, error);
    res.status(500).send('Failed to end the call');
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));
And here’s how you might handle that with a button click on a web app:
Copy code
document.getElementById('endCallButton').addEventListener('click', async () => {
  const roomName = 'your-room-name';

  try {
    await fetch('/end-call', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ roomName }),
    });
    alert('Call ended successfully');
  } catch (error) {
    console.error('Failed to end the call:', error);
  }
});
These examples should help you smoothly integrate the
deleteRoom
method into your app’s flow, making sure calls are properly ended when your agent is ready.
b
I am not using any frontEnd. Its completely handling in livekit server sdk. Can we use tools ? If yes. could you share the code snippet
t
If you’re managing everything server-side with the LiveKit Server SDK, you’ve got some handy options like schedulers, event listeners, or specific triggers to call the
deleteRoom
method automatically. For instance, you might want to end the call when a certain event happens or after a timeout, or even when an admin decides to wrap things up. Here’s a little code snippet to show you how you can use
deleteRoom
on the server side:
Copy code
const { RoomServiceClient } = require('@livekit/server-sdk');

// Initialize the RoomServiceClient with your LiveKit credentials
const roomClient = new RoomServiceClient(
  process.env.LIVEKIT_HOST,  // Your LiveKit host URL from environment variables
  process.env.LIVEKIT_API_KEY,  // Your API key from environment variables
  process.env.LIVEKIT_API_SECRET  // Your API secret from environment variables
);

// Function to end the call programmatically
async function endCall(roomName) {
  try {
    await roomClient.deleteRoom(roomName);
    console.log(`Room ${roomName} deleted successfully`);
  } catch (error) {
    console.error(`Error deleting room ${roomName}:`, error);
  }
}

// Example usage: Triggering the function based on a condition
setTimeout(() => {
  const roomName = 'your-room-name'; // Swap this with your actual room name
  endCall(roomName);
}, 60000); // Ends the call after 60 seconds
Just to break it down: • We’re using
setTimeout
here to mimic a condition, like ending the call after a minute. • You can swap out
setTimeout
for anything else that fits your needs, like listening for specific events or triggers. This way, you can keep everything running smoothly on the server side without needing to touch the frontend at all.
b
Hey, I want to end the call only If user want to end the call at the end of conversation. its there any way ?
t
To make sure the call only ends when the user really wants it to, you can set up a way to listen for a clear signal or action from them. Since everything is handled server-side, here’s a friendly approach you can take: 1. Using a Signal from the User: The user can send a signal—like pressing a button in their app or making a specific API call—to let you know they want to end the call. 2. Listening for a Custom Event: If the user interacts through a client, you can listen for a custom event or message from them that triggers ending the call. Here’s a simple example of how you might handle this in Node.js:
Copy code
const { RoomServiceClient } = require('@livekit/server-sdk');

// Initialize the RoomServiceClient with your LiveKit credentials
const roomClient = new RoomServiceClient(
  process.env.LIVEKIT_HOST,  // Your LiveKit host URL from environment variables
  process.env.LIVEKIT_API_KEY,  // Your API key from environment variables
  process.env.LIVEKIT_API_SECRET  // Your API secret from environment variables
);

// Function to end the call programmatically
async function endCall(roomName) {
  try {
    await roomClient.deleteRoom(roomName);
    console.log(`Room ${roomName} deleted successfully`);
  } catch (error) {
    console.error(`Error deleting room ${roomName}:`, error);
  }
}

// Example: Listening for a user signal to end the call
const express = require('express');
const app = express();
app.use(express.json());

<http://app.post|app.post>('/end-call', async (req, res) => {
  const { roomName } = req.body;

  try {
    await endCall(roomName);
    res.status(200).send(`Call for room ${roomName} ended successfully`);
  } catch (error) {
    console.error(`Error ending call for room ${roomName}:`, error);
    res.status(500).send('Failed to end the call');
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));
Here’s what’s happening: • The user sends a POST request to the
/end-call
endpoint with the room name when they’re ready to end the call. • The server listens for this request and then calls the
deleteRoom
method to close the call. This way, you’re making sure the call only ends when the user truly wants it to. If you have any questions or want to tweak this further, just let me know—I’m here to help!
b
NodeJs how to get the ttft and ttfb in server side not frontend (react) ?
Copy code
import { metrics, pipeline } from '@livekit/agents';

// Subscribe to metrics collection events and process accordingly
agent.on(pipeline.VPAEvent.METRICS_COLLECTED, (mtrcs: metrics.AgentMetrics) => {
  metrics.logMetrics(mtrcs);
})
its not returning the ttfb
t
Hey there! Just a quick note: the code snippet you shared for metrics collection doesn’t currently include TTFB (Time to First Byte). If you want to capture TTFB or TTFT (Time to First Token) on the server side with Node.js, you’ll want to make sure the metrics you’re listening to actually include those details. If the
METRICS_COLLECTED
event isn’t giving you TTFB, it might be that the current LiveKit SDK version doesn’t support it directly. To help you better, could you please check: • Are you running the latest version of the LiveKit SDK? • Do you have any special configurations or plugins set up for metrics collection? If TTFB is super important for what you’re working on, you might need to add some custom code to measure it—like tracking the time from when the request starts until the first byte arrives. Feel free to reach out if you want me to walk you through that or if you have any other questions!
b
I am using livekit v.0 in nodeJS I don't have the special configuration
t
Thanks for confirming that you’re using LiveKit v0 in Node.js without any special configurations. With your current setup, the LiveKit SDK doesn’t automatically provide TTFB (Time to First Byte) or TTFT (Time to First Token) metrics in the metrics collection events. If you want to track TTFB or TTFT, you can add a bit of custom logic to measure these yourself. For example: • TTFB: Note the time when you send a request and then check the time when the first byte of the response arrives. • TTFT: If it fits your use case, you can measure the time from starting a request to receiving the first token of a response (like in text-to-speech or language model interactions). Here’s a simple example of how you might manually measure TTFB:
Copy code
const fetch = require('node-fetch');

async function measureTTFB(url) {
  const startTime = Date.now();

  const response = await fetch(url);
  const firstByteTime = Date.now();

  console.log(`TTFB: ${firstByteTime - startTime} ms`);

  return response;
}

measureTTFB(process.env.TARGET_URL);
Just swap out
process.env.TARGET_URL
with the URL you want to test. Feel free to tweak this to fit your specific needs. And if you want a hand setting this up or have any other questions, just let me know—I’m here to help!
b
this code won't help me. can you give the code with livekit node js server
t
I don't have the answer you're looking for. You could also try asking your question: • in one of the other Slack channels or • to https://deepwiki.com/livekit/livekit_composite which is trained on all LiveKit source code If you find the answer, please post it here to help others!