# Live

Live edge state for the player store

Tracks when playback is at the live edge and what kind of live window the stream provides.

- `liveEdgeStart` is the playback time where the live edge begins. Playback counts as live when `currentTime` reaches this value.
- `targetLiveWindow` describes the kind of live window. Despite its name, it does not report a number of seconds: `0` means a sliding live window, `Infinity` means a live event with playback history, and `NaN` means on-demand or not known yet.

Both values are `NaN` when the media does not provide live-edge information.

Use the [buffer feature](https://videojs.org/docs/framework/html/reference/api/feature-buffer) to find the times a viewer can seek to. Its `seekable` value contains `[start, end]` pairs. On a sliding live stream, the oldest and newest available times both move forward.

The live presets do not include the [stream type feature](https://videojs.org/docs/framework/html/reference/api/feature-stream-type), so `selectStreamType` returns `undefined` unless you add it to a custom player.

The [time feature](https://videojs.org/docs/framework/html/reference/api/feature-time) reports the end of the available live video as `duration`, even when the browser reports `Infinity`. To check for live playback, use `!Number.isNaN(targetLiveWindow)` instead of checking `duration`.

## Import

```ts
import { liveFeature } from '@videojs/html';
```

The `liveAudioFeatures` and `liveVideoFeatures` [feature bundles](https://videojs.org/docs/framework/html/guides/presets) include this feature.

## API Reference

### State

| Property | Type | Description |
| --- | --- | --- |
| `liveEdgeStart` | `number` | Playback time where the live edge begins. Playback is live when `currentTime >= liveEdgeStart`. `NaN` when the stream is not live or the value is unknown. |
| `targetLiveWindow` | `number` | Describes the kind of live window available. This value is not a duration. `0` for a sliding live window, `Infinity` for a live event with playback history, and `NaN` for on-demand or unknown. |

### Selector

Pass `selectLive` to [`PlayerController`](https://videojs.org/docs/framework/html/reference/api/player-controller) to subscribe to live state. Returns `undefined` if the live feature is not configured.

**live-edge-button.ts**

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

const { PlayerController } = createPlayer({ features: liveVideoFeatures });

class LiveEdgeButton extends UIElement {
  readonly #live = new PlayerController(this, selectLive);
}
```

## Jump to the live edge

Use the packaged live button for the usual jump-to-live behavior. It combines the live, time, and buffer features, then seeks to the end of the last `seekable` range. It also manages its accessible label and disabled state.

**index.html**

```html
<script type="module">
  import '@videojs/html/ui/live-button';
</script>

<media-live-button class="station-live-button">On air</media-live-button>
```

Put the button in your custom controls and style it there. Do not calculate the destination from `duration` or set `currentTime` to `Infinity`.

If you need different behavior, you can combine the same public features yourself:

- Read `targetLiveWindow` from `selectLive` to check that the source is live.
- Read the newest available time from the last range returned by `selectBuffer`.
- Call the `seek()` action returned by `selectTime` with that time.

Read the same three selectors with [`PlayerController`](https://videojs.org/docs/framework/html/reference/api/player-controller). Call `selectTime`’s `seek()` action with the last end time from `selectBuffer` when `selectLive` reports a live source.

---

HTML documentation: https://videojs.org/docs/framework/html/llms.txt
All documentation: https://videojs.org/llms.txt
