基于 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
视频 SDK:
PlayerControl.js(大华 Web 播放控制 SDK)传输协议:RTSP over WebSocket
播放场景:录像回放(带时间段参数)
三、⚙️ 组件设计思路
我们封装一个通用的 <DahuaPlayer /> 组件,具备以下特性:
✅ 支持实时与回放播放模式
✅ 参数变化(通道号、时间、URL)自动重载
✅ 自动关闭旧实例,防止内存泄漏
✅ 支持一键全屏
✅ 完整错误提示与日志输出
四、📦 PlayerControl SDK 引入
首先在 public/module/ 目录下放置 Dahua 提供的 playerControl.js,
然后在 index.html 中引入:
<script src="/module/playerControl.js"></script>
五、🧠 组件核心代码
<template><videoref="videoRef"@click="fullScreen"style="width: 100%; height: 100%; background-color: #000;"autoplaymutedplaysinline></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.urlreturn `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 播放器。
