参考https://www.cnblogs.com/llxpbbs/articles/11623043.html
由于业务需要多路视频播放 http协议目前浏览器限制6条 ;所以需要搞成ws://
新建一个空白的文件夹,执行npm init, 根据提示输入相关信息后,下载node-media-server
npm install node-media-server --save
新建一个入口文件index.js
const NodeMediaServer = require('node-media-server');
const config = {
rtmp: {
port: 1935,
chunk_size: 60000,
gop_cache: true,
ping: 60,
ping_timeout: 30
},
http: {
port: 8000,
allow_origin: '*'
}
};
var nms = new NodeMediaServer(config)
nms.run();
然后在命令行中执行
1
node index.js
2.obs
3.flv.js 视频vue组件
<template>
<div class="video-box">
<video muted autoplay="autoplay" class="video-element" ref="video"></video>
</div>
</template>
<script>
import flvjs from "flv.js";
export default {
name: "c-video-player",
props: {
src: {
type: String,
},
},
data() {
return {
videoType: "", // 视频类型
flvPlayer: null,
videoElement: null,
currentVideoStatu: "play", // 当时视频播放状态
};
},
watch: {
src: {
handler(val) {
this.init(val);
},
deep: true,
},
},
mounted() {
// document.addEventListener('visibilitychange', () => {
// console.log('------------监听到浏览器切换');
// if (!this.src) return;
// this.closeFlvFN();
// this.initVideoFlv();
// });
if (!this.src) return;
this.init(this.src);
},
methods: {
init() {
const regIsVideo = /\.(webm|ogg|flv|mp4)$/i;
this.videoElement = this.$refs.video;
console.log("-------------dd");
this.currentVideoStatu = "play";
this.initVideoFlv();
// if (regIsVideo.test(this.src)) {
// this.videoType = /\.(flv)$/i.test(this.src) ? "flv" : "mp4";
// // this.currentVideoStatu = "play";
// switch (this.videoType) {
// case "flv":
// setTimeout(() => {
// this.initVideoFlv();
// }, 100);
// break;
// case "mp4":
// setTimeout(() => {
// this.initVideoFlv();
// }, 100);
// break;
// }
// } else {
// console.log("请确保您提交的格式是正确的视频格式!");
// }
},
// 初始化Flv视频的方法
async initVideoFlv() {
if (flvjs.isSupported()) {
this.flvPlayer = null;
this.flvPlayer = flvjs.createPlayer(
{
type: "flv",
isLive: false,
cors: true,
url: this.src,
hasAudio: false,
},
{
lazyLoad: false,
autoCleanupSourceBuffer: true,
stashInitialSize: 128,
enableStashBuffer: true,
}
);
this.openFlv();
this.flvPlayer.on("error", (err) => {
// this.$message({
// message: err,
// type: 'fail'
// })
// console.log('--------触发视频流异常');
// this.closeFlvFN();
// this.initVideoFlv();
console.log(err);
});
}
},
// 打开Flv视频的方法
async openFlv() {
this.$nextTick(() => {
this.flvPlayer.attachMediaElement(this.videoElement);
this.flvPlayer.load();
console.log("----------------load");
setTimeout(() => {
// this.flvPlayer.getFeatureList()
console.log("----------------bofang");
this.flvPlayer.play();
console.log("----------------bofang");
this.flvPlayer.on(flvjs.Events.LOADING_COMPLETE, function () {
//断流后做的
console.log(object,"----------------断开");
});
}, 100);
});
},
// 关闭Flv视频的方法
closeFlvFN() {
if (this.flvPlayer) {
this.flvPlayer.pause();
this.flvPlayer.unload();
this.flvPlayer.detachMediaElement();
this.flvPlayer.destroy();
}
},
// 生成截图
screenShotsFn() {
const video = this.$refs.video;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
ctx.drawImage(video, 0, 0);
const a = document.createElement("a");
a.href = canvas.toDataURL("image/png");
a.download = `${Date.now()}`;
a.click();
},
//切换静音状态
mutedFn(type) {
if (type) {
this.flvPlayer.muted = true;
} else {
this.flvPlayer.muted = false;
}
},
},
beforeDestroy() {
this.closeFlvFN();
},
};
</script>
<style lang="scss" scoped>
.video-box {
width: 100%;
height: 100%;
background-color: #333;
position: relative;
color: #fff;
list-style: none;
.right-control {
position: absolute;
right: 0;
top: 0;
width: 100%;
height: 0.4rem;
z-index: 2;
display: flex;
justify-content: flex-end;
background: linear-gradient(to bottom, #000, transparent);
i {
display: inline-block;
width: 0.2rem;
height: 0.2rem;
margin: 0.2rem 0.2rem 0 0;
transition: all 0.5s;
cursor: pointer;
&:hover {
width: 0.25rem;
height: 0.25rem;
margin: 0.17rem 0.17rem 0 0;
}
}
}
}
.video-element {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
</style>
4。
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<input v-model="u" />
<button @click="add">增加</button>
<button @click="reset">重置流地址</button>
<div class="videodList">
<div
style="width: 400px; height: 400px"
v-for="(item, index) in url"
:key="index"
>
<tslVideo :src="item" />
</div>
</div>
</div>
</template>
<script>
import tslVideo from "./tsl-video-player.vue";
export default {
name: "HelloWorld",
props: {
msg: String,
},
data() {
return {
u: "ws://localhost/livetest/hello.flv",
url: ["ws://localhost/livetest/hello.flv"],
};
},
components: {
tslVideo,
},
methods: {
add() {
this.url.push(this.u);
},
reset() {
this.url = ["ws://localhost/livetest/hello.flv"];
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.videodList {
display: flex;
justify-content: space-between;
align-content: space-between;
flex-wrap: wrap;
height: 700px;
overflow-y: auto;
}
</style>