# Play live streams

Play live streams with live-edge tracking, DVR windows, and stream-type detection.

> **Note**
>
> Using a pre-built [skin](./skins.md)? It already includes the controls shown here. You may still need the media or player setup in this guide. The component examples are for building your own player UI from individual [components](./ui-components.md).

## Installation

The examples use `<hlsjs-video>`, so install hls.js with the framework façade:

```bash
pnpm add @videojs/html @videojs/hlsjs-video
```

## Recommended approach

Use the live feature bundle with a streaming media element, and give users a `<media-live-button>`: it shows whether playback is at the live edge and seeks back to it when activated.

```html
<live-video-player>
  <media-container>
    <hlsjs-video src="https://your-stream.example.com/live.m3u8" autoplay muted playsinline></hlsjs-video>
    <media-live-button></media-live-button>
  </media-container>
</live-video-player>
<script type="module">
  import '@videojs/html/live-video/player';
  import '@videojs/html/media/hlsjs-video';
  import '@videojs/html/live-video/ui';
</script>
```

The examples use [`<hlsjs-video>`](../reference/components/hlsjs-video.md) for broad compatibility, but any streaming media component works here, including the smaller [`<hls-video>`](../reference/components/hls-video.md). Use `<hls-video>` when its supported feature set fits your stream.

The `liveVideoFeatures` bundle mirrors [`videoFeatures`](./features.md) but adds the live feature and drops playback rate (not meaningful for live), quality selection, and audio-track selection. The live presets also ship skins without a time slider, duration display, or current-time display.

Both bundles are plain arrays, so extending one is a spread:

```ts
import { createPlayer, streamTypeFeature } from '@videojs/html';
import { liveVideoFeatures } from '@videojs/html/live-video';

const { ProviderMixin } = createPlayer({ features: [...liveVideoFeatures, streamTypeFeature] });
```

## How it works

Two features describe liveness:

- The [stream type feature](../reference/api/feature-stream-type.md) reports `streamType`: `'live'`, `'on-demand'`, or `'unknown'`. Streaming media derives it from manifest metadata; plain media elements fall back to duration-based detection. `liveVideoFeatures` does not include it; add `streamTypeFeature` to the player’s features when you need `streamType`.
- The [live feature](../reference/api/feature-live.md) reports two values:
  - `liveEdgeStart` is where “live” begins on the timeline. When the playhead is at or past this time, the viewer is watching live; behind it, they’re watching earlier moments of the stream.
  - `targetLiveWindow` is how far back the stream lets viewers rewind. `0` means a plain live stream that stays at the edge. `Infinity` means full DVR: rewind as far as the recording goes. `NaN` means the stream isn’t live, or the player doesn’t know yet.

The [time feature](../reference/api/feature-time.md) adjusts for live playback: `duration` reports the live edge (the end of the seekable range) and keeps growing as the stream continues.

`<media-live-button>` reads this state: it renders as an active “go to live” control while playback is behind the edge, seeks to the edge on activation, and goes inactive at the edge. Until the media reports a `seekable` range — before metadata loads, or for non-live media — the button is disabled (`data-disabled`) because there is no edge to seek to. Custom live UIs should treat “behind the edge” and “actionable” as separate states.

## Availability and constraints

- `liveEdgeStart` and `targetLiveWindow` come from media that implements the live capability — the hls.js-based media elements. With plain media elements, stream type falls back to duration-based detection and `liveEdgeStart` stays `NaN`.
- Live playback drifts behind the edge when the network stalls or the tab is backgrounded. Always give users a path back to the edge.
- Seeking makes sense only for DVR streams (`targetLiveWindow` of `Infinity`). For standard-latency streams, omit the time slider.
- Playback rate control isn’t meaningful for live; `liveVideoFeatures` omits it.

## Common variations

### DVR: let users scrub back

For streams with a DVR window, give users a [`<media-time-slider>`](../reference/components/time-slider.md). The live preset skins don’t include one, so add it to your custom UI or [add the live skin source to your project](./customize-skins.md#style-skin-source). The slider tracks the sliding window automatically because `duration` follows the live edge.

### Switch UI by stream type

Render live or on-demand controls from `streamType` when one player handles both kinds of content. Add `streamTypeFeature` to the player’s features; `liveVideoFeatures` does not include it:

`<media-live-button>` selects from the live, time, and buffer features and reflects live state. To swap larger parts of the UI on `streamType`, build a provider with [createPlayer](../reference/api/html-create-player.md) and add `streamTypeFeature` to its features (`<live-video-player>` uses `liveVideoFeatures`, which does not include it), then read `streamType` from the player store through the [player controller](../reference/api/player-controller.md).

## Troubleshooting

### The live badge never activates

`streamType` isn’t `'live'`. Confirm the player’s features include `streamTypeFeature` (`liveVideoFeatures` does not include it, so `streamType` reads as `undefined`), the source is a live manifest, and it plays through a live-capable media element such as [`<hlsjs-video>`](../reference/components/hlsjs-video.md).

### Playback keeps falling behind the edge

Network throughput can’t sustain the stream, or the tab was backgrounded. `<media-live-button>` returns users to the edge; for lower drift, review the stream’s latency configuration on the encoder side.

### The time slider behaves oddly on a live stream

Standard-latency live streams have no meaningful seek range. Show the slider only for DVR streams (`targetLiveWindow` of `Infinity`).

## Related pages

### Components

- [media-time-slider](../reference/components/time-slider.md): A slider component for seeking through media playback time
- [media-buffering-indicator](../reference/components/buffering-indicator.md): Loading indicator that displays when the video player is buffering or waiting for data

### API

- [Live](../reference/api/feature-live.md): Live edge state for the player store
- [Stream type](../reference/api/feature-stream-type.md): Stream delivery type (live / on-demand) state for the player store
- [Time](../reference/api/feature-time.md): Playback position and duration state for the player store
- [hlsjs-video](../reference/components/hlsjs-video.md): HLS video element powered by hls.js for adaptive bitrate streaming

### Guides

- [Media sources](./media-sources.md): Set what a media element plays and how its engine plays it with the structured source property