Live

A live pill, a jump back to the edge, and a timeline when the stream keeps a window to scrub through.

import { live } from "react-video-kit/live";

Adds 609 B to a player1.6 KB on its ownSource

Adds a LIVE pill to the control bar. Press play below. This stream keeps about 20 seconds, so there's no timeline, only the pill.

0:00−0:000:00

Usage

live() doesn't play anything itself, so it goes with hls or dash:

tsx
import { hls } from "react-video-kit/hls";import { live } from "react-video-kit/live";import { defaultPlugins, VideoPlayer } from "react-video-kit/player";const plugins = [hls(), live(), ...defaultPlugins()];<VideoPlayer src="/stream.m3u8" plugins={plugins} />;

It's safe to keep for on-demand video, where it shows nothing.

edgeTolerance sets how many seconds behind the edge still counts as live. It defaults to 6:

tsx
live({ edgeTolerance: 10 });

Plain live and DVR

A stream that keeps at least 60 seconds counts as DVR, and the viewer can scrub back through what it keeps. Anything shorter isn't worth a scrubber, so it's plain live. This stream keeps about 100 seconds. Click back along the timeline, then press the pill to return.

0:00−0:000:00
ControlPlain liveDVR
WindowUnder 60 seconds60 seconds or more
TimelineHiddenShown, and it follows the edge
Speed menuHiddenShown
Elapsed timeHiddenHidden
media.timeline.kind"live""dvr"
media.capabilities.seek and ratefalsetrue
Attributes on the rootdata-livedata-live, data-dvr

The window comes from hls.js's playlist duration, dash.js's DVR window, or the element's seekable range under native HLS.

What the viewer sees

  • The pill reads LIVE, with a coloured dot (--rv-live) while playback is running and within edgeTolerance of the edge.
  • When the viewer pauses or falls further behind, the dot and the text dim, and the pill's accessible name changes to "Go to live".
  • Pressing the pill jumps to the edge, and plays if paused.

Build your own control

useCommands gives you goLive, and useVideoState tells you when it's worth offering:

tsx
"use client";import { useCommands, useVideoState } from "react-video-kit";import { live } from "react-video-kit/live";function BackToLive() {  const behind = useVideoState(live, (state) => state.active && !state.atEdge);  const { goLive } = useCommands(live);  return behind ? <button onClick={() => goLive()}>Back to live</button> : null;}

LiveIndicator is the pill. When you compose your own layout, place it anywhere inside the player:

tsx
import * as Video from "react-video-kit";import { LiveIndicator } from "react-video-kit/live";<Video.ControlRow>  <LiveIndicator /></Video.ControlRow>;

Behaviour

  • hls.js and dash.js report live state on their own. Without live(), the stream still plays and the root still gets data-live, but there's no pill, no goLive, and no data-dvr, so the default skin hides the timeline even on a DVR stream.
  • Under native HLS, live() is what recognises the stream: it reads the window from the element.
  • goLive seeks to media.live.edge. For hls.js that's its liveSyncPosition when it has one, and otherwise the end of the playlist.
  • data-live-edge on the root only looks at position, while the pill's data-edge also needs playback to be running.
  • On plain live, capabilities.seek and capabilities.rate are false, so the seek and speed keys in the hotkeys plugin and the double tap in the gestures plugin and the system's seek buttons in the Media Session plugin do nothing. seek and setRate still work from your own code, which is how goLive reaches the edge.
  • media.live holds dvr, start, edge, and latency, for anything you want to build around them. latency is 0 under native HLS.

API

Options

OptionTypeDescription
edgeTolerance?numberHow many seconds behind the edge still counts as live.

State

Read it with useVideoState(live, (state) => …).

FieldTypeDescription
activebooleanTrue while the current source is live.
dvrbooleanTrue when the viewer can seek back through a window of the stream.
atEdgebooleanTrue within edgeTolerance seconds of the live edge, and when the source isn't live.

Commands

Call them with useCommands(live).

CommandTypeDescription
goLive() => voidJumps to the live edge, and plays if paused.

Parts

PartDescription
LiveIndicatorSays when playback is live, and returns there when it isn't. Hidden otherwise.