基于 Vue3 封装大华 RTSP 回放视频组件(PlayerControl.js 实现)

在项目中,我们经常需要对接摄像头视频流,尤其是大华(Dahua)或海康(Hikvision)设备的视频实时播放与回放 。本文将介绍如何在 Vue3 + PlayerControl.js SDK 环境下封装一个可复用的大华视频回放组件


一、📺 背景介绍

在传统的视频回放场景中,大华设备通常通过 RTSP 协议 提供视频流(例如 rtsp://admin:password@ip:554/cam/playback?...)。

但是浏览器无法直接播放 RTSP 流,因此通常需要通过 WebSocket 转发SDK 解码(如 PlayerControl.js) 来实现播放。

我们项目中后端已经搭建了 rtspoverwebsocket 转发服务,因此可以直接在前端通过 SDK 播放 RTSP 视频。


二、🧩 技术栈与环境

  • 框架:Vue 3 + Vite

  • 视频 SDKPlayerControl.js(大华 Web 播放控制 SDK)

  • 传输协议:RTSP over WebSocket

  • 播放场景:录像回放(带时间段参数)


三、⚙️ 组件设计思路

我们封装一个通用的 <DahuaPlayer /> 组件,具备以下特性:

✅ 支持实时与回放播放模式

✅ 参数变化(通道号、时间、URL)自动重载

✅ 自动关闭旧实例,防止内存泄漏

✅ 支持一键全屏

✅ 完整错误提示与日志输出


四、📦 PlayerControl SDK 引入

首先在 public/module/ 目录下放置 Dahua 提供的 playerControl.js

然后在 index.html 中引入:

复制代码
<script src="/module/playerControl.js"></script>

五、🧠 组件核心代码

复制代码
<template>
  <video
    ref="videoRef"
    @click="fullScreen"
    style="width: 100%; height: 100%; background-color: #000;"
    autoplay
    muted
    playsinline
  ></video>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'

// 接收外部参数
const props = defineProps({
  wsURL: { type: String, default: 'ws://xxxx/rtspoverwebsocket' },
  url: { type: String, default: '' },
  ip: { type: String, required: true },
  channel: { type: Number, required: true },
  username: { type: String, default: 'admin' },
  password: { type: String, default: 'Test.998' },
  proto: { type: String, default: 'Private3' },
  subtype: { type: Number, default: 0 },
  starttime: { type: String, default: '' }, // "2025_11_10_09_00_00"
  endtime: { type: String, default: '' },
})

let player = null
const videoRef = ref(null)

/** 点击视频全屏 */
const fullScreen = (e) => {
  e.target.requestFullscreen()
}

/** 拼接 RTSP URL */
const buildRtspUrl = () => {
  if (props.url) return props.url
  return `rtsp://${props.username}:${props.password}@${props.ip}:554/cam/playback?channel=${props.channel}&subtype=${props.subtype}&starttime=${props.starttime}&endtime=${props.endtime}`
}

/** 初始化播放器 */
const initPlayer = async () => {
  await nextTick()

  if (!window.PlayerControl) {
    console.error('❌ PlayerControl SDK 未加载,请在 index.html 中引入 /module/playerControl.js')
    return
  }

  // 关闭旧实例
  if (player) {
    try {
      player.close()
    } catch (e) {
      console.warn('旧播放器关闭异常:', e)
    }
    player = null
  }

  const rtspURL = buildRtspUrl()
  console.log('🎥 当前播放 URL:', rtspURL)

  const options = {
    wsURL: props.wsURL,
    rtspURL,
    username: props.username,
    password: props.password,
    h265AccelerationEnabled: true,
  }

  player = new window.PlayerControl(options)

  player.on('WorkerReady', () => {
    console.log('✅ Worker 就绪,开始连接视频流...')
    player.connect()
  })

  player.on('Error', (err) => console.error('❌ 播放错误:', err))

  player.init(null, videoRef.value)
}

/** 生命周期挂载 */
onMounted(() => {
  initPlayer()
})

/** 监听参数变化自动重载 */
watch(
  () => [props.url, props.channel, props.starttime, props.endtime, props.subtype],
  async (newVal, oldVal) => {
    if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
      console.log('🔁 播放参数变化,重新加载视频...')
      await initPlayer()
    }
  },
  { deep: true }
)

/** 卸载时清理播放器 */
onBeforeUnmount(() => {
  if (player) {
    player.close()
    player = null
  }
})
</script>

六、💡 使用示例

复制代码
<DahuaPlayer
  :ip="'14.78.1.69'"
  :channel="1"
  :starttime="'2025_11_10_09_00_00'"
  :endtime="'2025_11_10_09_15_00'"
/>

七、🐛 常见问题与排查

问题描述 解决办法
PlayerControl SDK 未加载 检查 index.html 是否引入 /module/playerControl.js
module is not defined SDK 文件不兼容 ESModule,需直接 <script src> 引入而不是 import
播放无画面 检查 rtspoverwebsocket 服务是否启动;确认 URL 正确;确认通道有录像
切换时间段后视频不更新 确保 watch 监听了所有播放相关 props,并重新初始化 player

八、🎯 总结

通过封装此组件,我们实现了:

✅ 支持参数驱动的视频回放组件

✅ 全自动管理播放器生命周期

✅ 代码结构清晰,可复用性高

✅ 易于集成到任何 Vue 项目中

这种封装思路不仅适用于大华回放,也可扩展到海康、宇视等厂商的 Web SDK 播放器。

相关推荐
LSL666_2 小时前
spring多配置文件
java·服务器·前端·spring
万少2 小时前
HarmonyOS preview 预览文件 Kit 的入门讲解
前端
IT_陈寒2 小时前
JavaScript 性能优化实战:我从 V8 源码中学到的 7 个关键技巧
前端·人工智能·后端
jenchoi4133 小时前
软件供应链npm/pypi投毒预警情报【2025-11-09】
前端·安全·web安全·网络安全·npm·node.js
艾小码3 小时前
别再只会用默认插槽了!Vue插槽这些高级用法让你的组件更强大
前端·javascript·vue.js
JaguarJack3 小时前
CSS 也要支持 if 了 !!!CSS if() 函数来了!
前端·css
恋猫de小郭3 小时前
Flutter 3.38 发布,快来看看有什么更新吧
android·前端·flutter
wuk9989 小时前
实现ROS系统的Websocket传输,向Web应用推送sensor_msgs::Image数据
前端·websocket·网络协议
合作小小程序员小小店10 小时前
web网页开发,在线%考试管理%系统,基于Idea,vscode,html,css,vue,java,maven,springboot,mysql
java·前端·系统架构·vue·intellij-idea·springboot