Demos
How to import
<script setup lang="ts">
import { VideoPlayer } from '@fibrous/semi-ui-vue';
</script>
Basic Usage
For basic usage, pass the video address through src and pass the video cover address through poster

Code
<script setup lang="ts">
import { VideoPlayer } from '@fibrous/semi-ui-vue';
const src = '/assets/video/vchart-show-video.mp4';
const poster = '/assets/poster2.jpeg';
</script>
<template>
<VideoPlayer :height="630" :poster="poster" :src="src" />
</template>Set controls list
Set the display items of the menu bar through controlsList. The accepted value is an array. The default value is ['play', 'next', 'time', 'volume', 'playbackRate', 'quality', 'route', 'mirror', 'fullscreen', 'pictureInPicture']
A control shows when controlsList allows it and the prop it depends on is provided: next needs onNext, quality needs a non-empty qualityList, and route needs a non-empty routeList; the other controls depend only on controlsList.
onNext is a function prop; write @next or :onNext in the template. Whether it is passed decides whether the Next button shows.

Code
<script setup lang="ts">
import { VideoPlayer } from '@fibrous/semi-ui-vue';
const src = '/assets/video/vchart-show-video.mp4';
const poster = '/assets/poster2.jpeg';
</script>
<template>
<VideoPlayer :controlsList="['play', 'time', 'volume', 'playbackRate', 'fullscreen']" :height="630" :poster="poster" :src="src" />
</template>Loop playback
Use loop to set loop playback

Code
<script setup lang="ts">
import { VideoPlayer } from '@fibrous/semi-ui-vue';
const src = '/assets/video/vchart-show-video.mp4';
const poster = '/assets/poster2.jpeg';
</script>
<template>
<VideoPlayer :height="630" loop :poster="poster" :src="src" />
</template>Fast forward and rewind
Use seekTime to set the fast forward and rewind time, and use the left and right keys on the keyboard to fast forward and rewind.

Code
<script setup lang="ts">
import { ref } from 'vue';
import { Select, VideoPlayer } from '@fibrous/semi-ui-vue';
const seekTime = ref<number | undefined>(5);
const src = '/assets/video/vchart-show-video.mp4';
const poster = '/assets/poster2.jpeg';
const optionList = [
{ label: '5s', value: 5 },
{ label: '10s', value: 10 },
{ label: '15s', value: 15 },
];
</script>
<template>
<div>
<div>
<span :style="{ marginBottom: '10px' }">请选择快进快退时间</span>
<Select v-model="seekTime" aria-label="请选择快进快退时间" :optionList="optionList" placeholder="请选择快进快退时间" :style="{ width: '100px', marginLeft: '10px' }" />
</div>
<VideoPlayer :height="630" :poster="poster" :seekTime="seekTime" :src="src" :style="{ marginTop: '10px' }" />
</div>
</template>Playback rate
Set the rate selection list through playbackRateList. The rate, quality and route controls are native buttons that open their menu when focused with Tab; see "Keyboard and focus" for the keys. Each button is named by what it sets followed by the current option (such as "Playback speed 1.0x"), and its menu items are radio items

Code
<script setup lang="ts">
import { VideoPlayer } from '@fibrous/semi-ui-vue';
const playbackRateList = [
{ label: '0.5x', value: 0.5 },
{ label: '1.0x', value: 1 },
{ label: '1.5x', value: 1.5 },
{ label: '2.0x', value: 2 },
];
const src = '/assets/video/vchart-show-video.mp4';
const poster = '/assets/poster2.jpeg';
</script>
<template>
<VideoPlayer :height="630" :playbackRateList="playbackRateList" :poster="poster" :src="src" />
</template>Volume setting
Use volume to set the initial volume, the value range is 0 - 100, set muted to true to play silently. The volumeChange event is emitted when the user adjusts the volume

Code
<script setup lang="ts">
import { VideoPlayer } from '@fibrous/semi-ui-vue';
const src = '/assets/video/vchart-show-video.mp4';
const poster = '/assets/poster2.jpeg';
</script>
<template>
<VideoPlayer :height="630" muted :poster="poster" :src="src" />
</template>Clarity switching
Use qualityList to set the clarity selection list, defaultQuality to set the initial selected clarity, and update src in the qualityChange event.
Similarly for route switching, use routeList to set the route selection list, defaultRoute to set the initial selected route, and update src in the routeChange event.

Code
<script setup lang="ts">
import { ref } from 'vue';
import { VideoPlayer } from '@fibrous/semi-ui-vue';
const playList = [
{
src: '/assets/video/vchart-show-video.mp4',
quality: '1080p',
},
{
src: '/assets/video/vchart-show-video.mp4',
quality: '480p',
},
];
const poster = '/assets/poster2.jpeg';
const qualityList = [
{ label: '1080p', value: '1080p' },
{ label: '480p', value: '480p' },
];
const src = ref(playList[0].src);
function onQualityChange(quality: string) {
console.log('quality change', quality);
const source = playList.find((item) => item.quality === quality);
if (source) src.value = source.src;
}
</script>
<template>
<VideoPlayer defaultQuality="1080p" :height="630" :poster="poster" :qualityList="qualityList" :src="src" @qualityChange="onQualityChange" />
</template>Chapter markers
Set chapter markers via markers

Code
<script setup lang="ts">
import { VideoPlayer } from '@fibrous/semi-ui-vue';
const src = '/assets/video/vchart-show-video.mp4';
const poster = '/assets/poster2.jpeg';
const markers = [
{ start: 0, title: '片头' },
{ start: 4, title: '功能介绍' },
{ start: 38, title: 'Figma Plugin' },
{ start: 51, title: '片尾' },
];
</script>
<template>
<VideoPlayer :height="630" :markers="markers" :poster="poster" :src="src" />
</template>Theme
Set the theme via theme, the theme only affects the background color

Code
<script setup lang="ts">
import { VideoPlayer } from '@fibrous/semi-ui-vue';
const src = '/assets/video/vchart-show-video.mp4';
const poster = '/assets/poster2.jpeg';
</script>
<template>
<VideoPlayer :height="630" :poster="poster" :src="src" theme="light" />
</template>Using ref for control
Get the component instance through a template ref (useTemplateRef); its video property is the native video element, for more flexible control such as synchronized playback/pause of multiple videos. It is null before mount


Code
<script setup lang="ts">
import { useTemplateRef } from 'vue';
import { Button, VideoPlayer } from '@fibrous/semi-ui-vue';
const src = '/assets/video/vchart-show-video.mp4';
const poster = '/assets/poster2.jpeg';
const player1 = useTemplateRef('player1');
const player2 = useTemplateRef('player2');
function handlePlayAll() {
void player1.value?.video?.play();
void player2.value?.video?.play();
}
function handlePauseAll() {
player1.value?.video?.pause();
player2.value?.video?.pause();
}
</script>
<template>
<div>
<div :style="{ marginBottom: '12px' }">
<Button :style="{ marginRight: '8px' }" @click="handlePlayAll">同时播放</Button>
<Button @click="handlePauseAll">同时暂停</Button>
</div>
<div :style="{ display: 'flex', gap: '12px' }">
<VideoPlayer ref="player1" :height="315" :poster="poster" :src="src" width="50%" />
<VideoPlayer ref="player2" :height="315" :poster="poster" :src="src" width="50%" />
</div>
</div>
</template>Keyboard and focus
- While focus is inside the player, Space toggles play and pause, except on a button or an input control, which keeps the key; the left and right arrow keys rewind and fast forward by
seekTime, except inside an input control, the progress bar or a menu, which keep the keys. Combinations with Alt, Ctrl or Meta are ignored. - The progress bar is a slider (
role="slider"): the arrow keys move it byseekTime, PageUp and PageDown by a tenth of the duration, and Home and End jump to either end. Screen readers announce "current time / total time". - The playback rate, quality and route buttons open their menu when focused with Tab; the down and up arrow keys move focus to the first and last item. In the menu, the up and down arrow keys, Home and End move focus, Enter or Space selects, and Esc closes the menu and returns to the button.
- The volume popover opens when the volume button receives focus, and Enter or Space toggles mute; the down arrow key moves focus into the popover, where the volume slider takes the arrow keys.
- When the pointer leaves the player during playback, the control bar stays visible while it holds keyboard focus.
API
Props
| Property | Description | Type | Default |
|---|---|---|---|
| autoPlay | Whether to play automatically. | boolean | semiDefault("VideoPlayer", "autoPlay", false) |
| captionsSrc | Captions source URL; the captions are shown by default once set. | string | semiGlobalDefault("VideoPlayer", "captionsSrc") |
| clickToPlay | Whether clicking the video toggles playback. | boolean | semiDefault("VideoPlayer", "clickToPlay", true) |
| controlsList | Controls shown in the control bar, all by default. A control also needs the prop it depends on to show. | VideoControl[] | TypesemiDefault("VideoPlayer", "controlsList", [strings.PLAY, strings.NEXT, strings.TIME, strings.VOLUME, strings.PLAYBACK_RATE, strings.QUALITY, strings.ROUTE, strings.MIRROR, strings.FULLSCREEN, strings.PICTURE_IN_PICTURE]) |
| crossOrigin | CORS setting of the video element: anonymous or use-credentials; an empty string means anonymous. | "" | "anonymous" | "use-credentials" | semiGlobalDefault("VideoPlayer", "crossOrigin") |
| defaultPlaybackRate | Initial playback rate, read once when the player mounts. | number | TypesemiDefault("VideoPlayer", "defaultPlaybackRate", numbers.DEFAULT_PLAYBACK_RATE) |
| defaultQuality | Initial quality, read once when the player mounts. | string | semiGlobalDefault("VideoPlayer", "defaultQuality") |
| defaultRoute | Initial route, read once when the player mounts. | string | semiGlobalDefault("VideoPlayer", "defaultRoute") |
| height | Player height; a number is in pixels, a string is used as is. | string | number | semiGlobalDefault("VideoPlayer", "height") |
| loop | Whether to loop playback. | boolean | semiDefault("VideoPlayer", "loop", false) |
| markers | Chapter markers, each with a start time in seconds and a title. | Marker[] | semiGlobalDefault("VideoPlayer", "markers") |
| muted | Whether to start muted, read once when the player mounts. | boolean | semiDefault("VideoPlayer", "muted", false) |
| onNext | Called by the next button, which shows only when this is set and controlsList includes next. | Type(() => void) | undefined |
| playbackRateList | Playback rate options, by default 2.0, 1.5, 1.25, 1.0 and 0.75. | TypeVideoPlayerOption<number>[] | semiDefault("VideoPlayer", "playbackRateList", DEFAULT_PLAYBACK_RATE) |
| poster | Poster image URL. | string | semiGlobalDefault("VideoPlayer", "poster") |
| qualityList | Quality options; the quality control shows only when this is non-empty. | TypeVideoPlayerOption<string>[] | semiGlobalDefault("VideoPlayer", "qualityList") |
| routeList | Route options; the route control shows only when this is non-empty. | TypeVideoPlayerOption<string>[] | semiGlobalDefault("VideoPlayer", "routeList") |
| seekTime | Seconds a fast forward or rewind moves. | number | semiDefault("VideoPlayer", "seekTime", numbers.DEFAULT_SEEK_TIME) |
| src | Video URL. Without it a missing-resource message shows; removing it keeps the previous source on the video element. | string | semiGlobalDefault("VideoPlayer", "src") |
| theme | Theme, affecting only the background color: dark or light. | VideoPlayerTheme | semiDefault("VideoPlayer", "theme", strings.DARK) |
| volume | Initial volume from 0 to 100, read once when the player mounts. | number | semiDefault("VideoPlayer", "volume", numbers.DEFAULT_VOLUME) |
| width | Player width; a number is in pixels, a string is used as is. | string | number | semiGlobalDefault("VideoPlayer", "width") |
Events
| Event | Description | Callback parameters |
|---|---|---|
| play | Emitted when playback starts. | [] |
| pause | Emitted when playback pauses. | [] |
| qualityChange | Emitted when the quality changes, with the selected quality value. | [quality: string] |
| rateChange | Emitted when the playback rate changes, with the selected rate. | [rate: number] |
| routeChange | Emitted when the route changes, with the selected route value. | [route: string] |
| volumeChange | Emitted when the user drags the volume slider or toggles mute, with the new volume (0 when muted); not emitted on initialization. | [volume: number] |
Slots
| Slot | Description | Scope parameters |
|---|---|---|
| None |
Exposes
| Name | Description | Type |
|---|---|---|
| video | The native video element, null before mount. | HTMLVideoElement | null |
class, style and native attributes fall through to the root div as attrs, and a width or height in style overrides the width and height props. When the root has aria-label or aria-labelledby it gets role="group", and a role you pass takes precedence. Media events (timeupdate, ended and so on) do not bubble to the root, so listening to them on the component is not supported; get the native element through video and listen on it instead.
Marker
| Properties | Description | Type | Default Value |
|---|---|---|---|
| start | start time point | number | - |
| title | title | string | - |
VideoPlayerOption
The option type of playbackRateList, qualityList and routeList. The type of value follows the list: number for playback rates, string for quality and route.
| Properties | Description | Type | Default Value |
|---|---|---|---|
| label | Name shown in the menu | string | - |
| value | Option value, passed to the event | number | string | - |
Design Token
| Sass variable | Value | Usage |
|---|---|---|
| $animation_duration-videoPlayer_controls-show | 500ms | videoPlayer菜单栏-弹出动画-动画持续时间 |
| $animation_duration-videoPlayer_slider-in | 300ms | videoPlayer进度条-弹出动画-动画持续时间 |
| $animation_function-videoPlayer_slider-in | cubic-bezier(0.62, 0.05, 0.36, 0.95) | videoPlayer进度条-弹出动画-动画插值函数 |
| $animation_function-videoPlayer_slider-out | cubic-bezier(0.62, 0.05, 0.36, 0.95) | videoPlayer进度条-收起动画-动画插值函数 |
| $color-videoPlayer_theme_dark-text | var(--semi-color-bg-0) | dark theme 字体色 |
| $color-videoPlayer_theme_dark-bg | var(--semi-grey-8) | dark theme 背景色 |
| $color-videoPlayer_theme_light-text | var(--semi-grey-8) | light theme 字体色 |
| $color-videoPlayer_theme_light-bg | var(--semi-color-disabled-bg) | light theme 背景色 |
| $color-videoPlayer_pause-bg | var(--semi-color-text-1) | 暂停按钮颜色 |
| $color-videoPlayer_notification-bg | var(--semi-color-overlay-bg) | notification 背景色 |
| $color-videoPlayer_notification-text | var(--semi-color-default) | notification 字体色 |
| $color-videoPlayer_controls-bg | rgba(28, 31, 35, 0.8) | 控制栏背景色 |
| $color-videoPlayer_controls-text | #fff | 控制栏文字色 |
| $color-videoPlayer_controls_popup-bg | rgb(46, 50, 56) | 音量弹层与菜单背景色 |
| $color-videoPlayer_controls_item_popup-bg-default | var(--semi-color-overlay-bg) | 控制栏弹层背景色 |
| $color-videoPlayer_controls_item_popup-bg-hover | rgba(67, 68, 74, 1) | 控制栏弹层背景色 - hover |
| $color-videoPlayer_controls_popup_item-text-default | rgba(#fff, 0.7) | 控制栏文字色 |
| $color-videoPlayer_controls_popup_item-text-active | var(--semi-color-primary) | 控制栏弹层文字色 - 选中 |
| $color-videoPlayer_progress_bar-bg-played | var(--semi-color-primary) | 进度条已播放部分背景色 |
| $color-videoPlayer_progress_bar-bg-loaded | var(--semi-grey-3) | 进度条已加载部分背景色 |
| $color-videoPlayer_progress_bar-bg-unplayed | var(--semi-grey-5) | 进度条未播放部分背景色 |
| $color-videoPlayer_progress_bar_handle-bg | #fff | handle 背景色 |
| $color-videoPlayer_progress_bar_handle-border | var(--semi-color-primary) | handle 边框色 |
| $color-videoPlayer_progress_bar_handle-shadow | var(--semi-color-shadow) | handle 阴影色 |
| $height-videoPlayer_progress_bar_hotSpot-default | 20px | 进度条热区 default 高度 |
| $height-videoPlayer_progress_bar-default | 4px | 进度条 default 高度 |
| $height-videoPlayer_progress_bar-hover | 10px | 进度条 hover 高度 |
| $height-videoPlayer_progress_bar_handle | 16px | 进度条 handle 高度 |
| $height-videoPlayer_controls_menu-default | 56px | 控制栏 default 高度 |
| $height-videoPlayer_controls_volume-default | 168px | 控制栏音量 default 高度:标题 36px + 滑块 120px + 底部留白 12px |
| $height-videoPlayer_controls_popup-default | 24px | 控制栏弹层类元素 default 高度 |
| $height-videoPlayer_controls_popup_item-default | 32px | 控制栏弹层类元素 item default 高度 |
| $width-videoPlayer_controls_volume-default | 40px | 控制栏音量 default 宽度 |
| $width-videoPlayer_controls_popup_item-default | 50px | 控制栏弹层类元素 default 宽度 |
| $width-videoPlayer_controls_popup-default | 48px | 控制栏弹层 default 宽度 |
| $spacing-videoPlayer-progress_bar_chapter-marginRight | 2px | 进度条分节间距 |
| $spacing-videoPlayer_notification-bottom | 22px | notification 距离菜单栏距离 |
| $spacing-videoPlayer_notification-left | 8px | notification 距离菜单栏左侧距离 |
| $spacing-videoPlayer_notification_text-paddingY | 8px | notification 文字垂直方向 padding |
| $spacing-videoPlayer_notification_text-paddingX | 12px | notification 文字水平方向 padding |
| $spacing-videoPlayer-controls-padding | $spacing-base-tight $spacing-base | 控制栏 padding |
| $spacing-videoPlayer-controls_item-gap | $spacing-tight | 控制栏 item 间距 |
| $spacing-videoPlayer-controls_time-paddingX | 8px | 控制栏时间 paddingX |
| $spacing-videoPlayer-controls_volume_title-paddingX | 10px | 控制栏音量标题文字 paddingX |
| $spacing-videoPlayer-controls_volume_title-paddingY | 0px | 控制栏音量标题文字 paddingX |
| $spacing-videoPlayer-controls_volume_popup-paddingY | 0px | 控制栏音量弹层 paddingX |
| $spacing-videoPlayer-controls_volume_popup-paddingX | $spacing-extra-tight | 控制栏音量弹层 paddingX |
| $spacing-videoPlayer-controls_popup-paddingX | $spacing-tight | 控制栏弹层元素 paddingX |
| $spacing-videoPlayer-controls_popup-paddingY | 0px | 控制栏弹层元素 paddingY |
| $spacing-videoPlayer-progress_bar_wrapper-marginX | $spacing-tight | 进度条 wrapper marginX |
| $spacing-videoPlayer-progress_bar_wrapper-marginY | 0px | 进度条 wrapper marginY |
| $spacing-videoPlayer_progress_bar-centerY | $height-videoPlayer_progress_bar_hotSpot-default - $height-videoPlayer_progress_bar-default * 0.5 | 进度条与 handle 的中心线距热区顶部的距离,悬停变粗时上下对称 |
| $spacing-videoPlayer_error_svg-marginBottom | 12px | error svg marginBottom |
| $radius-videoPlayer_notification | 3px | notification 圆角 |
| $radius-videoPlayer_progress_bar_handle | 50% | 进度条 handle 圆角 |
| $radius-videoPlayer_progress_bar | 999px | 进度条圆角 |
| $radius-videoPlayer_controls_item | 3px | 控制栏 item 圆角 |
| $radius-videoPlayer_controls_popup | 4px | 控制栏弹层圆角 |
| $font-videoPlayer_notification-fontSize | $font-size-regular | notification 字体大小 |
| $font-videoPlayer_controls_item-fontSize | $font-size-small | 控制栏 item 字体大小 |
| $font-videoPlayer_controls_time_text-fontSize | $font-size-regular | 控制栏时间字体大小 |
| $font-videoPlayer_error-fontSize | $font-size-regular | error 字体大小 |
| $font-videoPlayer_notification-lineHeight | 20px | notification 行高 |
| $font-videoPlayer_controls_popup_item-lineHeight | 16px | 控制栏 item 行高 |
| $font-videoPlayer_controls_popup_item-fontWeight | 600 | 控制栏 item 字体粗细 |
| $font-videoPlayer_error-fontWeight | 600 | error 字体粗细 |