Skip to main content

Advanced Usage

Advanced topics and customization options for the Kaltura Avatar Client SDK.

Understanding the apiKey Parameter

The KalturaAvatarSession constructor takes an optional apiKey parameter:

// FE-only control - SDK creates the session
const session = new KalturaAvatarSession('your-kaltura-session', config);
await session.createSession({ avatarId: 'avatar-123' });

// BE/FE split - Backend creates session, SDK displays only
const session = new KalturaAvatarSession(undefined, config); // No apiKey!
const { sessionId, token } = await myBackend.createSession();
await session.initSession({ sessionId, token });

When to pass apiKey:

  • Only when you want the SDK to create sessions (demos, quick testing)
  • Not recommended for production

When to omit apiKey:

  • When backend creates sessions (recommended)
  • In initSession() flow - token comes from backend

Custom Logging

Configure logging levels for debugging:

const session = new KalturaAvatarSession('your-api-key', {
baseUrl: '...',
logLevel: 'debug', // 'debug' | 'info' | 'warn' | 'error'
});

Log levels:

  • debug - All logs including verbose debug info
  • info - Normal operation logs (default)
  • warn - Warnings only
  • error - Errors only

Say Text with Streaming Support

Use sayText with turnId and isFinal parameters for LLM streaming:

// Generate unique turn ID for this conversation turn
const turnId = `turn-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

// Streaming chunks from LLM
const chunks = ['Hello, ', 'this is ', 'a ', 'streaming ', 'response.'];

for (let i = 0; i < chunks.length; i++) {
const isFinal = i === chunks.length - 1; // Last chunk?
await session.sayText(chunks[i], turnId, isFinal);
}

Multiple Sessions

Run multiple avatar sessions simultaneously:

const session1 = new KalturaAvatarSession('your-api-key', config);
const session2 = new KalturaAvatarSession('your-api-key', config);

await Promise.all([
session1.createSession({
avatarId: 'avatar-1',
videoContainerId: 'container-1',
}),
session2.createSession({
avatarId: 'avatar-2',
videoContainerId: 'container-2',
}),
]);

// Control them independently
await session1.sayText('Hello from avatar 1');
await session2.sayText('Hello from avatar 2');

Custom Video Element Handling

If you need full control over the video element:

// Create session without auto-attach
await session.createSession({
avatarId: 'avatar-123',
});

// Get the media stream manually
const stream = session.getMediaStream(); // Advanced: not in basic API

// Create your own video element
const video = document.createElement('video');
video.srcObject = stream;
video.autoplay = true;
video.playsinline = true;
video.style.width = '100%';

// Custom container setup
const container = document.getElementById('my-custom-container');
container.appendChild(video);

Connection Quality

Monitor connection quality:

session.on('connectionChange', (state) => {
if (state === 'CONNECTED') {
console.log('Streaming started');
} else if (state === 'FAILED') {
console.log('Poor network quality');
}
});

TypeScript Tips

Full TypeScript support with no additional packages needed:

import type { AvatarConfig, CreateSessionOptions, SessionState, ConnectionState, AvatarError, AvatarErrorCode } from '@unisphere/models-sdk-js';

const config: AvatarConfig = {
baseUrl: 'https://api.avatar.us.kaltura.ai/v1/avatar-session',
logLevel: 'info',
};

const options: CreateSessionOptions = {
avatarId: 'avatar-123',
voiceId: 'voice-456',
videoContainerId: 'avatar-container',
};

Next Steps