Vue视频播放实战:vue-video-player与dplayer全攻略‌

Vue 视频播放实战:vue-video-player 与 DPlayer 全攻略


目录

  1. 前言
  2. 环境准备
  3. vue-video-player 实战

    • 3.1 安装与引入
    • 3.2 基础使用示例
    • 3.3 常用配置与自定义控件
    • 3.4 事件监听与 API 调用
    • 3.5 组件结构图解
  4. DPlayer 实战

    • 4.1 安装与引入
    • 4.2 基础使用示例
    • 4.3 弹幕、字幕与画中画功能
    • 4.4 主题、自定义按钮与插件扩展
    • 4.5 技术架构图解
  5. 对比与选型建议
  6. 常见问题与优化
  7. 总结

前言

在现代前端项目中,视频播放几乎是标配功能。Vue 生态下,有两个常见的成熟播放器解决方案:

  1. vue-video-player:基于 Video.js 封装的 Vue 组件,兼容性好,功能全面;
  2. DPlayer:一款轻量级、体验感极佳的 HTML5 弹幕播放器,支持弹幕、画中画、章节等高级功能,深受国内社区喜爱。

本文将从零开始,带你一步步掌握以上两个组件在 Vue(Vue 3 + Vite/CLI 或 Vue 2 + Vue CLI)项目中的集成与使用,并通过大量代码示例与图解,帮助你快速上手、灵活定制,轻松应对项目中的各种视频播放需求。


环境准备

  1. Vue 版本

    • 若使用 Vue 3,请确保项目使用 Vite 或 Vue CLI 4+,并存在 vue@^3.x
    • 若使用 Vue 2,请确保 Vue CLI 3+ 创建的项目,且存在 vue@^2.x
  2. Node.js 与包管理

    • Node.js 14+ 版本,NPM/Yarn/PNPM 均可。
  3. 播放器依赖

    • vue-video-player:需要安装 video.jsvue-video-player
    • DPlayer:需要安装 dplayer,可选 @types/dplayer(TypeScript 项目)。
  4. 开发工具

    • 推荐 VSCode、Android Studio(若做移动端调试)等。

vue-video-player 实战

vue-video-player 是基于 Video.js 封装的 Vue 组件,兼容 HLS、MP4、WebM 等多种视频格式,支持自定义皮肤、插件。在 Vue 项目中集成后,基本可以当作一个常规组件使用。

3.1 安装与引入

注意:以下示例以 Vue 3 + Vite 为主。Vue 2 项目逻辑类似,仅引入方式略有差异(组件名称与导入写法)。

步骤 1:安装依赖

# Vue 3 + Vite 或 Vue CLI 下
npm install video.js vue-video-player --save
# 或
yarn add video.js vue-video-player

安装后,在 node_modules 中会有:

  • video.js/: Video.js 核心库
  • vue-video-player/: Vue 封装组件

步骤 2:全局注册(可选)

若想在项目全局直接使用 <VideoPlayer>,可在入口文件(main.jsmain.ts)中进行注册。

// main.js(Vue 3)
import { createApp } from 'vue';
import App from './App.vue';

// 1. 引入样式
import 'video.js/dist/video-js.css';
import 'vue-video-player/dist/vue-video-player.css';

// 2. 引入组件
import VueVideoPlayer from 'vue-video-player';

// 3. 创建应用并注册
const app = createApp(App);
app.use(VueVideoPlayer);
app.mount('#app');

Vue 2 + Vue CLI 示例

// main.js(Vue 2)
import Vue from 'vue';
import App from './App.vue';

import 'video.js/dist/video-js.css';
import 'vue-video-player/dist/vue-video-player.css';

import VueVideoPlayer from 'vue-video-player';
Vue.use(VueVideoPlayer);

new Vue({
  render: h => h(App),
}).$mount('#app');

如果你不想全局注册,也可以在单个组件里按需引入:

<script setup>
import { VideoPlayer } from 'vue-video-player';
import 'video.js/dist/video-js.css';
import 'vue-video-player/dist/vue-video-player.css';
</script>

<template>
  <video-player :options="playerOptions" />
</template>

3.2 基础使用示例

假设我们在 src/components/VideoDemo.vue 中使用 <video-player>

<template>
  <div class="video-demo">
    <h2>vue-video-player 基础示例</h2>
    <video-player
      class="video-player vjs-custom-skin"
      :options="playerOptions"
      @ended="onEnded"
      @play="onPlay"
      @pause="onPause"
    ></video-player>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { VideoPlayer } from 'vue-video-player';

// 引入样式
import 'video.js/dist/video-js.css';
import 'vue-video-player/dist/vue-video-player.css';

const playerOptions = ref({
  autoplay: false,                  // 是否自动播放
  controls: true,                   // 是否显示控制栏
  preload: 'auto',                  // 视频预加载
  loop: false,                      // 是否循环播放
  muted: false,                     // 是否静音
  language: 'en',                   // 控制栏语言
  liveui: false,                    // 是否使用直播模式样式
  sources: [
    {
      type: 'video/mp4',
      src: 'https://www.w3schools.com/html/mov_bbb.mp4'
    }
  ],
  // 若需 HLS 格式,可用:
  // techOrder: ['html5', 'flash'],
  // html5: {
  //   hls: {
  //     withCredentials: false,
  //   }
  // },
  // sources: [
  //   {
  //     src: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
  //     type: 'application/x-mpegURL',
  //   }
  // ],
  fluid: true,                      // 响应式自适应容器
  poster: 'https://www.example.com/poster.png', // 封面图
});

// 事件回调
function onPlay() {
  console.log('视频开始播放');
}

function onPause() {
  console.log('视频已暂停');
}

function onEnded() {
  console.log('视频播放结束');
}

onMounted(() => {
  console.log('组件挂载完成,playerOptions=', playerOptions.value);
});
</script>

<style scoped>
.video-demo {
  max-width: 800px;
  margin: 16px auto;
}
.video-player {
  width: 100%;
  height: 450px;
}
.vjs-custom-skin .vjs-control-bar {
  /* 定制控制栏背景,如半透明黑色 */
  background: rgba(0, 0, 0, 0.5) !important;
}
</style>

说明:

  • playerOptions.sources 必须提供 typesrc
  • fluid: true 可使播放器自动适应父容器宽度。
  • 通过 @play@pause@ended 等原生 Video.js 事件,可监听播放状态。

3.3 常用配置与自定义控件

3.3.1 自定义控制栏组件

如果想在控制栏中添加自定义按钮,比如“截图”、“播放速度切换”等,需要使用 Video.js 的插件机制。以“截图”按钮为例:

<template>
  <div class="video-demo">
    <h2>自定义截图按钮示例</h2>
    <video-player
      ref="videoPlayer"
      class="video-player vjs-custom-skin"
      :options="playerOptions"
      @ready="onPlayerReady"
    ></video-player>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { VideoPlayer } from 'vue-video-player';
import videojs from 'video.js';

// 引入样式
import 'video.js/dist/video-js.css';
import 'vue-video-player/dist/vue-video-player.css';

const videoPlayer = ref(null);

const playerOptions = {
  controls: true,
  sources: [
    {
      type: 'video/mp4',
      src: 'https://www.w3schools.com/html/mov_bbb.mp4'
    }
  ],
  fluid: true,
  poster: 'https://www.example.com/poster.png'
};

// 自定义按钮:继承 Video.js Button
class ScreenshotButton extends videojs.getComponent('Button') {
  constructor(player, options) {
    super(player, options);
    this.controlText('截图');
  }
  handleClick() {
    const player = this.player();
    const track = player.videoWidth() && player.videoHeight()
      ? player.currentTime()
      : 0;

    // 创建 Canvas 截图
    const videoEl = player.el().getElementsByTagName('video')[0];
    const canvas = document.createElement('canvas');
    canvas.width = videoEl.videoWidth;
    canvas.height = videoEl.videoHeight;
    const ctx = canvas.getContext('2d');
    ctx.drawImage(videoEl, 0, 0, canvas.width, canvas.height);
    const dataURL = canvas.toDataURL('image/png');

    // 下载或展示
    const link = document.createElement('a');
    link.href = dataURL;
    link.download = `screenshot_${Date.now()}.png`;
    link.click();
  }
}

// 注册组件
videojs.registerComponent('ScreenshotButton', ScreenshotButton);

function onPlayerReady({ player }) {
  // 将自定义按钮插入到控制栏
  player.getChild('controlBar').addChild('ScreenshotButton', {}, 0);
}
</script>

<style scoped>
.video-player {
  width: 100%;
  height: 450px;
}
.vjs-custom-skin .vjs-control-bar {
  background: rgba(0, 0, 0, 0.5) !important;
}
</style>

要点解读

  1. videojs.getComponent('Button') 拿到基类后自定义一个按钮类,重写 handleClick
  2. onPlayerReady 中,调用 player.getChild('controlBar').addChild('ScreenshotButton', {}, index) 把按钮插入控制栏。
  3. 自定义按钮可自行添加 icon、tooltip 等。

3.3.2 切换清晰度(VTT/ID3/HLS 方式)

如果要在播放器中添加清晰度切换(如 480P/720P/1080P),可以在 playerOptions 中利用 Video.js 的 sources 数组,或借助 videojs-http-source-selector 插件。以下示例展示最简单的做法——手动销毁后重建播放器切换源:

<template>
  <div class="video-demo">
    <h2>手动切换清晰度示例</h2>
    <div class="btn-group">
      <button @click="changeSource('480p')">480P</button>
      <button @click="changeSource('720p')">720P</button>
      <button @click="changeSource('1080p')">1080P</button>
    </div>
    <video-player
      ref="videoPlayer"
      class="video-player"
      :options="playerOptions"
      @ready="onPlayerReady"
    ></video-player>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { VideoPlayer } from 'vue-video-player';
import videojs from 'video.js';

const videoPlayer = ref(null);

const sourcesMap = {
  '480p': 'https://example.com/video_480p.mp4',
  '720p': 'https://example.com/video_720p.mp4',
  '1080p': 'https://example.com/video_1080p.mp4'
};

const playerOptions = ref({
  controls: true,
  sources: [
    { type: 'video/mp4', src: sourcesMap['480p'] }
  ],
  fluid: true
});

let playerInstance = null;

function onPlayerReady({ player }) {
  playerInstance = player;
}

// 切换清晰度
function changeSource(level) {
  if (!playerInstance) return;
  // 暂存当前播放时间
  const currentTime = playerInstance.currentTime();
  // 更新源
  playerInstance.src({ type: 'video/mp4', src: sourcesMap[level] });
  // 重新加载并跳转到之前时间
  playerInstance.load();
  playerInstance.ready(() => {
    playerInstance.currentTime(currentTime);
    playerInstance.play();
  });
}
</script>

<style scoped>
.btn-group {
  margin-bottom: 8px;
}
.btn-group button {
  margin-right: 8px;
  padding: 6px 12px;
  background: #409eff;
  border: none;
  color: white;
  border-radius: 4px;
  cursor: pointer;
}
.btn-group button:hover {
  background: #66b1ff;
}
.video-player {
  width: 100%;
  height: 450px;
}
</style>

说明

  • 通过 Video.js 原生的 player.src() 方法可动态切换视频源。
  • 切换后调用 load()ready() 回调确保跳转与播放。

3.4 事件监听与 API 调用

vue-video-player 把 Video.js 常用事件都封装为组件事件。常见事件包括:

事件名说明回调参数
ready播放器初始化完成{ player }
play视频开始播放event
pause视频暂停event
ended视频播放结束event
error播放出错event
timeupdate播放进度更新(每隔一定时间触发)event
volumechange音量变化event
fullscreenchange全屏/退出全屏event

ready 回调里,你可以拿到 player 实例,进而调用视频的原生方法,例如:

function onPlayerReady({ player }) {
  // 暂停
  player.pause();
  // 获取当前时间
  const t = player.currentTime();
  console.log('当前播放时间:', t);
  // 跳转到某个时间点
  player.currentTime(30);
  // 全屏
  player.requestFullscreen();
  // 设置音量
  player.volume(0.5);
}

3.5 组件结构图解

VideoDemo.vue
┌─────────────────────────────────────────────────────────────┐
│ <video-player>                                              │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ <div class="video-js vjs-default-skin">                 │ │
│ │   <video class="vjs-tech" src="..." preload="auto"></video> │ │
│ │   <div class="vjs-control-bar">                          │ │
│ │     <!-- 播放/暂停 按钮 -->                                │ │
│ │     <!-- 音量、进度条、全屏等控件 -->                       │ │
│ │   </div>                                                  │ │
│ │   <!-- 其他 Video.js 插件容器(例如 弹幕、字幕面板) -->        │ │
│ │ </div>                                                   │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

事件流示意:
用户点击“播放” →组件触发 @play → Vue 组件逻辑接收 → 或者拿到 player 实例手动调用 play()
  • <video-player> 本质上是一个包装 Video.js 初始化与销毁的 Vue 组件,内部渲染一个带有 vjs-* 类名的容器。
  • 你只需通过 props 传入 options,以及监听 Vue 事件即可;若要访问更底层的 Video.js API,可在 @ready 拿到 player

DPlayer 实战

DPlayer 是国内社区非常流行的 HTML5 弹幕播放器,支持弹幕、字幕、画中画、画质切换等丰富功能。DPlayer 核心是原生 JS,而社区有专门的 Vue 封装插件,也可直接用 ref 挂载到 DOM 上。

4.1 安装与引入

步骤 1:安装依赖

npm install dplayer --save
# 如果需要字幕及插件支持,可额外安装:
# npm install flv.js flv.js/dist/flv.min.js --save

若想使用 Vue 封装组件(如 vue-dplayer),也可:

npm install vue-dplayer --save

但本文以原生 DPlayer + Vue 组合为主,方便你精准控制初始化与销毁。

步骤 2:在组件中引入

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import DPlayer from 'dplayer';
import 'dplayer/dist/DPlayer.min.css';
</script>

<template>
  <div class="dplayer-demo">
    <h2>DPlayer 基础示例</h2>
    <!-- 容器 -->
    <div ref="dpContainer" class="dplayer-container"></div>
  </div>
</template>

说明

  • dplayer 安装后会生成 DPlayer.min.css 以及 .js 文件,我们需在组件里引入 CSS。
  • ref="dpContainer" 用于挂载播放器实例。

4.2 基础使用示例

<template>
  <div class="dplayer-demo">
    <h2>DPlayer 基础示例</h2>
    <div ref="dpContainer" class="dplayer-container"></div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import DPlayer from 'dplayer';
import 'dplayer/dist/DPlayer.min.css';

let dp = null;
const dpContainer = ref(null);

onMounted(() => {
  // 初始化 DPlayer
  dp = new DPlayer({
    container: dpContainer.value,         // 挂载容器
    autoplay: false,
    theme: '#FADFA3',                     // 主题色
    loop: false,
    lang: 'zh-cn',
    preload: 'auto',
    volume: 0.7,
    video: {
      url: 'https://www.w3schools.com/html/mov_bbb.mp4',
      pic: 'https://www.example.com/poster.png',
      thumbnails: 'https://www.example.com/thumbs.jpg',
      type: 'auto'
    }
  });

  // 监听事件
  dp.on('play', () => {
    console.log('DPlayer:播放');
  });
  dp.on('pause', () => {
    console.log('DPlayer:暂停');
  });
  dp.on('ended', () => {
    console.log('DPlayer:播放结束');
  });
});

onBeforeUnmount(() => {
  if (dp) {
    dp.destroy(); // 组件卸载时销毁实例,释放资源
  }
});
</script>

<style scoped>
.dplayer-container {
  width: 100%;
  max-width: 800px;
  height: 450px;
  margin: 16px auto;
}
</style>

核心要点

  1. new DPlayer({ … }) 需传入 container(DOM 元素)。
  2. video 配置中,url 是视频地址,pic 是封面图,thumbnails 是进度条预览图。
  3. 通过 dp.on('event', callback) 监听 playpauseended 等事件。
  4. 一定要在组件销毁前调用 dp.destroy(),否则可能造成内存泄漏。

4.3 弹幕、字幕与画中画功能

4.3.1 弹幕(Danmaku)

DPlayer 的最大特色之一就是“弹幕”功能,对视频播放添加实时评论效果。使用非常简单:

<template>
  <div class="dplayer-demo">
    <h2>DPlayer 弹幕示例</h2>
    <div ref="dpContainer" class="dplayer-container"></div>
    <div class="danmaku-input">
      <input v-model="danmuText" placeholder="请输入弹幕内容" />
      <button @click="sendDanmaku">发送弹幕</button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import DPlayer from 'dplayer';
import 'dplayer/dist/DPlayer.min.css';

let dp = null;
const dpContainer = ref(null);

// 弹幕输入
const danmuText = ref('');

onMounted(() => {
  dp = new DPlayer({
    container: dpContainer.value,
    video: {
      url: 'https://www.w3schools.com/html/mov_bbb.mp4',
      pic: 'https://www.example.com/poster.png',
    },
    danmaku: {
      id: 'demo',  // 弹幕载体唯一 id,可用于后端区分视频
      api: 'https://api.prprpr.me/dplayer/', // 公开的 DPlayer 弹幕API示例
      maximum: 1000,
      user: '游客', // 自定义弹幕用户名
      bottom: '15px', // 弹幕距离底部距离
      unlimited: false
    }
  });
});

// 发送弹幕
function sendDanmaku() {
  if (!danmuText.value.trim()) return;
  dp.sendDanmaku({
    text: danmuText.value,
    color: '#ffffff',
    type: 'right', // 弹幕类型: 'right' | 'top' | 'bottom'
  });
  danmuText.value = '';
}

onBeforeUnmount(() => {
  if (dp) dp.destroy();
});
</script>

<style scoped>
.dplayer-container {
  width: 100%;
  max-width: 800px;
  height: 450px;
  margin: 16px auto;
}
.danmaku-input {
  display: flex;
  justify-content: center;
  margin-top: 8px;
}
.danmaku-input input {
  width: 60%;
  padding: 6px 8px;
  border: 1px solid #ccc;
  border-radius: 4px 0 0 4px;
  outline: none;
}
.danmaku-input button {
  padding: 6px 12px;
  background: #e6a23c;
  border: none;
  color: white;
  border-radius: 0 4px 4px 0;
  cursor: pointer;
}
.danmaku-input button:hover {
  background: #f0ad4e;
}
</style>

说明

  • danmaku 配置中,api 指向弹幕接口(可以自行搭建后端或使用公开 API)。
  • dp.sendDanmaku({ text, color, type }) 会将弹幕发送到后端并在本地展示。

4.3.2 字幕(Subtitles)

如果要为视频添加字幕,需在初始化时指定 subtitle

dp = new DPlayer({
  container: dpContainer.value,
  video: { url: 'https://www.example.com/video.mp4', pic: '...' },
  subtitle: {
    url: 'https://www.example.com/subtitle.srt', // 字幕文件地址,可为 .srt 或 .vtt
    type: 'srt',  // 字幕类型 'webvtt' | 'srt'
    fontSize: '25px',
    bottom: '10%',
    color: '#ff0000'
  }
});
  • subtitle.url:字幕文件地址,浏览器能直接加载。
  • type:字幕类型,.srt 或者 .vtt
  • fontSizebottomcolor 等可定制字幕样式。

4.3.3 画中画(Picture-in-Picture)

若需要在支持画中画的浏览器/环境下启用该功能,只需在初始化时设置:

dp = new DPlayer({
  container: dpContainer.value,
  video: { url: '...', pic: '...' },
  pip: true,  // 启用画中画
});

在支持的环境(如 Safari、Chrome 70+)下,右下角会出现“画中画”按钮,点击后视频会悬浮在页面上。

4.4 主题、自定义按钮与插件扩展

与 vue-video-player 类似,DPlayer 也支持自定义皮肤、按钮、插件。以“自定义回放速度”按钮为例:

<template>
  <div class="dplayer-demo">
    <h2>DPlayer 自定义功能示例</h2>
    <div ref="dpContainer" class="dplayer-container"></div>
    <div class="speed-controls">
      <button @click="setSpeed(0.5)">0.5x</button>
      <button @click="setSpeed(1)">1x</button>
      <button @click="setSpeed(1.5)">1.5x</button>
      <button @click="setSpeed(2)">2x</button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import DPlayer from 'dplayer';
import 'dplayer/dist/DPlayer.min.css';

let dp = null;
const dpContainer = ref(null);

onMounted(() => {
  dp = new DPlayer({
    container: dpContainer.value,
    video: {
      url: 'https://www.w3schools.com/html/mov_bbb.mp4',
      pic: 'https://www.example.com/poster.png',
    },
    playbackSpeed: [0.5, 1, 1.5, 2],  // 指定支持的倍速数组
    menu: [
      {
        text: '自定义菜单',
        link: 'https://dplayer.js.org/'
      }
    ]
  });
});

function setSpeed(rate) {
  if (dp) {
    dp.speed(rate);
    console.log(`已切换到 ${rate} 倍速`);
  }
}

onBeforeUnmount(() => {
  if (dp) dp.destroy();
});
</script>

<style scoped>
.dplayer-container {
  width: 100%;
  max-width: 800px;
  height: 450px;
  margin: 16px auto;
}
.speed-controls {
  display: flex;
  justify-content: center;
  margin-top: 8px;
}
.speed-controls button {
  margin: 0 6px;
  padding: 6px 12px;
  background: #67c23a;
  border: none;
  color: white;
  border-radius: 4px;
  cursor: pointer;
}
.speed-controls button:hover {
  background: #85ce61;
}
</style>

要点

  • 通过 playbackSpeed 数组设置可选倍速值。
  • dp.speed(rate) 即可实时切换。
  • menu 字段可添加右上角的自定义菜单链接。

4.5 技术架构图解

DPlayer.vue
┌──────────────────────────────────────────────────┐
│ new DPlayer({                                   │
│   container: dpContainer,                       │
│   video: { url, pic, type },                    │
│   danmaku: { api, id, },                        │
│   subtitle: { url, type, fontSize, ... },       │
│   pip: true,                                    │
│   playbackSpeed: [...],                         │
│   menu: [...]                                   │
│ })                                              │
│ ┌──────────────────────────────────────────────┐ │
│ │ <div class="dplayer-con">                    │ │
│ │   <video class="dplayer-video" src="..." /> │ │
│ │   <!-- Control Bar -->                        │ │
│ │   <div class="dplayer-control-bar">           │ │
│ │     <!-- 播放/暂停/音量/进度/全屏/弹幕等控件 -->     │ │
│ │   </div>                                      │ │
│ │   <!-- 弹幕层 -->                              │ │
│ │   <canvas class="dplayer-danmaku-layer" />   │ │
│ │   <!-- 字幕层 -->                              │ │
│ │   <div class="dplayer-subtitle"></div>        │ │
│ │ </div>                                        │ │
│ └──────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘

事件流示意:
视频缓冲完成 → DPlayer 自动监听 → 用户可发送弹幕 → dp.sendDanmaku({...})
  • 整体架构可分为:视频层<video>)、控制栏(各种按钮)、弹幕层(Canvas 渲染)、字幕层(DOM 元素)。
  • DPlayer 内部对 HLS、FLV、Dash 等格式提供了自动识别(type: 'auto'),并加载对应 JS 库(需要额外安装)。

对比与选型建议

特性vue-video-player (Video.js)DPlayer
体积较大(Video.js 核心 \~200KB+)较小(核心 \~100KB+)
弹幕支持需额外插件,如 videojs-contrib-danmaku原生支持,无需额外依赖
字幕支持Video.js 原生支持 .vtt/.srt原生支持 .vtt/.srt
画质切换需手动切换 player.src() 或插件支持 playlist 功能自动切换
插件生态丰富(广告、分析、VR、直播等)生态逐步完善,社区插件较多(截图、音效等)
移动端兼容性良好极佳
API 丰富程度完备完备
UI 美观度扩展性强,可自定义皮肤开箱即用,默认皮肤较现代
二次开发难度中等(需了解 Video.js plugin 机制)低(API 直观、文档清晰)
Vue 封装组件vue-video-player 便于集成可用 vue-dplayer 或手动封装
  • 如果项目需求偏向“基础播放器+广告、分析”或需兼容更多视频格式、插件,请优先考虑 vue-video-player (Video.js)
  • 若需快速搭建带弹幕、画中画、倍速切换、主题效果的现代播放器,且更看重“简洁 UI + 易用 API”,则 DPlayer 是更佳选择。

常见问题与优化

  1. 页面首次加载白屏/播放器闪烁

    • 原因:若在父容器宽高未确定前就渲染播放器,可能出现闪烁。
    • 解决:用 CSS 预留容器宽高,或在 v-if="showPlayer" 延迟渲染。
  2. HLS/FLV 视频无法播放

    • 原因:浏览器未原生支持 HLS/FLV,需引入对应 JS 库。
    • 解决

      • 对于 vue-video-player,可安装并引入 videojs-flash / videojs-contrib-hls 等插件;
      • 对于 DPlayer,可额外安装 flv.jsmpegts.js,并在初始化时指定 type: 'flv'
  3. 弹幕无法显示

    • 原因一danmaku.api 配置错误,无法请求弹幕数据;
    • 原因二:跨域请求被阻止,需后端或 CDN 配置 CORS;
    • 解决:确认 API 地址可访问、返回数据格式符合 DPlayer 要求,或使用本地模拟。
  4. 截图按钮样式错位

    • 原因:自定义按钮未指定图标,尺寸和位置需手动调整。
    • 解决:通过 CSS 设置 .vjs-screenshot-button .vjs-icon-placeholder:before { content: '📸'; } 或替换 SVG 图标。
  5. 嵌入到 Modal/Drawer 等动态容器中失真

    • 原因:CSS 隐藏时播放器无法正确计算宽高。
    • 解决:在容器弹出后触发重绘:

      setTimeout(() => {
        playerInstance && playerInstance.trigger('resize');
      }, 300);
    • 或使用 player.fluid(true) 重新适配。
  6. 手机端长按进度条弹出菜单(复制/粘贴/另存为)

    • 原因:浏览器默认行为影响交互。
    • 解决:为 <video> 添加 controlsList="nodownload noremoteplayback",或绑定 oncontextmenu="event.preventDefault()" 禁用右键菜单。

总结

本文从基础安装到高级定制,详细介绍了 Vue 应用中集成 vue-video-player(Video.js 封装)DPlayer 两种主流方案:

  1. vue-video-player:基于 Video.js,功能齐全,插件生态丰富,适合需要广告、分析、直播、VR 等复杂需求的项目;
  2. DPlayer:轻量级、弹幕体验出色,UI 现代、API 简洁,适合需要弹幕、字幕、画中画等极致体验的项目。

通过丰富的代码示例与图解,你可以掌握:

  • 如何在 Vue 中正确引入与注册播放器
  • 如何根据项目需求进行基础配置与样式定制
  • 如何使用 API 实现“清晰度切换”、“截图”、“弹幕”、以及“画中画”等高级功能
  • 如何在组件生命周期中初始化、销毁播放器,避免资源泄漏
VUE
最后修改于:2025年05月31日 12:23

评论已关闭

推荐阅读

DDPG 模型解析,附Pytorch完整代码
2024年11月24日
DQN 模型解析,附Pytorch完整代码
2024年11月24日
AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日