前言
在 Vue 3 生态中,视频播放功能是许多应用的核心需求。@videojs-player/vue
是一个专门为 Vue 3 设计的视频播放器组件,基于成熟的 Video.js 库构建,提供了简单而强大的视频播放解决方案。
主要特性
- Vue 3 组件化:原生 Vue 3 组件,完美融入组合式 API
- 功能丰富:支持多种视频格式、直播流、字幕等
- 高度可定制:支持主题、插件、控制栏等多种自定义选项
- TypeScript 支持:完整的类型定义
- 响应式设计:自适应不同屏幕尺寸
安装方式
# npm
npm install video.js @videojs-player/vue
# yarn
yarn add video.js @videojs-player/vue
# pnpm
pnpm add video.js @videojs-player/vue
快速上手
基础用法
<template>
<div class="text-center">
<h2 class="text-2xl font-bold p-2">基础视频播放器</h2>
<VideoPlayer
src="https://vjs.zencdn.net/v/oceans.mp4"
poster="https://github.surmon.me/images/poster/oceans.png"
:controls="true"
:fluid="true"
/>
</div>
</template>
<script setup>
import { VideoPlayer } from "@videojs-player/vue";
import "video.js/dist/video-js.css";
</script>
自定义配置
<template>
<div>
<h2>自定义配置播放器</h2>
<VideoPlayer :options="videoOptions" @ready="onPlayerReady" />
</div>
</template>
<script setup>
import { ref } from "vue";
import { VideoPlayer } from "@videojs-player/vue";
import "video.js/dist/video-js.css";
const videoOptions = ref({
autoplay: "muted", // 自动播放
controls: true, // 是否显示控制栏
responsive: true, // 是否响应式
fluid: true, // 是否自适应父容器宽度
loop: true, // 是否循环播放
playbackRate: 2, // 播放速度
playbackRates: [0.5, 1, 1.5, 2], // 播放速度选项
sources: [
{
src: "https://vjs.zencdn.net/v/oceans.mp4",
type: "video/mp4",
},
],
poster: "https://github.surmon.me/images/poster/oceans.png",
});
const onPlayerReady = (player) => {
console.log("播放器已准备就绪", player);
};
</script>
高级用法
播放器控制
<template>
<div
class="min-h-screen bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900 p-8"
>
<div class="max-w-4xl mx-auto">
<!-- 标题 -->
<h1
class="text-3xl font-bold text-white text-center mb-8 bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent"
>
视频播放器演示
</h1>
<!-- 视频播放器容器 -->
<div
class="bg-white/10 backdrop-blur-sm rounded-2xl p-6 shadow-2xl border border-white/20"
>
<video-player
:options="videoOptions"
@mounted="handleMounted"
class="w-full h-auto max-w-full rounded-xl overflow-hidden shadow-lg"
/>
</div>
<!-- 控制按钮区域 -->
<div
class="mt-8 bg-white/10 backdrop-blur-sm rounded-2xl p-6 shadow-2xl border border-white/20"
>
<h2 class="text-xl font-semibold text-white mb-4 text-center">
播放控制
</h2>
<div class="flex flex-wrap gap-4 justify-center">
<button
@click="play"
class="px-6 py-3 bg-gradient-to-r from-green-500 to-emerald-600 hover:from-green-600 hover:to-emerald-700 text-white font-semibold rounded-lg shadow-lg hover:shadow-xl transform hover:scale-105 transition-all duration-200 flex items-center gap-2"
>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path d="M8 5v10l8-5-8-5z" />
</svg>
播放
</button>
<button
@click="pause"
class="px-6 py-3 bg-gradient-to-r from-yellow-500 to-orange-600 hover:from-yellow-600 hover:to-orange-700 text-white font-semibold rounded-lg shadow-lg hover:shadow-xl transform hover:scale-105 transition-all duration-200 flex items-center gap-2"
>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path d="M5 4h3v12H5V4zm7 0h3v12h-3V4z" />
</svg>
暂停
</button>
<button
@click="mute"
class="px-6 py-3 bg-gradient-to-r from-red-500 to-pink-600 hover:from-red-600 hover:to-pink-700 text-white font-semibold rounded-lg shadow-lg hover:shadow-xl transform hover:scale-105 transition-all duration-200 flex items-center gap-2"
>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path
d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.617.794L5.617 14H3a1 1 0 01-1-1V7a1 1 0 011-1h2.617l2.766-2.794a1 1 0 011-.13zM14.657 2.929a1 1 0 011.414 0A9.972 9.972 0 0119 10a9.972 9.972 0 01-2.929 7.071 1 1 0 01-1.414-1.414A7.971 7.971 0 0017 10c0-2.21-.894-4.208-2.343-5.657a1 1 0 010-1.414zm-2.829 2.828a1 1 0 011.415 0A5.983 5.983 0 0115 10a5.984 5.984 0 01-1.757 4.243 1 1 0 01-1.415-1.415A3.984 3.984 0 0013 10a3.983 3.983 0 00-1.172-2.828 1 1 0 010-1.415z"
/>
</svg>
静音
</button>
<button
@click="setVolume(0.5)"
class="px-6 py-3 bg-gradient-to-r from-blue-500 to-indigo-600 hover:from-blue-600 hover:to-indigo-700 text-white font-semibold rounded-lg shadow-lg hover:shadow-xl transform hover:scale-105 transition-all duration-200 flex items-center gap-2"
>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path
d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.617.794L5.617 14H3a1 1 0 01-1-1V7a1 1 0 011-1h2.617l2.766-2.794a1 1 0 011-.13z"
/>
</svg>
设置音量
</button>
<button
@click="seekTo(30)"
class="px-6 py-3 bg-gradient-to-r from-purple-500 to-violet-600 hover:from-purple-600 hover:to-violet-700 text-white font-semibold rounded-lg shadow-lg hover:shadow-xl transform hover:scale-105 transition-all duration-200 flex items-center gap-2"
>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path
d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z"
/>
</svg>
跳转到30秒
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { VideoPlayer } from "@videojs-player/vue";
import "video.js/dist/video-js.css";
const player = ref();
const videoOptions = reactive({
controls: true,
sources: [
{
src: "https://vjs.zencdn.net/v/oceans.mp4",
type: "video/mp4",
},
],
poster: "https://github.surmon.me/images/poster/oceans.png",
});
const handleMounted = (payload) => {
console.log("handleMounted", payload);
player.value = payload.player;
};
const play = () => {
if (player.value) {
player.value.play();
}
};
const pause = () => {
if (player.value) {
player.value.pause();
}
};
const mute = () => {
if (player.value) {
player.value.muted(!player.value.muted());
}
};
const setVolume = (volume) => {
if (player.value) {
player.value.volume(volume);
}
};
const seekTo = (time) => {
if (player.value) {
player.value.currentTime(time);
}
};
</script>

直播流播放
<template>
<div>
<h2>直播流播放器</h2>
<VideoPlayer :options="liveOptions" @ready="onLivePlayerReady" />
</div>
</template>
<script setup>
import { ref } from "vue";
import { VideoPlayer } from "@videojs-player/vue";
import "video.js/dist/video-js.css";
const liveOptions = ref({
controls: true,
responsive: true,
fluid: true,
liveui: true,
sources: [
{
src: "https://example.com/live-stream.m3u8",
type: "application/x-mpegURL",
},
],
});
const onLivePlayerReady = (player) => {};
</script>
字幕支持
<template>
<div>
<h2>字幕支持播放器</h2>
<VideoPlayer :options="subtitleOptions" @ready="onSubtitlePlayerReady" />
</div>
</template>
<script setup>
import { ref } from "vue";
import { VideoPlayer } from "@videojs-player/vue";
import "video.js/dist/video-js.css";
const subtitleOptions = ref({
controls: true,
responsive: true,
fluid: true,
sources: [
{
src: "https://vjs.zencdn.net/v/oceans.mp4",
type: "video/mp4",
},
],
tracks: [
{
kind: "subtitles",
src: "https://example.com/subtitles-zh.vtt",
srclang: "zh",
label: "中文",
default: true,
},
{
kind: "subtitles",
src: "https://example.com/subtitles-en.vtt",
srclang: "en",
label: "English",
},
],
});
const onSubtitlePlayerReady = (player) => {};
</script>
常见问题
Q: 如何实现自动播放?
A: 由于浏览器限制,自动播放需要满足以下条件之一:
- 视频设置为静音(
muted: true
) - 用户已与页面交互
<VideoPlayer autoplay="muted" />
Q: 如何处理跨域视频?
A: 确保视频服务器设置了正确的 CORS 头,或在组件上添加 crossorigin
属性:
<VideoPlayer :src="videoSrc" crossorigin="anonymous" />
总结
@videojs-player/vue
是 Vue 3 应用中实现视频播放功能的最佳选择之一,它简单、可靠、高效,能够满足大多数视频播放需求。无论是简单的视频展示还是复杂的流媒体应用,它都能提供出色的解决方案。
原文链接:https://code.ifrontend.net/archives/1273,转载请注明出处。
评论0