Live Video API
Preview
HLS · LL-HLS

Stream Playback

Deliver live and DVR playback to web and mobile. Use standard HLS for maximum compatibility, LL-HLS for lower latency, or drop in the Sendexa embed player. Protect premium content with signed playback URLs.

HLS everywhere

Works in Safari natively and via hls.js on Chrome, Firefox, and Edge.

Low-latency HLS

LL-HLS manifests when latencyMode is low — target 3–8s glass-to-glass.

Live DVR

Let viewers scrub back within the configured DVR window.

Signed playback

Optional JWT playback tokens for paid / private streams.

Standard HLS

8–15s

latencyMode: standard

LL-HLS

3–8s

latencyMode: low

ABR rungs

Auto

Built from ingest quality

DVR max

4h

dvrWindowSeconds ≤ 14400

Playback URLs

Returned under data.playback when you create or fetch a stream. Use llHls only when the stream was created with latencyMode: "low".

JSON
{
"playback": {
"hls": "https://live.sendexa.co/str_01JQX7K2M9N4P5/index.m3u8",
"llHls": "https://live.sendexa.co/str_01JQX7K2M9N4P5/ll/index.m3u8",
"embedUrl": "https://player.sendexa.co/live/str_01JQX7K2M9N4P5",
"poster": "https://cdn.sendexa.co/posters/str_01JQX7K2M9N4P5.jpg"
}
}
FieldUse for
hlsDefault multi-bitrate HLS — best compatibility
llHlsLow-latency HLS players (Safari 16+, hls.js LL mode)
embedUrlIframe embed of the Sendexa player (auth + UI included)
posterThumbnail before go-live or while reconnecting

Web playback with hls.js

HTML
<!-- npm i hls.js | or CDN -->
<video id="live" controls playsinline autoplay muted
class="w-full aspect-video bg-black rounded-xl"></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<script>
const src = 'https://live.sendexa.co/str_01JQX7K2M9N4P5/ll/index.m3u8';
const video = document.getElementById('live');
if (video.canPlayType('application/vnd.apple.mpegurl')) {
// Safari — native HLS / LL-HLS
video.src = src;
} else if (window.Hls && Hls.isSupported()) {
const hls = new Hls({
enableWorker: true,
lowLatencyMode: true, // for LL-HLS
backBufferLength: 90,
});
hls.loadSource(src);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, () => video.play());
} else {
console.error('HLS not supported in this browser');
}
</script>

React player example

TSX
'use client';
import { useEffect, useRef } from 'react';
import Hls from 'hls.js';
export function LivePlayer({
src,
lowLatency = true,
}: {
src: string;
lowLatency?: boolean;
}) {
const ref = useRef<HTMLVideoElement>(null);
useEffect(() => {
const video = ref.current;
if (!video || !src) return;
if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = src;
return;
}
if (Hls.isSupported()) {
const hls = new Hls({ lowLatencyMode: lowLatency });
hls.loadSource(src);
hls.attachMedia(video);
return () => hls.destroy();
}
}, [src, lowLatency]);
return (
<video
ref={ref}
controls
playsInline
autoPlay
muted
className="aspect-video w-full rounded-xl bg-black"
/>
);
}
// Usage:
// <LivePlayer src={stream.playback.llHls ?? stream.playback.hls} />

Embed player

Fastest path for dashboards and marketing pages — no player code required.

HTML
<iframe
src="https://player.sendexa.co/live/str_01JQX7K2M9N4P5?autoplay=1&muted=1"
allow="autoplay; fullscreen; picture-in-picture"
allowfullscreen
class="w-full aspect-video rounded-xl border-0"
></iframe>
FieldTypeRequiredDescription
autoplay0|1optionalStart playback when live (may require muted=1).
muted0|1optionalStart muted for browser autoplay policies.
dvr0|1optionalShow DVR scrubber when stream.dvr is enabled.
tokenstringoptionalPlayback JWT for private streams (see signed playback).

Mobile

Swift
import AVKit
let url = URL(string: "https://live.sendexa.co/str_01JQX7K2M9N4P5/index.m3u8")!
let player = AVPlayer(url: url)
let controller = AVPlayerViewController()
controller.player = player
present(controller, animated: true) {
player.play()
}

DVR (live rewind)

Enable dvr: true when creating the stream. Viewers can seek within dvrWindowSeconds. Most players expose this automatically on the live edge timeline.

JavaScript
// Create with 2-hour DVR
await fetch('https://api.sendexa.co/v1/video/streams', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic YOUR_DASHBOARD_BASE64_TOKEN',
},
body: JSON.stringify({
name: 'Town Hall',
dvr: true,
dvrWindowSeconds: 7200,
latencyMode: 'standard',
}),
});

Signed / private playback

For tickets or members-only streams, mint short-lived playback tokens from your backend. Pass them as a query param or Authorization header depending on player support.

POST
/v1/video/streams/:streamId/playback-tokens
Bash
curl -X POST 'https://api.sendexa.co/v1/video/streams/str_01JQX7K2M9N4P5/playback-tokens' \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN' \
-d '{
"ttl": 600,
"viewerId": "user_42",
"capabilities": ["live", "dvr"]
}'
JSON
{
"success": true,
"code": "PLAYBACK_TOKEN_ISSUED",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
"expiresAt": "2026-07-12T18:15:00.000Z",
"playbackUrl": "https://live.sendexa.co/str_01JQX7K2M9N4P5/index.m3u8?token=eyJ…"
}
}

VOD after the stream ends

With record: true, Sendexa archives the broadcast. When processing completes, you receive video.recording.ready (same family as room recordings) with a signed MP4 URL — see Webhooks.

Player UX tips

Autoplay policies
Start muted + playsInline; unmute on user gesture.
Offline / idle poster
Show playback.poster or your own branding while status is idle/starting.
Error recovery
On hls.js fatal network errors, destroy and recreate the Hls instance.
Analytics
Correlate player sessionId with streamId in your product analytics.

Related