Skip to main content
Features are self-contained units of player functionality. Each one adds state properties and actions to the player. You choose exactly which features your player includes — nothing more, nothing less.

Feature bundles

A feature bundle is an array of features grouped for a specific use case. The preset bundles are the starting point for most players:
import { videoFeatures } from '@videojs/react/video';
import { audioFeatures } from '@videojs/react/audio';
import { backgroundFeatures } from '@videojs/react/background';

Build a player with individual features

When you need precise control over what the player includes, pass an array of individual features directly to createPlayer():
import { createPlayer, playback, volume, time } from '@videojs/react';

const Player = createPlayer({
  features: [playback, volume, time],
});

Extend a preset’s feature bundle

Feature bundles are plain arrays, so you can spread them and append additional features:
import { createPlayer, playback } from '@videojs/react';
import { backgroundFeatures, BackgroundVideo, BackgroundVideoSkin } from '@videojs/react/background';

// Add play/pause to a background video
const Player = createPlayer({
  features: [...backgroundFeatures, playback],
});

function Hero() {
  return (
    <Player.Provider>
      <Player.Container>
        <BackgroundVideo src="hero.mp4" />
        <PlayButton
          render={(props, state) => (
            <button {...props}>{state.paused ? 'Play' : 'Pause'}</button>
          )}
        />
      </Player.Container>
    </Player.Provider>
  );
}

Check feature availability

Some features — volume, fullscreen, and picture-in-picture — expose an *Availability property because platform support varies. For example, iOS Safari does not allow programmatic volume control.
ValueMeaning
'available'Ready to use
'unavailable'Could work but not ready yet
'unsupported'Platform can never support this
import { Player } from './player';

function PiPControl() {
  const availability = Player.usePlayer((s) => s.pipAvailability);

  if (availability === 'unsupported') return null;

  return (
    <PiPButton
      render={(props) => <button {...props}>PiP</button>}
    />
  );
}

Feature-scoped selectors

Each feature exports a pre-built selector that returns just that feature’s state and actions. Use these to avoid subscribing to more state than you need.
import { selectPlayback, selectVolume } from '@videojs/react';
import { Player } from './player';

function VolumeControl() {
  const volume = Player.usePlayer(selectVolume);
  return (
    <button onClick={() => volume?.toggleMuted()}>
      {volume?.muted ? 'Unmute' : 'Mute'}
    </button>
  );
}

Custom state selectors

Use createSelector() from @videojs/react (or @videojs/store) to build your own memoized selectors:
import { createSelector, usePlayer } from '@videojs/react';
import { Player } from './player';

// Derived selector: combine two pieces of state
const selectPlaybackSummary = createSelector(
  (s) => s.paused,
  (s) => s.currentTime,
  (paused, currentTime) => ({ paused, currentTime })
);

function PlaybackSummary() {
  const summary = Player.usePlayer(selectPlaybackSummary);
  return (
    <span>
      {summary.paused ? 'Paused' : 'Playing'} at {summary.currentTime.toFixed(1)}s
    </span>
  );
}

Next steps

Custom skins

Build or eject a skin to match your design.

Media sources

Swap in HLS, DASH, and other media providers.

Build docs developers (and LLMs) love