代码演示
如何引入
<script setup lang="ts">
import { VideoPlayer } from '@fibrous/semi-ui-vue';
</script>
基本用法
基本使用,通过 src 传入视频地址, 通过 poster 传入视频封面地址

代码
<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>设置菜单栏功能
通过 controlsList 设置菜单栏的展示项,该项接受值为数组,默认值为['play', 'next', 'time', 'volume', 'playbackRate', 'quality', 'route', 'mirror', 'fullscreen', 'pictureInPicture']
控件在 controlsList 允许、并且它所依赖的属性已提供时才显示:next 需要 onNext,quality 需要非空的 qualityList,route 需要非空的 routeList;其余控件只看 controlsList。
onNext 是函数 prop,模板里写 @next 或 :onNext 都可以;传与不传决定「下一个」按钮是否显示。

代码
<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 设置循环播放

代码
<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>快进快退
通过 seekTime 设置快进快退时间,通过键盘左右键执行快进快退

代码
<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>播放速率
通过 playbackRateList 设置速率选择列表。速率、清晰度与线路控件都是原生按钮,用 Tab 聚焦即展开菜单,键盘操作见「键盘和焦点」。按钮名称为用途加当前选项(如「倍速 1.0x」),菜单项是单选项

代码
<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 设置初始音量,值区间为 0 - 100, 设置 muted 为 true 可以静音播放。用户调整音量时会触发 volumeChange 事件

代码
<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>清晰度切换
通过 qualityList 设置清晰度选择列表,defaultQuality 设置初始选择的清晰度,在 qualityChange 事件中更新 src。
线路切换同理,通过 routeList 设置线路选择列表,defaultRoute 设置初始选择的线路,在 routeChange 事件中更新 src。

代码
<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>章节标记
通过 markers 设置章节标记点

代码
<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 设置主题, 主题仅影响背景色

代码
<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>使用 ref 控制
通过模板 ref(useTemplateRef)取得组件实例,其 video 属性是原生 video 元素,可以实现更灵活的控制,例如多个视频同步播放/暂停。元素在挂载前为 null


代码
<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>键盘和焦点
- 焦点在播放器内时,空格键切换播放与暂停,焦点在按钮或输入控件上时空格键交给该控件;左右方向键按
seekTime快退、快进,焦点在输入控件、进度条或菜单内时方向键交给它们。带 Alt、Ctrl、Meta 的组合键不处理。 - 进度条是滑块(
role="slider"),用方向键按seekTime增减,PageUp、PageDown 按总时长的十分之一增减,Home、End 跳到两端。读屏读出的是「当前时长 / 总时长」。 - 倍速、清晰度、线路按钮用 Tab 聚焦即展开菜单,下、上方向键把焦点移到菜单的第一项、最后一项;菜单内用上下方向键与 Home、End 移动,Enter 或空格确认,Esc 关闭并回到按钮。
- 音量按钮获得焦点时展开音量弹层,Enter 或空格切换静音;下方向键把焦点移进弹层,音量滑块用方向键调节。
- 播放中指针离开播放器后,控制栏内有键盘焦点时控制栏保持显示。
API
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| autoPlay | 是否自动播放。 | boolean | semiDefault("VideoPlayer", "autoPlay", false) |
| captionsSrc | 字幕资源地址,传入后默认显示字幕。 | string | semiGlobalDefault("VideoPlayer", "captionsSrc") |
| clickToPlay | 点击视频画面时是否切换播放与暂停。 | boolean | semiDefault("VideoPlayer", "clickToPlay", true) |
| controlsList | 控制栏展示的控件,默认展示全部。控件还要满足依赖的属性已提供才会显示。 | 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 | video 元素的 CORS 设置,允许的值为 anonymous 与 use-credentials,空串等同 anonymous。 | "" | "anonymous" | "use-credentials" | semiGlobalDefault("VideoPlayer", "crossOrigin") |
| defaultPlaybackRate | 初始播放倍率,仅在挂载时读取。 | number | TypesemiDefault("VideoPlayer", "defaultPlaybackRate", numbers.DEFAULT_PLAYBACK_RATE) |
| defaultQuality | 初始清晰度,仅在挂载时读取。 | string | semiGlobalDefault("VideoPlayer", "defaultQuality") |
| defaultRoute | 初始线路,仅在挂载时读取。 | string | semiGlobalDefault("VideoPlayer", "defaultRoute") |
| height | 播放器高度,数字按像素处理,字符串原样使用。 | string | number | semiGlobalDefault("VideoPlayer", "height") |
| loop | 是否循环播放。 | boolean | semiDefault("VideoPlayer", "loop", false) |
| markers | 章节标记,每项含起始时间 start(秒)与标题 title。 | Marker[] | semiGlobalDefault("VideoPlayer", "markers") |
| muted | 是否静音播放,仅在挂载时读取。 | boolean | semiDefault("VideoPlayer", "muted", false) |
| onNext | 点击下一个按钮时调用。设置后且 controlsList 包含 next 时才显示该按钮。 | Type(() => void) | undefined |
| playbackRateList | 倍速选项列表,默认为 2.0、1.5、1.25、1.0、0.75 五档。 | TypeVideoPlayerOption<number>[] | semiDefault("VideoPlayer", "playbackRateList", DEFAULT_PLAYBACK_RATE) |
| poster | 封面图地址。 | string | semiGlobalDefault("VideoPlayer", "poster") |
| qualityList | 清晰度选项列表,非空时才显示清晰度控件。 | TypeVideoPlayerOption<string>[] | semiGlobalDefault("VideoPlayer", "qualityList") |
| routeList | 线路选项列表,非空时才显示线路控件。 | TypeVideoPlayerOption<string>[] | semiGlobalDefault("VideoPlayer", "routeList") |
| seekTime | 快进快退一次的秒数。 | number | semiDefault("VideoPlayer", "seekTime", numbers.DEFAULT_SEEK_TIME) |
| src | 视频地址。未设置时显示资源缺失提示;移除后 video 元素保留上一个地址。 | string | semiGlobalDefault("VideoPlayer", "src") |
| theme | 主题,仅影响背景色,可选 dark 或 light。 | VideoPlayerTheme | semiDefault("VideoPlayer", "theme", strings.DARK) |
| volume | 初始音量,取值 0 到 100,仅在挂载时读取。 | number | semiDefault("VideoPlayer", "volume", numbers.DEFAULT_VOLUME) |
| width | 播放器宽度,数字按像素处理,字符串原样使用。 | string | number | semiGlobalDefault("VideoPlayer", "width") |
Events
| 事件 | 说明 | 回调参数 |
|---|---|---|
| play | 开始播放时触发。 | [] |
| pause | 暂停时触发。 | [] |
| qualityChange | 切换清晰度时触发,参数为所选清晰度的值。 | [quality: string] |
| rateChange | 切换倍速时触发,参数为所选倍率。 | [rate: number] |
| routeChange | 切换线路时触发,参数为所选线路的值。 | [route: string] |
| volumeChange | 用户拖动音量滑块或切换静音时触发,参数为变化后的音量,静音时为 0;初始化不触发。 | [volume: number] |
Slots
| 插槽 | 说明 | 作用域参数 |
|---|---|---|
| 无 |
Exposes
| 名称 | 说明 | 类型 |
|---|---|---|
| video | 原生 video 元素,挂载前为 null。 | HTMLVideoElement | null |
class、style 与原生属性经 attrs 落在根元素 div 上,style 中的 width、height 覆盖 width、height 属性;根元素带 aria-label 或 aria-labelledby 时自动加 role="group",自己传 role 则以传入的为准。媒体事件(timeupdate、ended 等)不会冒泡到根元素,因此不支持在组件上监听,需要时通过 video 取得原生元素后自行监听。
Marker
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| start | 起始时间点 | number | - |
| title | 标题 | string | - |
VideoPlayerOption
playbackRateList、qualityList、routeList 的选项类型,value 的类型随列表而定(倍速为 number,清晰度与线路为 string)。
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| label | 菜单中显示的名称 | string | - |
| value | 选项值,事件参数取此 | number | string | - |
设计变量
| Sass 变量 | 值 | 用法 |
|---|---|---|
| $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 字体粗细 |