Skip to main content
Video.js v10 supports a range of media sources through swappable media elements. Switching from a plain <video> to HLS or DASH is a one-line change — your skin and features stay the same.

Plain video and audio

import { createPlayer } from '@videojs/react';
import { videoFeatures, VideoSkin, Video } from '@videojs/react/video';
import '@videojs/react/video/skin.css';

const Player = createPlayer({ features: videoFeatures });

function App() {
  return (
    <Player.Provider>
      <VideoSkin>
        <Video src="https://example.com/movie.mp4" />
      </VideoSkin>
    </Player.Provider>
  );
}

HLS

The HLS media element wraps hls.js and is included in @videojs/core as a dependency. Pass an .m3u8 URL directly as src:
import { HlsVideo } from '@videojs/react/media/hls-video';
import { VideoSkin } from '@videojs/react/video';
import { Player } from './player';

function App() {
  return (
    <Player.Provider>
      <VideoSkin>
        <HlsVideo src="https://example.com/stream.m3u8" />
      </VideoSkin>
    </Player.Provider>
  );
}

DASH

The DASH media element wraps dash.js and is also bundled in @videojs/core. Pass an .mpd URL as src:
import { DashVideo } from '@videojs/react/media/dash-video';
import { VideoSkin } from '@videojs/react/video';
import { Player } from './player';

function App() {
  return (
    <Player.Provider>
      <VideoSkin>
        <DashVideo src="https://example.com/manifest.mpd" />
      </VideoSkin>
    </Player.Provider>
  );
}

Background video

The /background preset bakes in autoplay, muted, and loop on the media element — ideal for hero sections and decorative video:
import { createPlayer } from '@videojs/react';
import {
  backgroundFeatures,
  BackgroundVideo,
  BackgroundVideoSkin,
} from '@videojs/react/background';
import '@videojs/react/background/skin.css';

const Player = createPlayer({ features: backgroundFeatures });

function Hero() {
  return (
    <Player.Provider>
      <BackgroundVideoSkin>
        <BackgroundVideo src="hero.mp4" />
      </BackgroundVideoSkin>
    </Player.Provider>
  );
}

Swapping sources dynamically

Media components accept a src prop that you can update at any time. The player reacts to src changes automatically:
import { useState } from 'react';
import { Video, VideoSkin } from '@videojs/react/video';
import { Player } from './player';

const SOURCES = [
  'https://example.com/clip1.mp4',
  'https://example.com/clip2.mp4',
];

function Playlist() {
  const [index, setIndex] = useState(0);

  return (
    <Player.Provider>
      <VideoSkin>
        <Video src={SOURCES[index]} />
      </VideoSkin>
      <button onClick={() => setIndex((i) => (i + 1) % SOURCES.length)}>
        Next
      </button>
    </Player.Provider>
  );
}

Error handling

When media fails to load, the player exposes error state. The built-in skins render a dismissable error dialog automatically. To handle errors in custom skins:
import { AlertDialog } from '@videojs/react';
import { Player } from './player';

function ErrorDialog() {
  return (
    <AlertDialog
      aria-labelledby="error-title"
      render={(props, { onDismiss }) => (
        <div {...props} className="error-overlay">
          <p id="error-title">Something went wrong.</p>
          <button onClick={onDismiss}>Dismiss</button>
        </div>
      )}
    />
  );
}

Media element reference

Component (React)Element (HTML)Source format
Video<video>MP4, WebM, and other browser-native formats
Audio<audio>MP3, AAC, Ogg, and other browser-native formats
HlsVideo<hls-video>HLS (.m3u8) via hls.js
DashVideo<dash-video>MPEG-DASH (.mpd) via dash.js
BackgroundVideo<background-video>MP4 (autoplay, muted, loop)

Next steps

Custom features

Control which features and state the player tracks.

Custom skins

Build a skin that matches your design.

Build docs developers (and LLMs) love