docs(site): add "Why Video.js?" concept page (#1526)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Darius Cepulis
2026-05-13 11:30:06 -07:00
committed by GitHub
co-authored by Claude
parent e73f87d392
commit ad515d3a24
7 changed files with 164 additions and 2 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

@@ -11,6 +11,8 @@ import Aside from '@/components/Aside.astro';
Video.js v10 is built around a three-part architecture that separates concerns and maximizes flexibility. Each part is designed to work independently or together, allowing you to use as much or as little of Video.js as you need.
For the reasoning behind this design, see <DocsLink slug="concepts/why-videojs">Why Video.js?</DocsLink>.
## 1. State management
<FrameworkCase frameworks={["react"]}>
State is handled by a `Player.Provider`, which creates a central state store that all components can access. When you wrap your player in a `Player.Provider`, the components automatically connect to the state.
@@ -0,0 +1,159 @@
---
title: 'Why Video.js?'
description: 'The open-source video player for React and HTML. Lightweight, accessible components built for performance and streaming.'
---
import FrameworkCase from '@/components/docs/FrameworkCase.astro';
import DocsLink from '@/components/docs/DocsLink.astro';
import DocsLinkCard from '@/components/docs/DocsLinkCard.astro';
import ContentWidth from '@/components/frames/ContentWidth.astro';
import { TabsRoot, TabsList, TabsPanel, Tab } from '@/components/Tabs.tsx';
import chromeDefaultControls from '@/assets/docs/concepts/why-videojs/chrome-default-controls.png';
import safariDefaultControls from '@/assets/docs/concepts/why-videojs/safari-default-controls.png';
import firefoxDefaultControls from '@/assets/docs/concepts/why-videojs/firefox-default-controls.png';
Video.js is the open-source video player for the web. It makes web video easy, performant, accessible, and customizable.
Let's dig into when you'd want to use Video.js, starting with the the question we hear most...
## Why not `<video>`?
The native `<video>` tag is great if you can describe your video as an image with a play button. Past that, the gaps show up quickly.
### Cross-browser inconsistency
Chrome, Safari, and Firefox each render the default `<video>` controls differently. You can hide them, but you can't deeply style or rearrange them. Building UI that matches your product means starting from scratch.
<ContentWidth margins="lg" class="grid grid-cols-3 gap-4">
<figure>
<img
src={chromeDefaultControls.src}
width={chromeDefaultControls.width}
height={chromeDefaultControls.height}
alt="Chrome's default video controls"
class="w-full h-auto"
/>
<figcaption class="mt-2 text-center">Chrome</figcaption>
</figure>
<figure>
<img
src={safariDefaultControls.src}
width={safariDefaultControls.width}
height={safariDefaultControls.height}
alt="Safari's default video controls"
class="w-full h-auto"
/>
<figcaption class="mt-2 text-center">Safari</figcaption>
</figure>
<figure>
<img
src={firefoxDefaultControls.src}
width={firefoxDefaultControls.width}
height={firefoxDefaultControls.height}
alt="Firefox's default video controls"
class="w-full h-auto"
/>
<figcaption class="mt-2 text-center">Firefox</figcaption>
</figure>
</ContentWidth>
### Video interactions
Video often involves a lot more than an MP4 in `src`. Rich playback features (like thumbnail previews, adaptive bitrate, quality selection, chapters, audio track switching, control localization, error UI, live-streaming UI, analytics, ads, 360 video, Chromecast, AirPlay, DRM, and more) are _possible_ with the video element but require complex wiring and deep consideration for maintainabilty and <DocsLink slug="concepts/accessibility">accessibility</DocsLink>.
Video.js aims to handle this all out of the box. (Though some features are still under development. Stay tuned!)
### Streaming formats and sources
Behind features like adaptive bitrate and quality selection are video formats like HLS or DASH -- videos broken into segments that can be selected according to bandwidth and preferences. Not every browser supports HLS, and DASH support is even more limited. Video.js closes the gap so the same `src` works everywhere.
Of course, your video might not be coming from a `src` like that. It might be provided by a service. However, services like YouTube, Vimeo, and Mux each speak their own API. Switching from a self-hosted file to a hosted service shouldn't mean switching players. Video.js abstracts the source so you can change where the video comes from without rewriting the surrounding code.
Video.js even considers sources like canvas-based MoQ or animated GIFs, all with the same components.
## Why Video.js?
Video.js is built at Mux by the teams behind Video.js, Plyr, Vidstack, and Media Chrome, with contributions from engineers across other player projects. Between us, our projects have served tens of billions of monthly video plays. Most of the choices on this page came from things we got wrong the first time, then the second, then the fifth. We've been supporting your edge cases for over a decade. Now we're shipping the player we always wanted to build.
Let's dig into some of the design principles that help explain why we built Video.js and why it may be the best choice for your project or team.
### Add only what you need
Most player libraries ship every feature in one bundle, so you carry code you don't run. If your video doesn't need a feature like DRM, why ship that code? Video.js turns features into independent, _composable_ modules. You hand `createPlayer` the array you actually want, and what you don't import doesn't ship.
<FrameworkCase frameworks={["react"]}>
```tsx
import { createPlayer, playback, time } from '@videojs/react';
const Player = createPlayer({
features: [playback, time], // [!code focus]
});
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```ts
import { createPlayer, playback, time } from '@videojs/html';
const { ProviderMixin, PlayerController, context } = createPlayer({
features: [playback, time], // [!code focus]
});
```
</FrameworkCase>
<DocsLinkCard slug="concepts/features">Learn more about features</DocsLinkCard>
Of course, you don't have to think about every feature you're going to need if you don't want to. Pre-built feature bundles are still there if you'd rather not assemble the list by hand.
<DocsLinkCard slug="concepts/presets">Learn more about presets</DocsLinkCard>
### Framework-native
Many player libraries wrap a single web component for every framework. That works, until you reach the seams: refs you can't pass through, state that doesn't reconcile, prop names that aren't quite React or HTML. Video.js ships idiomatic APIs in each framework: React components and hooks for React, custom elements and controllers for HTML. (And we plan on supporting more frameworks in the futrue!)
The player feels like the rest of your app.
<TabsRoot client:idle>
<TabsList client:idle label="Framework-native APIs">
<Tab client:idle value="react" initial>React</Tab>
<Tab client:idle value="html">HTML</Tab>
</TabsList>
<TabsPanel client:idle value="react" initial>
```tsx
import { Player, Video, VideoSkin } from '@videojs/react/video';
function MyPlayer() {
return (
<Player.Provider>
<VideoSkin>
<Video src="movie.mp4" />
</VideoSkin>
</Player.Provider>
);
}
```
</TabsPanel>
<TabsPanel client:idle value="html">
```html
<script type="module" src="@videojs/html/video/player"></script>
<video-player>
<video-skin>
<video src="movie.mp4"></video>
</video-skin>
</video-player>
```
</TabsPanel>
</TabsRoot>
### Eject and own
Most player libraries draw a line between "configurable through props" and "fork the source." Cross the line and you're on your own. Video.js lets you eject any skin and walk away with the source: components in your framework's language that you can read and change. The skin you ship is yours; the rest of the player keeps working underneath it.
<DocsLinkCard slug="how-to/customize-skins">Customize skins</DocsLinkCard>
### AI-native DX
Documentation aimed at human readers usually doesn't help an agent. Video.js publishes an `llms.txt` index, ships every docs page as both HTML and Markdown, and has a dedicated guide for building with AI assistants. Drop the player into a Claude or Cursor session and the docs come along for the ride.
<DocsLinkCard slug="how-to/build-with-ai">Build with AI</DocsLinkCard>
@@ -25,10 +25,10 @@ Video.js v10 is currently in _beta_. The API may evolve with [feedback&#x1F64F;]
</Aside>
<FrameworkCase frameworks={["react"]}>
Video.js is a **React video player component library** &mdash; composable primitives, hooks, and TypeScript types for building accessible, customizable players with minimal bundle size.
Video.js is a **React video player component library**: composable primitives, hooks, and TypeScript types for building accessible, customizable players with minimal bundle sizes, advanced features, and consistency across browsers.
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
Video.js is an **HTML video player built on custom elements** &mdash; lightweight, framework-free components for building accessible, customizable players with minimal bundle size.
Video.js is an **HTML video player built on custom elements**: lightweight, framework-free components for building accessible, customizable players with minimal bundle sizes, advanced features, and consistency across browsers.
</FrameworkCase>
<LLMCase>
+1
View File
@@ -23,6 +23,7 @@ export const sidebar: Sidebar = [
llmsDescription: 'Installation, project setup, and introductory guides.',
contents: [
{ slug: 'how-to/installation' },
{ slug: 'concepts/why-videojs' },
{ slug: 'concepts/overview' },
{ slug: 'how-to/build-with-ai' },
{ slug: 'concepts/v10-roadmap', sidebarLabel: 'Roadmap' },