Kaltura PlayKit Player: Embedding & Control Guide¶
Embed Kaltura's PlayKit player in web applications using iframe or dynamic JavaScript. Both methods support KS-based access control, clipping, autoplay, and full programmatic control via the player API.
Base URL: https://cdnapisec.kaltura.com/p/{PARTNER_ID}/embedPlaykitJs/uiconf_id/{PLAYER_ID} (may differ by region)
Auth: Optional KS for access-controlled content (see Session Guide)
Format: HTML embed (iframe) or JavaScript SDK (PlayKit)
1. When to Use¶
- Website and app video playback — Embed adaptive video and audio playback in websites, web apps, and mobile web views using iframe or JavaScript integration.
- Branded player customization — Configure player appearance (watermarks, custom CSS, UI component toggles) and behavior (autoplay, looping, stream priority) to match your application's branding.
- Interactive video delivery — Enable in-player experiences such as chapter navigation, dual-screen slides, in-video quizzes, hotspots, and transcript search through the 30+ plugin ecosystem.
- Access-controlled content — Deliver protected video content using KS-based authentication, entry-scoped sessions, privacy contexts, and IP tokenization for CDN-protected delivery.
- Programmatic player control — Build custom playback workflows with play/pause/seek APIs, event listeners for progress tracking, and runtime plugin control for dynamic layout switching.
2. Prerequisites¶
- KS (Kaltura Session): Optional for public content. For access-controlled entries, generate a USER KS (type=0) scoped with
sview:ENTRY_IDon your server and pass it to the player. For IP-tokenized delivery, includeiprestrict:VIEWER_IP. - Player instance (uiConfId): A player configuration created in the KMC under Studio > TV Platform or Studio > Player. The
uiConfIddetermines which plugins are available and the default player settings. - Partner ID: Your Kaltura account ID, used to construct the player library URL and authenticate API requests.
- Session management: See Session Guide for KS generation and privilege scoping.
3. Embed Type Comparison¶
- Iframe embed – Simplest drop-in, ideal for quick embedding where the host page manages layout only. Works well for sites that restrict JavaScript to first-party code. Control the configuration passed to the player by adding query string params.
- Dynamic JS (PlayKit) – recommended when you need runtime config, start time, programmatic control, or richer integrations.
4. Kaltura Player Iframe Embed¶
Use the Kaltura iframe endpoint and pass parameters via query string. This form accepts entry_id, uiconf_id, optional ks, and most common initial config and playback flags.
<!-- Responsive container -->
<div style="position:relative;max-width:100%;aspect-ratio:16/9;">
<iframe
id="kaltura_player"
title="Kaltura video"
src="https://cdnapisec.kaltura.com/p/{PARTNER_ID}/embedPlaykitJs/partner_id/{PARTNER_ID}/uiconf_id/{PLAYER_INSTANCE_ID}?iframeembed=true&ks={KALTURA_SESSION}&entry_id={ENTRY_ID}&kalturaSeekFrom={CLIP_START_SECONDS}&kalturaClipTo={CLIP_END_SECONDS}&config[playback]={"autoplay":true,"mutedAutoPlay":true,"muted":true}"
allowfullscreen=""
allow="autoplay *; fullscreen *; encrypted-media *"
style="width: 100%; height: 100%; aspect-ratio: 16 / 9; min-width: 100%; background-color: black; border: 0px; border-radius: 0.5rem; overflow: hidden;" >
</iframe>
</div>
iframe Params Replacement Tokens¶
- {PARTNER_ID} - is your Kaltura account ID.
- {PLAYER_INSTANCE_ID} - is your Player Instance ID (
uiConfId). Find it in the Kaltura Management Console (KMC) under Studio > TV Platform or Studio > Player — each player configuration has a numeric ID displayed in the list or detail view. - {KALTURA_SESSION} - is a valid Kaltura Session that can be used to access the video Kaltura Entry ID to be played in this session (if playback is anonymous and the entry id open to public, this param can be skipped).
- {ENTRY_ID} - The ID of the video to be played.
- {CLIP_START_SECONDS} - will clip the video from that particular start second. if skipped - video will begin from the start.
- {CLIP_END_SECONDS} - will clip the video to that second. if skipped, the video will play to its full duration.
config[playback] params:¶
autoplay- set totrueto begin playback automatically orfalseto begin at paused state.muted- set totrueto begin playback muted (volume=0).mutedAutoPlay- set totrueto ensure autoplay always begin playback muted.
Other iframe Embed Notes¶
- To make the iframe responsive ensure a wrapping div is set and the iframe has a defined
aspect-ratio. - Set a meaningful
titlefor accessibility and SEO. - Ensure to include
allowandallowfullscreenattributes for autoplay/PiP/encrypted-playback/fullscreen.
Note: we're using cdnapisec.kaltura.com in this example, but your account region/deployment may differ. Make sure to use the correct base URL of your Kaltura account.
5. Dynamic JS (PlayKit) embed¶
Load the PlayKit/Kaltura Player JS for your PID/UiConfID, then call KalturaPlayer.setup(...) and loadMedia(...).
The code below assumes the same tokens as above.
<!-- 1) Load player library for your PID/UiConfID -->
<script src="https://cdnapisec.kaltura.com/p/{PARTNER_ID}/embedPlaykitJs/uiconf_id/{PLAYER_INSTANCE_ID}/kaltura-player.js" type="text/javascript"></script>
<!-- 2) Player container -->
<div id="kplayer" style="max-width:100%;aspect-ratio:16/9;"></div>
<script>
// 3) Setup with provider + playback; pass KS here when needed
try {
const player = KalturaPlayer.setup({
targetId: 'kplayer',
provider: {
partnerId: {PARTNER_ID},
uiConfId: {PLAYER_INSTANCE_ID},
ks: '{KALTURA_SESSION}' // optional if content is public
// env: { serviceUrl: 'https://www.kaltura.com' } // override if needed
},
playback: {
autoplay: true,
muted: true
}
});
// 4) Load media and optionally start at N seconds
player.loadMedia(
{ entryId: '{ENTRY_ID}' },
{ seekFrom: {CLIP_START_SECONDS}, clipTo: {CLIP_END_SECONDS} }
);
// Wait for the player to be ready (tracks loaded, safe to query state)
player.ready().then(() => {
console.log("player is ready!");
});
} catch (e) {
console.error(e.message);
}
5.1 Full KalturaPlayer.setup() Config Object¶
The KalturaPlayer.setup() call accepts a configuration object with the following top-level sections:
const player = KalturaPlayer.setup({
targetId: 'kplayer', // Required: DOM element ID for the player container
log: { level: 'ERROR' }, // Log level: 'DEBUG', 'INFO', 'WARN', 'ERROR', 'OFF'
provider: {
partnerId: PARTNER_ID, // Required: Kaltura partner ID (integer)
uiConfId: UICONF_ID, // Required: Player instance ID from KMC
ks: 'KS_STRING', // Optional: Kaltura Session for authenticated playback
env: {
serviceUrl: 'https://www.kaltura.com', // API service URL (override for non-default regions)
cdnUrl: 'https://cdnapisec.kaltura.com' // CDN URL (override for non-default regions)
}
},
playback: {
autoplay: true, // Auto-start playback (requires muted:true in most browsers)
muted: false, // Start muted
mutedAutoPlay: true, // Fall back to muted autoplay if unmuted autoplay is blocked
loop: false, // Loop playback when media ends
startTime: 0, // Start playback at this position (seconds)
volume: 1.0, // Initial volume (0.0 - 1.0)
playsinline: true, // Inline playback on mobile (no fullscreen takeover)
preload: 'auto', // Preload behavior: 'auto', 'metadata', 'none'
allowMutedAutoPlay: true, // Allow muted autoplay as fallback
streamPriority: [
{ engine: 'html5', format: 'hls' },
{ engine: 'html5', format: 'dash' },
{ engine: 'html5', format: 'progressive' }
]
},
ui: {
disable: false, // Disable the entire UI
css: '', // Custom CSS string injected into the player
components: {
seekbar: { disabled: false }, // Toggle individual UI components
watermark: {
img: 'https://example.com/logo.png',
url: 'https://example.com',
placement: 'top-left', // 'top-left', 'top-right', 'bottom-left', 'bottom-right'
timeout: 0 // Seconds to show watermark (0 = always)
}
}
},
plugins: {
// Plugin configs — see section 6.2 for details per plugin
}
});
| Config Section | Purpose |
|---|---|
targetId |
DOM element ID where the player renders. The element must exist before setup() is called. |
provider |
Kaltura account and authentication settings. partnerId and uiConfId are required. |
playback |
Playback behavior: autoplay, volume, looping, stream format priority. |
ui |
Player UI customization: disable controls, inject CSS, toggle components, add watermarks. |
plugins |
Plugin activation and configuration. Pass an empty object {} to enable with defaults, or provide config parameters. |
log |
Logging verbosity. Use DEBUG during development and ERROR in production. |
5.2 loadMedia() Options¶
The player.loadMedia() method accepts two arguments: a media info object and an optional options object:
player.loadMedia(
{ entryId: 'ENTRY_ID' }, // Required: entry to load
{
seekFrom: 30, // Start playback at 30 seconds (clipping start)
clipTo: 120, // End playback at 120 seconds (clipping end)
startTime: 30 // Alternative to seekFrom for setting start position
}
);
| Parameter | Type | Description |
|---|---|---|
entryId |
string | Kaltura entry ID to load |
seekFrom |
number | Clip start position in seconds |
clipTo |
number | Clip end position in seconds |
startTime |
number | Initial playback position in seconds |
6. JS Control (Play/Pause/Seek/Volume)¶
With dynamic JS embeds, the player instance exposes standard controls:
// Play / Pause
player.play();
player.pause();
// Seek (seconds)
player.currentTime = 90;
// Volume (0.0 – 1.0)
player.volume = 0.5;
These APIs are part of the web player’s base interface. Key properties and methods:
| API | Type | Description |
|---|---|---|
player.play() |
method | Start playback |
player.pause() |
method | Pause playback |
player.currentTime |
get/set | Current playback position in seconds |
player.duration |
get | Total media duration in seconds |
player.volume |
get/set | Volume level (0.0 – 1.0) |
player.muted |
get/set | Mute state (boolean) |
player.playbackRate |
get/set | Playback speed (1.0 = normal) |
player.isLive() |
method | Whether the current media is a live stream |
player.ready() |
method | Returns a Promise that resolves when the player is ready for interaction |
player.loadMedia({entryId}) |
method | Load a new media entry into the player |
6.1 Binding to JS player events (drive app flows)¶
The Kaltura player exposes a DOM-style event system and a Promise for readiness. Use it for analytics beacons, UI reactions, gated flows, etc.
Player core events consist of two event types:
- HTML5 Video Events — Standard events from the underlying
<video>element - Player Custom Events — Events specific to the Kaltura player that extend beyond standard HTML5 video
All core events are accessible via player.Event.Core as shown in the example below.
HTML5 Video Events¶
| Event | Constant | Callback Payload |
|---|---|---|
| Play | PLAY |
No payload. Fired when playback is requested (before media actually starts playing). |
| Pause | PAUSE |
No payload. Fired when playback is paused. |
| Ended | ENDED |
No payload. Fired when playback reaches the end of the media. |
| Seeking | SEEKING |
No payload. The player's currentTime property reflects the target seek position. |
| Seeked | SEEKED |
No payload. Fired when a seek operation completes. |
| Time Update | TIME_UPDATE |
No payload. Fired continuously during playback (typically every 250ms). Read player.currentTime and player.duration for position data. |
| Volume Change | VOLUME_CHANGE |
No payload. Read player.volume (0.0-1.0) for the new volume level. |
| Waiting | WAITING |
No payload. Fired when playback stalls due to buffering. |
| Playing | PLAYING |
No payload. Fired when playback resumes after buffering or pause. |
| Can Play | CANPLAY |
No payload. Fired when enough data is buffered to begin playback. |
| Loaded Metadata | LOADED_METADATA |
No payload. Fired when media metadata (duration, dimensions) is available. Read player.duration for the media length. |
| Loaded Data | LOADED_DATA |
No payload. Fired when the first frame of the media is loaded. |
| Duration Change | DURATION_CHANGE |
No payload. Fired when player.duration changes (e.g., live stream duration updates). |
| Rate Change | RATE_CHANGE |
No payload. Read player.playbackRate for the new rate value. |
| Error | ERROR |
event.payload — object with severity (number: 0=CRITICAL, 1=RECOVERABLE), category (number: 1=NETWORK, 2=TEXT, 3=MEDIA, 4=MANIFEST, 5=ENCRYPTION), code (number), and data (error details object). |
Player Custom Events¶
| Event | Constant | Callback Payload |
|---|---|---|
| Player State Changed | PLAYER_STATE_CHANGED |
event.payload.oldState — object with type (string: "idle", "loading", "playing", "paused", "buffering"). event.payload.newState — object with type (same values). |
| Media Loaded | MEDIA_LOADED |
No payload. Fired after loadMedia() resolves and media sources are set. |
| First Play | FIRST_PLAY |
No payload. Fired once per media load — the first time play is requested. |
| First Playing | FIRST_PLAYING |
No payload. Fired once per media load — the first time media actually renders a frame. |
| Tracks Changed | TRACKS_CHANGED |
event.payload.tracks — array of track objects, each with type (string: "video", "audio", "text"), label (string), language (string), active (boolean), and index (number). |
| Text Track Changed | TEXT_TRACK_CHANGED |
event.payload.selectedTextTrack — track object with language (string), label (string), kind (string: "subtitles", "captions"), active (boolean), and index (number). |
| Audio Track Changed | AUDIO_TRACK_CHANGED |
event.payload.selectedAudioTrack — track object with language (string), label (string), active (boolean), and index (number). |
| Video Track Changed | VIDEO_TRACK_CHANGED |
event.payload.selectedVideoTrack — track object with width (number), height (number), bitrate (number), active (boolean), and bandwidth (number). |
| Enter Fullscreen | ENTER_FULLSCREEN |
No payload. Fired when the player enters fullscreen mode. |
| Exit Fullscreen | EXIT_FULLSCREEN |
No payload. Fired when the player exits fullscreen mode. |
| Enter Picture-in-Picture | ENTER_PICTURE_IN_PICTURE |
No payload. Fired when the player enters PiP mode. |
| Exit Picture-in-Picture | EXIT_PICTURE_IN_PICTURE |
No payload. Fired when the player exits PiP mode. |
| Source Selected | SOURCE_SELECTED |
event.payload.selectedSource — array of source objects, each with mimetype (string), url (string), id (string), bandwidth (number), width (number), height (number). |
| Change Source Started | CHANGE_SOURCE_STARTED |
No payload. Fired when a new media source begins loading (e.g., after loadMedia()). |
| Change Source Ended | CHANGE_SOURCE_ENDED |
No payload. Fired when the new media source has been applied. |
| Autoplay Failed | AUTOPLAY_FAILED |
event.payload — object with error (string, browser's autoplay rejection reason). |
| Mute Change | MUTE_CHANGE |
event.payload.mute — boolean, the new mute state. |
| Playback Start | PLAYBACK_START |
No payload. Fired once per session when the first play begins (differs from FIRST_PLAY in that it fires after buffering completes). |
| Playback Ended | PLAYBACK_ENDED |
No payload. Fired when all media in the playlist or single entry finishes. |
| Ad Started | AD_STARTED |
event.payload.adType — string ("preroll", "midroll", "postroll"). event.payload.adPosition — number (ad index). |
| Ad Completed | AD_COMPLETED |
event.payload.adType — string. event.payload.adPosition — number. |
| Ad Skipped | AD_SKIPPED |
event.payload.adType — string. event.payload.adPosition — number. |
<script>
window.player = player;
function onPlay() { console.log('PLAY'); }
function onPause() { console.log('PAUSE'); }
function onEnded() { console.log('ENDED'); }
function onError(ev){ console.error('ERROR', ev && ev.payload); }
function onSeeking() { console.log('SEEKING...'); }
function onSeeked() { console.log('SEEKED'); }
function onTimeUpdate() { console.log("currentTime: ", player.currentTime); }
player.ready().then(() => {
console.log("player is ready!");
const E = player.Event.Core;
// bind to events:
player.addEventListener(E.PLAY, onPlay);
player.addEventListener(E.PAUSE, onPause);
player.addEventListener(E.ENDED, onEnded);
player.addEventListener(E.ERROR, onError);
player.addEventListener(E.TIME_UPDATE, onTimeUpdate);
player.addEventListener(E.SEEKING, onSeeking);
player.addEventListener(E.SEEKED, onSeeked);
});
window.dispose = function() {
console.log('disposing...');
const E = player.Event.Core;
window.player.removeEventListener(E.PLAY, onPlay);
window.player.removeEventListener(E.PAUSE, onPause);
window.player.removeEventListener(E.ENDED, onEnded);
window.player.removeEventListener(E.ERROR, onError);
window.player.removeEventListener(E.TIME_UPDATE, onTimeUpdate);
window.player.removeEventListener(E.SEEKING, onSeeking);
window.player.removeEventListener(E.SEEKED, onSeeked);
}
</script>
6.2 PlayKit Plugin Ecosystem¶
The Kaltura Player v7 (PlayKit) supports 30+ plugins that extend playback with interactive features. Plugins are configured via the plugins block in KalturaPlayer.setup():
const player = KalturaPlayer.setup({
targetId: 'kplayer',
provider: { partnerId: PARTNER_ID, uiConfId: UICONF_ID, ks: KS },
plugins: {
dualscreen: {}, // enable Dual Screen plugin
transcript: {}, // enable Transcript plugin
navigation: {} // enable Navigation plugin
}
});
Key plugins and their configuration parameters:
Dual Screen (dualscreen)¶
Multi-stream PIP / side-by-side layout switching for entries with a secondary stream (e.g., slides + presenter).
| Parameter | Type | Default | Description |
|---|---|---|---|
layout |
string | "pip" |
Initial layout: "pip" (picture-in-picture), "sbs" (side-by-side), "single" (primary only), "singleSecondary" (secondary only) |
mainViewEntryId |
string | (auto) | Entry ID for the main (primary) view |
secondaryViewEntryId |
string | (auto) | Entry ID for the secondary view |
pip.position |
string | "bottom-right" |
PiP window position: "top-left", "top-right", "bottom-left", "bottom-right" |
inverse |
boolean | false |
Swap primary and secondary media in the layout |
childSizeMultiplier |
number | 0.3 |
PiP window size as a fraction of the player (0.0 - 1.0) |
Navigation (navigation)¶
Chapter-based navigation with thumbnails from cue points defined on the entry.
| Parameter | Type | Default | Description |
|---|---|---|---|
position |
string | "right" |
Panel position: "right", "left", "top", "bottom" |
expandOnFirstPlay |
boolean | true |
Auto-expand the navigation panel on first play |
visible |
boolean | true |
Show the navigation panel |
itemsOrder.bySortOrder |
boolean | true |
Sort chapters by the cue point sortOrder field |
Transcript (transcript)¶
Searchable transcript overlay synced to playback, using caption assets on the entry.
| Parameter | Type | Default | Description |
|---|---|---|---|
position |
string | "right" |
Panel position: "right", "left", "top", "bottom" |
expandOnFirstPlay |
boolean | true |
Auto-expand the transcript panel on first play |
visible |
boolean | true |
Show the transcript panel |
showTime |
boolean | true |
Display timestamps next to each line |
scrollOffset |
number | 0 |
Pixels to offset auto-scroll from the top |
searchDebounceTimeout |
number | 250 |
Milliseconds to debounce search input |
searchNextPrevVisible |
boolean | true |
Show next/previous navigation in search results |
downloadDisabled |
boolean | false |
Hide the transcript download button |
plugins: {
transcript: {
position: 'right',
expandOnFirstPlay: true,
showTime: true,
downloadDisabled: false
}
}
Q&A (qna)¶
Live Q&A panel for virtual events, enabling audience questions and moderator responses.
| Parameter | Type | Default | Description |
|---|---|---|---|
position |
string | "right" |
Panel position: "right", "left" |
expandOnFirstPlay |
boolean | false |
Auto-expand the Q&A panel on first play |
visible |
boolean | true |
Show the Q&A panel |
dateFormat |
string | "mmmm do, yyyy" |
Date display format for Q&A entries |
bannerDuration |
number | 5000 |
Banner notification duration in milliseconds |
Hotspots (hotspots)¶
Clickable overlay hotspots on video, defined via cue points with custom data.
| Parameter | Type | Default | Description |
|---|---|---|---|
visible |
boolean | true |
Show hotspot overlays |
Hotspot content, position, and timing are defined by cue points on the entry (via the cuePoint API service), not by plugin config. The plugin reads these cue points and renders them at the specified times.
In-Video Quiz (IVQ) (ivq)¶
Interactive quizzes during playback, pausing the video to present questions at configured cue points.
| Parameter | Type | Default | Description |
|---|---|---|---|
visible |
boolean | true |
Show quiz overlays |
Quiz questions, answers, and timing are defined by cue points on the entry (created via the quiz plugin in KMC or through the API). The IVQ plugin renders them during playback.
SEO (seo)¶
Auto-generates JSON-LD structured data (VideoObject schema) for video entries to improve search engine discoverability.
| Parameter | Type | Default | Description |
|---|---|---|---|
includeDescription |
boolean | true |
Include the entry description in the JSON-LD output |
includeThumbnail |
boolean | true |
Include the thumbnail URL in the JSON-LD output |
includeUploadDate |
boolean | true |
Include the upload date in the JSON-LD output |
Downloads (downloads)¶
Adds a download button to the player UI that lists available flavor assets (transcoded versions) for download.
| Parameter | Type | Default | Description |
|---|---|---|---|
flavorParamIds |
string | "" |
Comma-separated flavor param IDs to offer for download. Empty string means all available flavors. |
presetName |
string | "" |
Name for the download preset group |
displayFlavors |
boolean | true |
Show individual flavor selection (resolution/bitrate) in the download menu |
displayCaptions |
boolean | true |
Show caption download options in the download menu |
displayAttachments |
boolean | true |
Show attachment download options in the download menu |
KAVA (kava)¶
Built-in analytics event reporting that sends playback metrics to the Kaltura Analytics system.
| Parameter | Type | Default | Description |
|---|---|---|---|
partnerId |
number | (from provider) | Override the partner ID for analytics reporting |
entryId |
string | (from media) | Override the entry ID for analytics reporting |
ks |
string | (from provider) | Override the KS for analytics reporting |
tamperAnalyticsHandler |
function | null |
Callback to modify analytics events before sending. Receives the event object and returns modified event or false to cancel. |
customVar1 |
string | "" |
Custom variable 1 (passed to analytics backend) |
customVar2 |
string | "" |
Custom variable 2 |
customVar3 |
string | "" |
Custom variable 3 |
Three shared infrastructure packages power the interactive plugins: kaltura-cuepoints (temporal markers), ui-managers (shared UI components), and timeline (timeline visualization). These are bundled automatically when the plugin is enabled.
Plugin availability depends on your player configuration (
uiConfId). Configure plugins in the KMC under Studio > TV Platform (select a player, then edit its plugins) or via thepluginsconfig block inKalturaPlayer.setup().
6.3 Player Runtime API¶
After the player is created with KalturaPlayer.setup(), you can control plugins and player behavior at runtime using the service and plugin APIs.
player.getService(name)¶
Retrieve a plugin service by name. Returns undefined if the plugin is not loaded for the current player configuration.
var svc = player.getService('dualScreen');
if (svc) {
svc.ready.then(function() {
console.log('Dual Screen service is ready');
});
} else {
console.log('Dual Screen plugin not available in this player config');
}
| Method | Returns | Description |
|---|---|---|
player.getService(name) |
service object or undefined |
Get a plugin's service interface. The name is the service registration name (e.g., 'dualScreen', 'sidePanels'). |
service.ready |
Promise | Resolves when the service has finished initializing (e.g., secondary media is loaded for dual screen). |
player.plugins.*¶
Access plugin instances directly to call runtime methods. Each plugin is accessible by its config key:
// Access the Dual Screen plugin instance
var ds = player.plugins.dualscreen;
// Switch layouts at runtime (after service is ready)
var svc = player.getService('dualScreen');
svc.ready.then(function() {
ds._switchToPIP({ force: true }, true); // Switch to PiP layout
ds._switchToSideBySide({ force: true }, true); // Switch to side-by-side
ds._switchToSingleMedia({ force: true }, true); // Switch to single view
ds._switchToInversePIP({ force: true }, true); // Switch to inverse PiP
});
player.configure()only sets the initial config. It does not trigger runtime changes for plugins like Dual Screen. To control plugins at runtime, use the plugin instance methods (e.g.,player.plugins.dualscreen._switchTo*()) after the servicereadypromise resolves.
player.configure(config)¶
Updates player configuration at runtime. Effective for playback and ui settings, but not for plugin runtime state changes (plugins read config only at setup time):
// These work at runtime:
player.configure({ playback: { volume: 0.5 } });
player.configure({ ui: { css: '.custom { color: red; }' } });
// This does NOT trigger a plugin layout change at runtime:
player.configure({ plugins: { dualscreen: { layout: 'sbs' } } });
// Instead, use: player.plugins.dualscreen._switchToSideBySide({ force: true }, true);
player.destroy()¶
Destroys the player instance, removing all event listeners, stopping playback, and cleaning up the DOM. Call this when removing the player from the page:
7. Server-Side KS for Player¶
Generate a scoped USER KS (type=0) for player embeds. Use specific privileges to control what the player can access:
curl -X POST "$KALTURA_SERVICE_URL/service/session/action/start" \
-d "format=1" \
-d "partnerId=$KALTURA_PARTNER_ID" \
-d "secret=$KALTURA_ADMIN_SECRET" \
-d "type=0" \
-d "userId=viewer@example.com" \
-d "expiry=3600" \
-d "privileges=sview:ENTRY_ID,appid:myapp-example.com,privacycontext:MY_PORTAL"
Recommended player KS privileges:
| Privilege | Purpose |
|---|---|
sview:ENTRY_ID |
Restrict playback to a specific entry (or sview:* for all accessible entries) |
appid:APP_NAME-APP_DOMAIN |
Analytics tracking — identifies which app/domain generated the playback |
privacycontext:CATEGORY_NAME |
Scope access to entries in a specific privacy-enabled category |
setrole:PLAYBACK_BASE_ROLE |
Restrict the KS to read-only playback operations |
enableentitlement |
Enforce category entitlement checks |
7.1 IP Tokenization for CDN-Protected Content¶
When CDN tokenization is enforced on your account, the player KS must include the viewer's IP address so the CDN can validate the request:
- Server looks up the viewer's IP from the HTTP request
- Generates a KS with
iprestrict:IPto bind the session to that IP - Configures the player to use HLS-only streaming (required for IP-tokenized delivery)
const player = KalturaPlayer.setup({
targetId: 'kplayer',
provider: {
partnerId: PARTNER_ID,
uiConfId: UICONF_ID,
ks: IP_RESTRICTED_KS // KS includes iprestrict:VIEWER_IP
},
playback: {
autoplay: true,
streamPriority: [
{ engine: 'html5', format: 'hls' } // Force HLS for CDN tokenization
]
}
});
IP tokenization requires account-level CDN configuration. Contact your Kaltura specialist for setup. See Session Guide section 8.5 for
iprestrictprivilege details.
8. Playback Progress Tracking (Quartile Events)¶
Track playback milestones (25%, 50%, 75%, 100%) using the TIME_UPDATE event:
player.ready().then(() => {
const milestones = { 25: false, 50: false, 75: false, 100: false };
player.addEventListener(player.Event.Core.TIME_UPDATE, () => {
const duration = player.duration;
if (!duration) return;
const pct = Math.floor((player.currentTime / duration) * 100);
for (const mark of [25, 50, 75, 100]) {
if (pct >= mark && !milestones[mark]) {
milestones[mark] = true;
console.log('Reached ' + mark + '% milestone');
// Send analytics beacon: fetch('/api/track', { method: 'POST', body: ... })
}
}
});
player.addEventListener(player.Event.Core.ENDED, () => {
if (!milestones[100]) {
milestones[100] = true;
console.log('Reached 100% milestone (ENDED)');
}
});
});
Use quartile tracking for custom engagement analytics, completion-gated content (e.g., unlock next module after 75%), or third-party analytics integration.
9. Error Handling¶
| Scenario | Detection | Resolution |
|---|---|---|
Invalid entryId |
Player shows "Media not found" error | Verify entry exists and has status=2 (READY) via baseEntry.get |
| Expired or invalid KS | Player shows access denied | Generate a fresh KS; for production, use AppToken session renewal |
| Player library not loaded | KalturaPlayer is not defined |
Check the script src URL — verify partnerId and uiConfId are correct |
| Plugin not available | player.getService('name') returns undefined |
The plugin may not be enabled for this player config — verify uiConfId |
| Autoplay blocked by browser | Video loads but does not play | Set playback.autoplay: true with muted: true — browsers require muted autoplay |
Retry strategy: For transient errors (expired KS, network failures), implement KS refresh logic and retry loadMedia. For client errors (invalid entryId, missing player library, wrong uiConfId), fix the configuration before retrying — these will not resolve on their own.
10. Best Practices¶
- Use USER KS (type=0) for player embeds. Scope to specific entries with
sview:entryIdwhen possible. - Set short KS expiry (1-4 hours). For long-running pages, implement KS refresh logic.
- Use iframe embed for simple integrations. It handles library loading and configuration automatically.
- Use JS embed for programmatic control. When you need play/pause/seek, event listeners, or plugin interaction.
- Load the player library once. Cache the
<script>tag and reuse it across videos. UseKalturaPlayer.setup()for each new player instance. - Use Access Control profiles on entries for content protection (geo, domain, IP restrictions) rather than implementing client-side checks.
- Debug with a generic event listener. During development, log all player events to understand the event flow:
11. Related Guides¶
- Session Guide — Generate KS for access-controlled player embeds
- AppTokens — Secure KS generation for production player integrations
- Content Delivery — playManifest URLs, delivery profiles, and CDN configuration for playback
- eSearch — Search for entries to embed in the player
- REACH — Add captions and translations that appear in the player
- Events Platform — Create events with live webcast sessions (played via embedded player)
- Multi-Stream — Dual Screen / multi-screen entries for PiP and Side-by-Side playback
- Access Control API — Access control profiles for restricting player playback (geo, domain, IP, scheduling)
- Categories & Entitlements API — Category entitlements affecting content visibility
- API Getting Started — Foundation guide covering content model and API patterns
- Captions & Transcripts — Caption assets displayed in the player transcript plugin
- Analytics Reports — Player events feed analytics reports
- Unisphere Framework — Unisphere plugins for player integration (unisphere-service, unisphere, unisphere-genie)
- Cue Points & Interactive Video — Chapters, slides, annotations, ads, quizzes, hotspots — data behind player timeline, navigation, and IVQ plugins
- Quiz API — Interactive video quiz lifecycle and IVQ player plugin