vue3播放rtsp流需要配合后端转码,一般是转成flv格式后,传回前端播放;但是找到了一个更简单的方法,使用一个大神写的EasyMedia,它将前后端写好一起打包成了一个jar包,运行jar包,vue3中利用xgplayer播放就行;
但是使用的时候遇到很多坑,可能是我使用的是vue3+ts的缘故,这里就写一下vue3+ts中如何使用;
教程来源:EasyMedia播放rtsp视频流(vue2、vue3皆可用)
EasyMedia jar包下载(1.2版本):链接:https://pan.baidu.com/s/1BjLz7AQT5A__h-wlewQpYg?pwd=e19b 提取码:e19b
1、运行EasyMedia
下载好EasyMedia的jar包好,随便置于一个位置,进入jar所在文件夹,启动cmd,通过命令java -jar EasyMedia-1.2.0.jar
运行jar包,可以先通过:localhost:8888
看看是否运行成功,并测试一个rtsp流
2、vue界面使用
1)安装西瓜播放器插件
package.json中在dependencies
下添加以下依赖:
"xgplayer": "^2.18.2",
"xgplayer-flv.js": "^2.2.1"
//添加后执行安装命令
npm install
2)界面使用
在需要使用的界面加入以下代码:
rtspPlayer.vue
<template>
<div>
<div style="height: 100%;width: 100%;display: flex;align-items: center;justify-content: center;">
<div class="video" v-show="isPlay" :id="elId"></div>
<div v-show="!isPlay" style="color: #08979C;font-size: 25px;">暂无视频源</div>
</div>//这一部分可以放入需要放入的组件之中
<el-button @click="playRTSP(playUrl)">播放</el-button>
</div>
</template>
<script setup lang="ts">
import FlvJsPlayer from 'xgplayer-flv.js';//因为这个没有ts版本,只有js; 在shim-vue.d.ts,中加上declare module 'xgplayer-flv.js';
import Player from 'xgplayer';
import { guid } from '@/util'; //生成唯一id的,代码在下面
const isPlay = ref(false)
const player = ref<any>({})
const elId = guid()
const visibilitychange = onMounted(() => {
console.log('computed执行');
document.addEventListener('visibilitychange', function () {
// console.log(document.visibilityState);
// console.log(document.hidden);
if (document.hidden) {
console.log("页面隐藏")
}
});
})
//绑定url,播放
const playRTSP(url:string){
createPlayer(url,true,0)
}
const createPlayer = (url: string, hasCloseBtn: boolean, index: number) => {
console.log(url);
console.log(hasCloseBtn);
console.log(index);
if (!url) {
return;
}
// if (player) {
// changeVideo(url);
// return;
// }
isPlay.value = true;
player.value = new FlvJsPlayer({
id: elId,
url: url,
// fitVideoSize: 'auto',
fluid: true,
autoplay: true,
isLive: true,
playsinline: false,
screenShot: true,
whitelist: [''],
ignores: ['time'],
closeVideoClick: true,
// errorTips: '<span class="app-error">无视频源</span>',
customConfig: {
isClickPlayBack: false
},
flvOptionalConfig: {
enableWorker: true,
enableStashBuffer: true, //启用缓存
stashInitialSize: 4096, //缓存大小4m
lazyLoad: false,
lazyLoadMaxDuration: 40 * 60,
autoCleanupSourceBuffer: true,
autoCleanupMaxBackwardDuration: 35 * 60,
autoCleanupMinBackwardDuration: 30 * 60
} //flv.js可选配置项 [flv.js配置](https://github.com/bilibili/flv.js/blob/master/docs/api.md#config)
});
// 自定义播放器按钮
// let divStr =
// '<i class="btn-hover el-icon-camera button-screen-shot" style="font-size: 23px;margin-right: 10px;pointer-events: auto;"></i>' +
// '<i class="btn-hover el-icon-s-tools button-set" style="font-size: 23px;margin-right: 10px;pointer-events: auto;"></i>' +
// '<i class="btn-hover el-icon-video-camera-solid button-history" style="font-size: 23px;margin-right: 10px;pointer-events: auto;"></i>';
let divStr = '<i class="btn-hover el-icon-d-arrow-left button-playback" style="font-size: 23px;pointer-events: auto;"></i>';
let divClose = '<i @click="closePlayer" class="btn-hover el-icon-close app-close-btn-c"></i>';
let util = Player.util;
// let customBtn = util.createDom('div', divStr, {}, 'flex align-center justify-center app-player-button'); //'div', divStr, {}, 'class'
let customBtn = util.createDom(
'div',
divStr,
{ style: 'width: 40px;heigth:40px;position: absolute;right: 155px;top: 7px;' },
'flex align-center justify-center app-player-button'
); //'div', divStr, {}, 'class'
let closeBtn = util.createDom('div', divClose, {}, 'app-close-btn');
let xgControls = player.root.querySelector('xg-controls');
let xgError = player.root.querySelector('xg-error');
xgControls.appendChild(customBtn);
player.root.appendChild(closeBtn);
// let shot = customBtn.querySelector('.button-screen-shot');
// let set = customBtn.querySelector('.button-set');
// let history = customBtn.querySelector('.button-history');
let closeBtnc = closeBtn.querySelector('.app-close-btn-c');
let playback = customBtn.querySelector('.button-playback');
player.on('play', () => { });
player.on('focus', () => {
if (hasCloseBtn) {
closeBtn.style.display = 'block';
}
});
player.on('ended', () => { });
player.on('blur', () => {
closeBtn.style.display = 'none';
});
player.on('error', () => { });
if (closeBtnc) {
closeBtnc.addEventListener('click', () => {
closePlayer();
});
}
// 点击视频时间,设置selectIndex
// player.video.addEventListener('click', () => {
// $emit('clickPlayer', index);
// });
}
const changeVideo = (url: string) => {
player.src = url;
}
const closePlayer = () => {
isPlay.value = false;
if (player) {
player.value.destroy();
}
}
const playObjDestroy = () => {
if (player) {
player.value.destroy();
}
console.log('销毁了');
}
defineExpose({
createPlayer,
playObjDestroy
})
</script>
util.ts
const S4 = function() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
};
export function guid() {
return (S4() + S4() +'-' +S4() +'-' +S4() +'-' +S4() +'-' +S4() +S4() +S4()
);
}
传入正常的rtsp流就可以播放
3)注意事项
(1)切换rtsp流,需要使用上述代码中的
changeVideo (url: string)
方法,才能切换,切勿重复调用createPlayer
方法;(2)播放的div放入Dialog弹出的模态框与Drawer抽屉中,不能立即加载播放,不然会报错;可以防止一个点击按钮,手动点击播放;