Video Player
Headless video player: the shared MediaPlayer controls under VideoPlayer* names plus the native <video> part, fullscreen, and picture-in-picture. Shared types and helpers are exported from @vizejs/ui/media-player.
|
|
| Package |
@vizejs/ui/video-player |
| Maturity |
stable |
| Own the source |
vize lib pull video-player |
| Requires |
context, media-player |
| Aliases |
video player, video, video controls, picture in picture, fullscreen video |
| Covers |
HTML video, Fullscreen API, Picture-in-Picture API, Vidstack Player, Media Chrome |
Usage
import { VideoPlayerCaptionsButton, VideoPlayerLoadingIndicator, VideoPlayerMuteButton, VideoPlayerPlayButton, VideoPlayerPlaybackRateButton, VideoPlayer, VideoPlayerRoot, VideoPlayerSeekSlider, VideoPlayerTimeDisplay, VideoPlayerVolumeSlider, VideoPlayerFullscreenButton, VideoPlayerPictureInPictureButton, VideoPlayerVideo } from "@vizejs/ui/video-player";
Or copy the source into your project with vize lib pull video-player (see Source Distribution).
API
Source: src/families/media/media-player/media-player-captions-button.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string | null |
undefined |
Accessible name override. undefined uses the state-dependent label from the root messages; null omits aria-label so visible slot text names the button. |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before the action. Call preventDefault() to skip it. |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Button content, e.g. an icon. Receives the playback state. |
Exposed
| Member |
Type |
Description |
disabled |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
VideoPlayerLoadingIndicator
Source: src/families/media/media-player/media-player-loading-indicator.vue
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Indicator content, rendered only while loading. Defaults to messages.loading. |
Source: src/families/media/media-player/media-player-mute-button.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string | null |
undefined |
Accessible name override. undefined uses the state-dependent label from the root messages; null omits aria-label so visible slot text names the button. |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before the action. Call preventDefault() to skip it. |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Button content, e.g. an icon. Receives the playback state. |
Exposed
| Member |
Type |
Description |
disabled |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
Source: src/families/media/media-player/media-player-play-button.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string | null |
undefined |
Accessible name override. undefined uses the state-dependent label from the root messages; null omits aria-label so visible slot text names the button. |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before the action. Call preventDefault() to skip it. |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Button content, e.g. an icon. Receives the playback state. |
Exposed
| Member |
Type |
Description |
disabled |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
Source: src/families/media/media-player/media-player-playback-rate-button.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string | null |
undefined |
Accessible name override. undefined uses the state-dependent label from the root messages; null omits aria-label so visible slot text names the button. |
rates |
readonly number[] |
[0.5, 1, 1.25, 1.5, 2] |
Rates cycled on click, in order. The next rate after the current one is chosen; an unknown current rate selects the first. |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before the action. Call preventDefault() to skip it. |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Button content, e.g. an icon. Receives the playback state. |
Exposed
| Member |
Type |
Description |
disabled |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
VideoPlayer
Source: src/families/media/media-player/media-player-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned base id. null and undefined select a deterministic fallback. |
volume |
number |
undefined |
Controlled volume from 0 to 1 (v-model:volume). |
defaultVolume |
number |
1 |
Initial volume for uncontrolled use. |
muted |
boolean |
undefined |
Controlled muted state (v-model:muted). |
defaultMuted |
boolean |
false |
Initial muted state for uncontrolled use. Rendered as the native muted attribute, so muted autoplay works before hydration. |
playbackRate |
number |
undefined |
Controlled playback rate (v-model:playbackRate). |
defaultPlaybackRate |
number |
1 |
Initial playback rate for uncontrolled use. |
currentTime |
number |
undefined |
Synchronized playback position (v-model:currentTime). The media element stays the source of truth: timeupdate emits the position, and a parent value more than half a second away from it seeks. |
keyboardShortcuts |
boolean |
true |
Handle media keyboard shortcuts while focus is inside the player. |
seekStep |
number |
5 |
Seconds moved by arrow keys on the seek slider and root shortcuts. |
skipStep |
number |
10 |
Seconds skipped by the J and L shortcuts. |
volumeStep |
number |
0.05 |
Volume change for arrow keys, from 0 to 1. |
messages |
MediaPlayerMessages |
undefined |
Localized accessible labels for every control part. Missing keys use English defaults. |
dir |
"ltr" | "rtl" |
"ltr" |
Reading direction used by horizontal sliders and arrow keys. |
ariaLabel |
string |
undefined |
Accessible player name; adds role="group". |
ariaLabelledby |
string |
undefined |
Ids that name the player; adds role="group". |
Events
| Event |
Payload |
Description |
update:volume |
[volume: number] |
Fired when the volume requests a new controlled value. |
update:muted |
[muted: boolean] |
Fired when the muted state requests a new controlled value. |
update:playbackRate |
[rate: number] |
Fired when the playback rate requests a new controlled value. |
update:currentTime |
[time: number] |
Fired on every native timeupdate and seek with the current position. |
play |
[] |
Fired after playback starts. |
pause |
[] |
Fired after playback pauses. |
ended |
[] |
Fired after playback reaches the end. |
playRejected |
[reason: unknown] |
Fired when play() is rejected, e.g. by an autoplay policy. |
error |
[code: number | null] |
Fired when the media element reports an error (MediaError.code). |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Media element and controls. Receives the complete playback state. |
Exposed
| Member |
Type |
Description |
buffered |
— |
|
captionTrack |
— |
|
currentTime |
— |
|
duration |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
error |
— |
|
fullscreen |
— |
|
loading |
— |
|
media |
— |
|
muted |
— |
|
pause |
— |
|
paused |
— |
|
pictureInPicture |
— |
|
play |
— |
|
playbackRate |
— |
|
seek |
— |
|
seekBy |
— |
|
seeking |
— |
|
setCaptionTrack |
— |
|
setMuted |
— |
|
setPlaybackRate |
— |
|
setVolume |
— |
|
state |
— |
|
textTracks |
— |
|
toggleCaptions |
— |
|
toggleFullscreen |
— |
|
togglePictureInPicture |
— |
|
togglePlay |
— |
|
volume |
— |
|
VideoPlayerRoot
Source: src/families/media/media-player/media-player-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned base id. null and undefined select a deterministic fallback. |
volume |
number |
undefined |
Controlled volume from 0 to 1 (v-model:volume). |
defaultVolume |
number |
1 |
Initial volume for uncontrolled use. |
muted |
boolean |
undefined |
Controlled muted state (v-model:muted). |
defaultMuted |
boolean |
false |
Initial muted state for uncontrolled use. Rendered as the native muted attribute, so muted autoplay works before hydration. |
playbackRate |
number |
undefined |
Controlled playback rate (v-model:playbackRate). |
defaultPlaybackRate |
number |
1 |
Initial playback rate for uncontrolled use. |
currentTime |
number |
undefined |
Synchronized playback position (v-model:currentTime). The media element stays the source of truth: timeupdate emits the position, and a parent value more than half a second away from it seeks. |
keyboardShortcuts |
boolean |
true |
Handle media keyboard shortcuts while focus is inside the player. |
seekStep |
number |
5 |
Seconds moved by arrow keys on the seek slider and root shortcuts. |
skipStep |
number |
10 |
Seconds skipped by the J and L shortcuts. |
volumeStep |
number |
0.05 |
Volume change for arrow keys, from 0 to 1. |
messages |
MediaPlayerMessages |
undefined |
Localized accessible labels for every control part. Missing keys use English defaults. |
dir |
"ltr" | "rtl" |
"ltr" |
Reading direction used by horizontal sliders and arrow keys. |
ariaLabel |
string |
undefined |
Accessible player name; adds role="group". |
ariaLabelledby |
string |
undefined |
Ids that name the player; adds role="group". |
Events
| Event |
Payload |
Description |
update:volume |
[volume: number] |
Fired when the volume requests a new controlled value. |
update:muted |
[muted: boolean] |
Fired when the muted state requests a new controlled value. |
update:playbackRate |
[rate: number] |
Fired when the playback rate requests a new controlled value. |
update:currentTime |
[time: number] |
Fired on every native timeupdate and seek with the current position. |
play |
[] |
Fired after playback starts. |
pause |
[] |
Fired after playback pauses. |
ended |
[] |
Fired after playback reaches the end. |
playRejected |
[reason: unknown] |
Fired when play() is rejected, e.g. by an autoplay policy. |
error |
[code: number | null] |
Fired when the media element reports an error (MediaError.code). |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Media element and controls. Receives the complete playback state. |
Exposed
| Member |
Type |
Description |
buffered |
— |
|
captionTrack |
— |
|
currentTime |
— |
|
duration |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
error |
— |
|
fullscreen |
— |
|
loading |
— |
|
media |
— |
|
muted |
— |
|
pause |
— |
|
paused |
— |
|
pictureInPicture |
— |
|
play |
— |
|
playbackRate |
— |
|
seek |
— |
|
seekBy |
— |
|
seeking |
— |
|
setCaptionTrack |
— |
|
setMuted |
— |
|
setPlaybackRate |
— |
|
setVolume |
— |
|
state |
— |
|
textTracks |
— |
|
toggleCaptions |
— |
|
toggleFullscreen |
— |
|
togglePictureInPicture |
— |
|
togglePlay |
— |
|
volume |
— |
|
VideoPlayerSeekSlider
Source: src/families/media/media-player/media-player-seek-slider.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string |
undefined |
Accessible name. Defaults to the root messages.seek. |
ariaLabelledby |
string |
undefined |
Ids that name the slider instead of aria-label. |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Thumb content. Receives the playback state. |
Exposed
| Member |
Type |
Description |
dragging |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
focus |
— |
|
thumb |
— |
|
VideoPlayerTimeDisplay
Source: src/families/media/media-player/media-player-time-display.vue
Props
| Prop |
Type |
Default |
Description |
mode |
MediaPlayerTimeDisplayMode |
"current" |
Which time to show: the position, the duration, or the time remaining (rendered with a leading minus sign). |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState & { readonly text: string; readonly seconds: number } |
Custom rendering. Receives the formatted text, raw seconds, and playback state. |
VideoPlayerVolumeSlider
Source: src/families/media/media-player/media-player-volume-slider.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string |
undefined |
Accessible name. Defaults to the root messages.volume. |
ariaLabelledby |
string |
undefined |
Ids that name the slider instead of aria-label. |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Thumb content. Receives the playback state. |
Exposed
| Member |
Type |
Description |
dragging |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
focus |
— |
|
thumb |
— |
|
Source: src/families/media/video-player/video-player-fullscreen-button.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string | null |
undefined |
Accessible name override. undefined uses the state-dependent label from the root messages; null omits aria-label so visible slot text names the button. |
unsupported |
VideoPlayerUnsupportedBehavior |
"disable" |
Behavior when the platform lacks support, detected after mount (the server always renders the unsupported state): disable the button or hide it. |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before the request. Call preventDefault() to skip it. |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Button content, e.g. an icon. Receives the playback state. |
Exposed
| Member |
Type |
Description |
disabled |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
Source: src/families/media/video-player/video-player-picture-in-picture-button.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string | null |
undefined |
Accessible name override. undefined uses the state-dependent label from the root messages; null omits aria-label so visible slot text names the button. |
unsupported |
VideoPlayerUnsupportedBehavior |
"disable" |
Behavior when the platform lacks support, detected after mount (the server always renders the unsupported state): disable the button or hide it. |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before the request. Call preventDefault() to skip it. |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
Button content, e.g. an icon. Receives the playback state. |
Exposed
| Member |
Type |
Description |
disabled |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
VideoPlayerVideo
Source: src/families/media/video-player/video-player-video.vue
Props
| Prop |
Type |
Default |
Description |
src |
string |
undefined |
Video source, validated by the shared media-source policy. Unsafe sources are dropped (data-invalid-src); use <source> children for format fallbacks. |
poster |
string |
undefined |
Poster image, validated as an image source. |
preload |
MediaPlayerPreload |
"metadata" |
Native preload hint. |
playsinline |
boolean |
true |
Play inline on iOS instead of entering native fullscreen. |
autoplay |
boolean |
false |
Native autoplay. Browsers usually require the root defaultMuted as well. |
loop |
boolean |
false |
Restart at the end. |
controls |
boolean |
false |
Also render the browser's native controls. |
crossOrigin |
MediaPlayerCrossOrigin |
undefined |
Native CORS policy, required for cross-origin captions. |
disablePictureInPicture |
boolean |
false |
Hide the browser picture-in-picture affordance and disable the PiP button. |
width |
number | string |
undefined |
Intrinsic width used to reserve layout space. |
height |
number | string |
undefined |
Intrinsic height used to reserve layout space. |
allowInsecure |
boolean |
false |
Permit unencrypted http: sources for local development. |
Slots
| Slot |
Slot props |
Description |
default |
MediaPlayerSlotState |
<source> and <track> children, plus fallback content. |
Exposed
| Member |
Type |
Description |
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
Behavior
Normative state x input -> outcome table for video-player-video.vue,
video-player-fullscreen-button.vue, and video-player-picture-in-picture-button.vue
(@vizejs/ui/video-player). The shared controls re-exported as VideoPlayer*
follow media-player.behavior.md. Every row is proven by the named test.
| ID |
State |
Input |
Outcome |
Evidence |
| VP1 |
render |
props |
native <video> with validated src/poster, playsinline, preload, CORS, size, slot <track>s; unsafe sources are dropped |
renders a native video with validated sources and inline-playback attributes |
| VP2 |
defaultMuted |
autoplay |
the element renders and stays muted so muted autoplay is allowed |
defaultMuted mutes the element for muted autoplay |
| VP3 |
fullscreen supported |
button / F key |
the root container enters and leaves fullscreen; state, data-fullscreen, and labels follow fullscreenchange |
fullscreen toggles the root through the standard API and reports state |
| VP4 |
prefixed platforms |
toggle |
falls back to webkitRequestFullscreen, then native iOS video fullscreen with webkitbeginfullscreen/webkitendfullscreen |
fullscreen falls back to WebKit prefixes and native video fullscreen |
| VP5 |
PiP supported |
button |
enters and leaves picture-in-picture, tracking enterpictureinpicture/leavepictureinpicture; disablePictureInPicture opts out |
picture-in-picture is detected after mount and toggles the video |
| VP6 |
unsupported |
render |
platform buttons are disabled, or hidden with unsupported="hide", and report data-supported="false" |
unsupported platform controls are disabled or hidden |
| VP7 |
any |
click with preventDefault() |
the request is skipped; ariaLabel overrides the default label |
platform buttons honor preventDefault and aria-label overrides |
| VP8 |
aliases |
import / setup |
VideoPlayer aliases the shared root; video parts require the provider |
VideoPlayer aliases the shared root and requires a provider for its parts |
| VP9 |
SSR |
isolated requests |
markup is byte-identical and platform buttons render the unsupported state until mount |
renders byte-identical video player markup with unsupported platform controls |
| VP10 |
SSR / hydration |
hydrate |
server markup hydrates without warnings or node replacement |
hydrates video player markup without warnings or node replacement |
| VP11 |
types |
compile |
the root is the shared MediaPlayer root and unsupported behavior is a closed union |
video-player.types.test-d.ts |
Platform capabilities are detected after mount. WebKit-prefixed APIs are reached
through in checks and Reflect, never through casts.