[2023年11月27日20:31:09]
记一次业务监控流flv播放的封装
vue3封装flvjs,用于监控流。包括:判断可播放、推流、停流、播放、销毁功能。
/** useRender.ts */
import flvjs from "flv.js";
import type FlvJs from "flv.js";
const host = import.meta.env.VITE_APP_BASE_API;
let player: Flvjs.Player | undefined;
let timer: number | undefined;
/**
* 判断是否可用flv
* @returns
*/
function canUseFlv(): boolean {
return flvjs.isSupported();
}
/**
* 初始化
* @param camereInfo
* @param videoElement
*/
function _init(camereInfo: any, videoElement: HTMLVideoElement) {
play(camereInfo, videoElement);
}
/**
* 销毁
* @param flvPlayer
* @returns
*/
function destroyPlayer(flvPlayer: FlvJs.Player | undefined) {
if (!flvPlayer) return;
flvPlayer?.pause();
flvPlayer?.unload();
flvPlayer?.detachMediaElement();
flvPlayer?.destroy();
flvPlayer = undefined;
}
/**
* 补帧追帧
* @param flvPlayer
* @param videoElement
*/
function increaseFrame(
flvPlayer: FlvJs.Player,
videoElement: HTMLVideoElement
) {
let end = flvPlayer.buffered.end(0);
let delta = end - flvPlayer.currentTime;
if (delta > 10 || delta < 0) {
flvPlayer.currentTime = flvPlayer.buffered.end(0) - 1;
} else if (delta > 1) {
videoElement.playbackRate = 1.1;
} else {
videoElement.playbackRate = 1;
}
}
/**
* 播放
* @param cameraInfo
* @param videoElement
*/
function play(cameraInfo: any, videoElement: HTMLVideoElement) {
let flvPlayer = flvjs.createPlayer(
{
type: "flv",
isLive: true,
hasAudio: false,
url: cameraInfo.streamAddress,
},
{
enableStashBuffer: false,
stashInitialSize: 128,
}
);
flvPlayer.mediaElement = videoElement
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
player = flvPlayer;
flvPlayer.on(flvjs.Events.METADATA_ARRIVED, function () {
console.log("获取视频流...");
/** 监听进度补追帧 */
videoElement.addEventListener("progress", function () {
try {
increaseFrame(flvPlayer, videoElement);
} catch {};
});
/** 监听重回浏览器画面触发补追帧 */
videoElement.addEventListener("visibilitychange", function () {
try {
increaseFrame(flvPlayer, videoElement);
} catch {};
});
flvPlayer.play();
});
/** 断流重连 */
flvPlayer.on(
flvjs.Events.ERROR,
function (errorType: FlvJs.ErrorTypes, errorDetails: FlvJs.ErrorDetails) {
if(timer) return;
timer = window.setTimeout(() => {
console.log("播放时发生了一个错误");
videoElement.removeEventListener("progress", function () {
increaseFrame(flvPlayer, videoElement);
});
videoElement.removeEventListener("visibilitychange", function () {
increaseFrame(flvPlayer, videoElement);
});
if(player) player = undefined;
destroyPlayer(flvPlayer);
_init(cameraInfo, videoElement);
clearTimeout(timer);
timer = undefined;
}, 3000);
}
);
}
function killPlayer() {
if (!player) return;
player.mediaElement.removeEventListener("progress", function () {
increaseFrame(player, player.mediaElement);
})
player.mediaElement.removeEventListener("visibilitychange", function () {
increaseFrame(player, player.mediaElement);
})
player?.pause();
player?.unload();
player?.detachMediaElement();
player?.destroy();
player = undefined;
clearTimeout(timer);
timer = undefined;
}
/**
* 开始推流
* @param cameraInfo
*/
async function startPush(cameraInfo: any) {
await fetch(host + "/api/Device/Camera/PushCamera", {
method: "POST",
headers: new Headers({
"Content-Type": "application/json",
"Authorization": userStore.token
} as HeadersInit),
body: JSON.stringify([
{
bizType: "HKMQTT",
id: cameraInfo.id,
cameraName: cameraInfo.cameraName,
rtspPath: cameraInfo.rtspPath,
rtmpPath: cameraInfo.rtmpPath,
streamAddress: cameraInfo.streamAddress,
no: cameraInfo.no
}
]),
})
}
/**
* 停止推流
* @param cameraInfo
*/
async function stopPush(cameraInfo: any) {
await fetch(host + "/api/Device/Camera/StopCamera", {
method: "POST",
headers: new Headers({
"Content-Type": "application/json",
"Authorization": userStore.token
} as HeadersInit),
body: JSON.stringify([
{
bizType: "HKMQTT",
id: cameraInfo.id,
cameraName: cameraInfo.cameraName,
rtspPath: cameraInfo.rtspPath,
rtmpPath: cameraInfo.rtmpPath,
streamAddress: cameraInfo.streamAddress,
no: cameraInfo.no
}
]),
});
}
export default function useRender() {
return {
startPush,
stopPush,
play,
killPlayer,
canUseFlv
};
}
标签:function,播放,封装,flvPlayer,param,flv,player,cameraInfo,videoElement
From: https://www.cnblogs.com/lastkiss/p/17860390.html