Avatario Plugin for LiveKit Agents
Bringing lifelike AI avatars with synchronized speech and facial animation to your LiveKit-powered applications
Introduction
Avatario brings lifelike AI avatars with synchronized speech and facial animation to your LiveKit-powered applications. This plugin enables seamless integration of Avatario avatars as participants in your LiveKit rooms.
Installation
Install the plugin using PyPi:
pip install livekit-plugins-avatarioai
Authentication & Setup
The Avatario plugin requires a Avatario API key.
Set AVATARIO_API_KEY in your environment or .env file where your LiveKit worker code is running:
# In your environment or .env file
AVATARIO_API_KEY=your_api_key_here
Available Avatars
We provide a list of stock avatars that can be accessed using the following curl command:
curl --request GET \
--url https://app.onezot.work/api/avatars/stock \
-H "Content-Type: application/json"
This returns a list of our stock avatars along with their attributes and IDs that you can use in your integration.
You can also find detailed information about our stock avatars in the Stock Avatars documentation.
Usage
Use the plugin in an AgentSession. For example, you can use this avatar in theVoice AI quickstart
from livekit import agents
from livekit.agents import AgentSession, RoomOutputOptions
from livekit.plugins import avatarioai
async def entrypoint(ctx: agents.JobContext):
await ctx.connect()
session = AgentSession(
# ... stt, llm, tts, etc.
)
avatar = avatarioai.AvatarSession(
avatar_id="...", # ID of the avatario avatar to use
video_info=avatarioai.VideoInfo(
custom_background_url="https://xyz.com",
video_frame_height=720,
video_frame_width=1080,
)
)
# Start the avatar and wait for it to join
await avatar.start(session, room=ctx.room)
# Start your agent session with the user
await session.start(
room=ctx.room,
room_output_options=RoomOutputOptions(
# Disable audio output to the room. The avatar plugin publishes audio separately.
audio_enabled=False,
),
# ... agent, room_input_options, etc....
)
Parameters
This section describes some of the available parameters. See the plugin reference for a complete list of all available parameters.
avatar_id string Required
ID of the Avatario avatar to use. See Stock Avatars for reference.
avatar_participant_name string Optional Default: avatario-avatar-agent
The name of the participant to use for the avatar.
video_info VideoInfo Optional
Video configuration settings including custom background and frame dimensions.
- custom_background_url (string): URL of custom background image. If URL is invalid or image cannot be downloaded, a plain white background will appear.
- video_frame_width (integer): Width of video frame (default: 1080, maximum: 1920)
- video_frame_height (integer): Height of video frame (default: 720, maximum: 1080)
video_frame_width integer Optional Default: 1280
The width of video frame to be streamed (maximum 1920)
video_frame_height integer Optional Default: 720
The height of the video frame to be streamed (maximum 1080)
Frontend Integration
There are two main ways to integrate Avatario avatars in your frontend applications using LiveKit:
Method 1: LiveKit Agents Playground
The easiest way to test and interact with Avatario avatars is through the LiveKit Agents Playground.
Steps:
- Visit the LiveKit Agents Playground
- Choose one of two connection methods:
- LiveKit Cloud: Click "Continue with LiveKit Cloud" for the easiest setup
- Manual: Click the "Manual" tab and enter your LiveKit token and WebSocket URL
- Click "Connect" to establish the connection
- Start interacting with your Avatario avatar in real-time
Note: This method is perfect for testing and prototyping. For production applications, use the HTML/JavaScript integration method below.
Method 2: HTML/JavaScript Integration
For custom frontend applications, you can integrate directly using the LiveKit client SDK.
Minimal HTML Example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Avatario Avatar Demo</title>
<script src="https://cdn.jsdelivr.net/npm/livekit-client@2.13.3/dist/livekit-client.umd.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #000;
color: #fff;
}
.video-container {
position: relative;
width: 100%;
max-width: 640px;
aspect-ratio: 16/9;
background: #222;
border-radius: 8px;
overflow: hidden;
margin: 20px 0;
}
video {
width: 100%;
height: 100%;
object-fit: cover;
}
.local-video {
position: absolute;
bottom: 10px;
right: 10px;
width: 150px;
height: 100px;
border: 2px solid #fff;
border-radius: 8px;
}
.controls {
display: flex;
gap: 10px;
margin: 20px 0;
}
button {
padding: 10px 20px;
border: none;
border-radius: 5px;
background: #007bff;
color: white;
cursor: pointer;
}
button:disabled {
background: #666;
cursor: not-allowed;
}
button.disconnect {
background: #dc3545;
}
</style>
</head>
<body>
<h1>Avatario Avatar Demo</h1>
<div class="controls">
<button id="connectBtn">Connect to Avatar</button>
<button id="disconnectBtn" disabled>Disconnect</button>
<button id="toggleAudio">Mute Audio</button>
<button id="toggleVideo">Turn Off Video</button>
</div>
<div class="video-container">
<video id="remoteVideo" autoplay playsinline></video>
<video id="localVideo" class="local-video" autoplay playsinline muted></video>
<audio id="remoteAudio" autoplay></audio>
</div>
<div id="status">Ready to connect...</div>
<script>
const { Room, RoomEvent, Track } = LiveKitClient;
let room = null;
let isAudioEnabled = true;
let isVideoEnabled = true;
// Get DOM elements
const connectBtn = document.getElementById('connectBtn');
const disconnectBtn = document.getElementById('disconnectBtn');
const toggleAudioBtn = document.getElementById('toggleAudio');
const toggleVideoBtn = document.getElementById('toggleVideo');
const remoteVideo = document.getElementById('remoteVideo');
const localVideo = document.getElementById('localVideo');
const remoteAudio = document.getElementById('remoteAudio');
const status = document.getElementById('status');
// Replace these with your actual values
const LIVEKIT_URL = 'wss://your-livekit-server.com';
const ACCESS_TOKEN = 'your-access-token';
async function connectToRoom() {
try {
status.textContent = 'Connecting...';
connectBtn.disabled = true;
// Create room instance
room = new Room({
adaptiveStream: true,
dynacast: true
});
// Set up event listeners
room.on(RoomEvent.Connected, () => {
status.textContent = 'Connected! Waiting for avatar...';
disconnectBtn.disabled = false;
});
room.on(RoomEvent.Disconnected, () => {
status.textContent = 'Disconnected';
connectBtn.disabled = false;
disconnectBtn.disabled = true;
});
room.on(RoomEvent.ParticipantConnected, (participant) => {
if (participant.identity.includes('avatar')) {
status.textContent = 'Avatar connected!';
}
});
room.on(RoomEvent.TrackSubscribed, (track, publication, participant) => {
if (track.kind === Track.Kind.Video) {
track.attach(remoteVideo);
} else if (track.kind === Track.Kind.Audio) {
track.attach(remoteAudio);
}
});
// Connect to room
await room.connect(LIVEKIT_URL, ACCESS_TOKEN);
// Enable camera and microphone
await room.localParticipant.enableCameraAndMicrophone();
// Attach local video
const videoTrack = room.localParticipant.getTrackPublication(Track.Source.Camera);
if (videoTrack?.track) {
videoTrack.track.attach(localVideo);
}
} catch (error) {
console.error('Connection failed:', error);
status.textContent = 'Connection failed: ' + error.message;
connectBtn.disabled = false;
}
}
async function disconnectFromRoom() {
if (room) {
room.disconnect();
room = null;
}
}
async function toggleAudio() {
if (room) {
isAudioEnabled = !isAudioEnabled;
await room.localParticipant.setMicrophoneEnabled(isAudioEnabled);
toggleAudioBtn.textContent = isAudioEnabled ? 'Mute Audio' : 'Unmute Audio';
}
}
async function toggleVideo() {
if (room) {
isVideoEnabled = !isVideoEnabled;
await room.localParticipant.setCameraEnabled(isVideoEnabled);
toggleVideoBtn.textContent = isVideoEnabled ? 'Turn Off Video' : 'Turn On Video';
}
}
// Event listeners
connectBtn.addEventListener('click', connectToRoom);
disconnectBtn.addEventListener('click', disconnectFromRoom);
toggleAudioBtn.addEventListener('click', toggleAudio);
toggleVideoBtn.addEventListener('click', toggleVideo);
</script>
</body>
</html>
Setup Requirements:
- Replace
LIVEKIT_URL
with your LiveKit server WebSocket URL - Replace
ACCESS_TOKEN
with a valid LiveKit access token - Ensure your LiveKit server is running with the Avatario plugin configured
- Make sure your avatar agent is running and connected to the same room
Important: This is a minimal example for demonstration. For production use, implement proper error handling, token refresh, and additional LiveKit features as needed.