Skip to main content

Advanced Usage

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

Understanding the apiKey Parameter

The KalturaAvatarSession constructor accepts an optional apiKey in the configuration object:

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

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

When to include apiKey in config:

  • 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
New Signature

The apiKey is now part of the config object for a cleaner API. The legacy signature new KalturaAvatarSession(apiKey, config) still works but shows a deprecation warning.

Custom Logging

Configure logging levels for debugging:

const session = new KalturaAvatarSession({
apiKey: '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({
apiKey: 'your-api-key',
...config
});
const session2 = new KalturaAvatarSession({
apiKey: 'your-api-key',
...config
});

await Promise.all([
session1.createSession({
visualId: 'visual-1',
videoContainerId: 'container-1',
}),
session2.createSession({
visualId: 'visual-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({
visualId: 'visual-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,
TTSLanguage,
CatalogServiceConfig,
CatalogItem,
} from '@unisphere/models-sdk-js';

import { TTSLanguages, CatalogService } from '@unisphere/models-sdk-js';

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

const options: CreateSessionOptions = {
visualId: 'visual-123',
voiceId: 'voice-456',
language: TTSLanguages.ENGLISH,
videoContainerId: 'avatar-container',
};

Next Steps