mirror of
https://github.com/zoriya/v10.git
synced 2026-08-13 01:19:44 +00:00
7.1 KiB
7.1 KiB
HTML API
HTML-specific concerns: element naming, imports, skins.
Element Naming
| Layer | Pattern | Examples |
|---|---|---|
| Player | <{mediatype}-player> |
<video-player>, <audio-player> |
| Skin | <{mediatype}-skin> |
<video-skin>, <minimal-video-skin> |
| Media | <{source}-{mediatype}> |
<hls-video>, <dash-video>, <hls-audio> |
| UI | <media-{component}> |
<media-play-button>, <media-slider> |
Special Players
Only fundamentally different behaviors get their own player:
<background-video-player> <!-- no controls, autoplay, loop -->
Import Paths
Player (includes base features)
import '@videojs/html/player/video'; // includes features.video
import '@videojs/html/player/audio'; // includes features.audio
import '@videojs/html/player/background-video';
Features (additive)
import '@videojs/html/feature/streaming';
import '@videojs/html/feature/ads';
import '@videojs/html/feature/live';
import '@videojs/html/feature/chapters';
// Granular
import '@videojs/html/feature/quality-selection';
import '@videojs/html/feature/audio-tracks';
import '@videojs/html/feature/text-tracks';
Media
import '@videojs/html/media/hls-video';
import '@videojs/html/media/hls-audio';
import '@videojs/html/media/dash-video';
Skins
// Default skin
import '@videojs/html/skin/video.css';
import '@videojs/html/skin/video';
// Named variants
import '@videojs/html/skin/video/minimal.css';
import '@videojs/html/skin/video/minimal';
import '@videojs/html/skin/audio.css';
import '@videojs/html/skin/audio';
UI Primitives (for custom skins)
import '@videojs/html/ui/menu';
import '@videojs/html/ui/radio-group';
import '@videojs/html/ui/slider';
Registration Models
Side-Effect Imports (Declarative)
Elements register globally when imported:
import '@videojs/html/player/video';
import '@videojs/html/skin/video';
<video-player>
<video-skin>
<video src="video.mp4">
</video-skin>
</video-player>
createPlayer (Escape Hatch)
For custom element names or full control:
import { createPlayer, features } from '@videojs/html';
const { PlayerElement, PlayerController } = createPlayer({
features: [features.video, myCustomFeature]
});
customElements.define('my-video-player', PlayerElement);
<my-video-player>
<video src="video.mp4">
</my-video-player>
Split Provider/Container (Advanced)
When media element and container need different DOM locations:
import { createPlayer, features } from '@videojs/html';
const { ProviderElement, ContainerElement } = createPlayer({
features: [features.video]
});
customElements.define('my-video-provider', ProviderElement);
customElements.define('my-video-container', ContainerElement);
<my-video-provider>
<video src="video.mp4">
<my-video-container>
<!-- Controls here, separate from media -->
</my-video-container>
</my-video-provider>
Skins
Adaptive Skins
Default skin adapts to available features:
import '@videojs/html/player/video';
import '@videojs/html/feature/streaming'; // skin will show quality menu
import '@videojs/html/skin/video';
<video-skin> <!-- adapts to used features -->
Named Skins
Specific UI compositions and style variants:
<video-skin> <!-- default style -->
<minimal-video-skin> <!-- stripped down -->
<cinematic-video-skin> <!-- dark/immersive -->
Skin Customization
Default skin handles optional feature UI via lazy loading.
Ejected skin structure:
skin/
video/
video-skin.ts
video-skin.css
features.ts
features.ts:
import { features } from '@videojs/html';
// Lazy-define element for a feature
// Shell element registers immediately, loads implementation when feature available
features.lazy(
'qualitySelection',
() => import('./ui/quality-menu')
);
MediaElement Base Class
Base class for UI primitives. The host element IS the control (e.g., <media-play-button> extends button behavior).
// src/ui/media-play-button.ts
import { MediaElement, PlayerController, features } from '@videojs/html';
export class MediaPlayButton extends MediaElement {
#playback = new PlayerController(this, features.playback);
override connectedCallback() {
super.connectedCallback();
this.addEventListener('click', this.#handleClick);
}
#handleClick = () => {
this.#playback.value?.toggle();
};
override update() {
const playback = this.#playback.value;
if (!playback) return;
this.setAttribute('aria-pressed', String(!playback.paused));
}
}
// define/ui/media-play-button.ts (side-effect import)
import { MediaPlayButton } from '../src/ui/media-play-button.js';
customElements.define('media-play-button', MediaPlayButton);
Usage:
import '@videojs/html/ui/media-play-button';
PlayerController
Reactive controller for accessing player state. Triggers update() when subscribed feature changes.
import { PlayerController, features, MediaElement } from '@videojs/html';
export class MediaVolumeSlider extends MediaElement {
#volume = new PlayerController(this, features.volume);
override connectedCallback() {
super.connectedCallback();
this.addEventListener('input', this.#handleInput);
}
#handleInput = (e: Event) => {
this.#volume.value?.setVolume(parseFloat((e.target as HTMLInputElement).value));
};
override update() {
const volume = this.#volume.value;
if (!volume) return;
// Host is the slider — update its value
(this as unknown as HTMLInputElement).value = String(volume.volume);
}
}
Controller API
| Property | Returns | Description |
|---|---|---|
value |
Slice | undefined |
Feature slice, triggers update on change |
Mixins
For advanced customization when you need to extend behavior.
ProviderMixin
import { createPlayer, features, MediaElement } from '@videojs/html';
const { ProviderMixin } = createPlayer({
features: [features.video]
});
class MyProvider extends ProviderMixin(MediaElement) {
// Custom provider logic
}
ContainerMixin
const { ContainerMixin } = createPlayer({
features: [features.video]
});
class MyContainer extends ContainerMixin(MediaElement) {
// Custom container logic
}
Full Example
// main.ts
import '@videojs/html/player/video';
import '@videojs/html/feature/streaming';
import '@videojs/html/media/hls-video';
import '@videojs/html/skin/video.css';
import '@videojs/html/skin/video';
<!DOCTYPE html>
<html>
<head>
<script type="module" src="main.ts"></script>
</head>
<body>
<video-player>
<video-skin>
<hls-video src="https://example.com/stream.m3u8"></hls-video>
</video-skin>
</video-player>
</body>
</html>