Skip to main content

Livepeer delivers content over HLS (3-8 second latency) and WebRTC (sub-second latency). The @livepeer/react Player selects the best protocol automatically. For custom players, construct URLs directly from the playbackId.

@livepeer/react Player

Install:
npm install @livepeer/react
import * as Player from '@livepeer/react/player';

export const VideoPlayer = ({ playbackId }: { playbackId: string }) => (
  <Player.Root src={`https://livepeercdn.studio/hls/${playbackId}/index.m3u8`}>
    <Player.Container>
      <Player.Video />
      <Player.Controls />
    </Player.Container>
  </Player.Root>
);
For JWT-gated content, pass the signed token:
<Player.Root
  src={`https://livepeercdn.studio/hls/${playbackId}/index.m3u8`}
  jwt={jwtToken}
>
  <Player.Container>
    <Player.Video />
  </Player.Container>
</Player.Root>
The Player sends the JWT as the Livepeer-Jwt header for WebRTC and HLS, and as the jwt query parameter for MP4 playback.

Direct playback URLs

Construct playback URLs using the playbackId returned when you create a stream or asset:

HLS.js integration

npm install hls.js
import Hls from 'hls.js';

const videoElement = document.querySelector('video');
const src = `https://livepeercdn.studio/hls/${playbackId}/index.m3u8`;

if (Hls.isSupported()) {
  const hls = new Hls({
    // For JWT-gated content
    xhrSetup: (xhr) => {
      xhr.setRequestHeader('Livepeer-Jwt', jwtToken);
    },
  });
  hls.loadSource(src);
  hls.attachMedia(videoElement);
} else if (videoElement.canPlayType('application/vnd.apple.mpegurl')) {
  // Native HLS (Safari, iOS)
  videoElement.src = `${src}?jwt=${jwtToken}`;
}

Confirming asset readiness

VOD assets are not playable until transcoding is complete. Subscribe to the asset.ready webhook, or poll the asset status:
const asset = await client.asset.get(assetId);

if (asset.asset.status.phase === 'ready') {
  const playbackUrl = `https://livepeercdn.studio/asset/hls/${asset.asset.playbackId}/index.m3u8`;
  // render player
} else if (asset.asset.status.phase === 'failed') {
  console.error('Transcoding failed:', asset.asset.status.error);
}

Create a Livestream

Get a playback ID from a new stream.

Access Control

Sign JWTs for gated content playback.
Last modified on April 7, 2026