React

<HlsPlayer>

Dedicated HLS adaptive bitrate player component for React.

<HlsPlayer>

<HlsPlayer> is the dedicated player for HLS adaptive bitrate streams (.m3u8 manifests). When you know your source is HLS, using <HlsPlayer> directly instead of <Player> gives you a smaller bundle — the YouTube and MP4 engines are entirely absent.

import { HlsPlayer } from "@playerkit/react";

<HlsPlayer src="https://example.com/stream.m3u8" />

Basic Usage

import { HlsPlayer } from "@playerkit/react";

function VideoPlayer() {
  return (
    <HlsPlayer
      src="https://example.com/live/stream.m3u8"
      autoPlay
      muted
      poster="https://example.com/thumbnail.jpg"
      style={{ width: "100%", aspectRatio: "16/9" }}
    />
  );
}

Props

<HlsPlayer> extends all BasePlayerProps with HLS-specific additions.

Base Props

PropTypeDefaultDescription
srcstringrequiredHLS manifest URL (.m3u8)
autoPlaybooleanfalseStart playing immediately
mutedbooleanfalseStart muted
controlsbooleantrueShow the built-in control bar
posterstringPoster/thumbnail before playback
startTimenumber0Seek to this time (seconds) on load
keyboardbooleantrueEnable keyboard shortcuts
seekStepnumber10Seconds per arrow key press / double-tap
playbackRatesnumber[][0.25, 0.5, 0.75, 1, 1.25, 1.5, 2]Speed menu options
themePlayerThemeName"default"Preset theme
themeOverridesThemeVarsCSS variable overrides
customizationPlayerCustomizationShow/hide individual controls
objectFit"contain" | "cover" | "fill""contain"CSS object-fit for the video element
onObjectFitChange(fit: PlayerObjectFit) => voidCallback when user clicks video fit toggle
classNamestringCSS class for the outer container
videoClassNamestringCSS class for the <video> element
styleCSSPropertiesInline styles for the outer container
logLevelLogLevel"none"Logger verbosity
debugTouchZonesbooleanfalseShow mobile touch zone overlays
disableDevOptionsbooleanfalseEnterprise security shield
onPlayerReady(player: PlayerControls) => voidCalled when player initializes

HLS-Specific Props

PropTypeDefaultDescription
tokenFetcherTokenFetcherAsync function that returns the authenticated stream URL
tokenRefresherTokenRefresherBackground polling function for token renewal
liveLiveConfigLive stream configuration
rootHTMLElement | nullElement to use as the fullscreen root
renderControls(props: HlsPlayerRenderControlsProps) => ReactNodeReplace the entire control bar
centerZoneX{ start: number; end: number }{ start: 0.4, end: 0.6 }Horizontal tap-to-play zone
centerZoneY{ start: number; end: number }{ start: 0.4, end: 0.6 }Vertical tap-to-play zone

LiveConfig Options

The live prop configures HLS live stream behavior:

type LiveConfig = {
  /** Sync the playhead within N seconds of the live edge. Default: 3 */
  syncDuration?: number;
  /** Enable HLS low-latency mode. Default: false */
  lowLatency?: boolean;
  /** Explicitly enable DVR (seek-back in live stream). Default: auto-detected */
  dvr?: boolean;
};

Token Authentication

For protected HLS streams requiring an auth token:

import { HlsPlayer } from "@playerkit/react";
import type { TokenFetcher, TokenRefresher } from "@playerkit/react";

const videoId = "my-video-id";

const tokenFetcher: TokenFetcher = async ({ signal }) => {
  const res = await fetch(`https://api.example.com/videos/${videoId}/token`, {
    signal,
  });
  const { url, expiresAt } = await res.json();
  return { url, expiresAt }; // expiresAt triggers automatic refresh
};

const tokenRefresher: TokenRefresher = async ({ signal }) => {
  const res = await fetch(`https://api.example.com/videos/${videoId}/refresh`, {
    signal,
  });
  const { url, expiresAt } = await res.json();
  return { url, expiresAt };
};

function SecurePlayer() {
  return (
    <HlsPlayer
      src="placeholder" // tokenFetcher overrides this
      tokenFetcher={tokenFetcher}
      tokenRefresher={tokenRefresher}
    />
  );
}

See the Token Auth guide for a full walkthrough.


Live Streams

<HlsPlayer
  src="https://example.com/live/stream.m3u8"
  live={{
    syncDuration: 5,    // Stay within 5s of live edge
    lowLatency: true,   // Enable HLS low-latency mode
    dvr: true,          // Allow seeking back in the DVR window
  }}
/>

See the Live Streams guide for details on DVR, latency tuning, and the live edge indicator.


Custom Controls

Replace the entire control bar with your own render function:

<HlsPlayer
  src="https://example.com/stream.m3u8"
  renderControls={({ player, state, seekRelative, formatTime }) => (
    <div className="my-controls">
      <button onClick={() => player?.togglePlay()}>
        {state?.isPlaying ? "⏸" : "▶"}
      </button>
      <span>{formatTime(state?.currentTime ?? 0)}</span>
      <input
        type="range"
        min={0}
        max={state?.duration ?? 0}
        value={state?.currentTime ?? 0}
        onChange={(e) => player?.seek(Number(e.target.value))}
      />
      <span>{formatTime(state?.duration ?? 0)}</span>
    </div>
  )}
/>

The renderControls callback receives:

PropTypeDescription
playerPlayerControls | nullFull player API
statePlayerSnapshot | nullCurrent playback state
progressnumberCurrent time as a percentage (0–1)
bufferednumberBuffered time as a percentage (0–1)
seekRelative(direction: -1 | 1) => voidSeek backward/forward by seekStep
formatTime(seconds: number) => stringFormat seconds as HH:MM:SS

Also Accepts Native Video Attributes

<HlsPlayer> passes all native <video> HTML attributes through to the underlying element (minus autoPlay, controls, src, className, style — those are handled by PlayerKit):

<HlsPlayer
  src="https://example.com/stream.m3u8"
  crossOrigin="anonymous"
  playsInline
  loop={false}
  onLoadedMetadata={(e) => console.log("Metadata loaded", e)}
/>

On this page