vue3 中播放.flv视频
vue3 中播放.flv视频
方法一:使用flv.js
<template><div class="player-wrap"><video ref="player" :autoplay="autoplay" loop muted></video></div>
</template><script setup lang="ts">
import flvjs from "flv.js";
const emits = defineEmits(["reloadUrl", "loadError"]);
interface Props {videoId: string;videoPath: string;width?: string;height?: string;autoplay: boolean;controls?: boolean;
}
const props = withDefaults(defineProps<Props>(), {videoId: "123",videoPath: "",width: "100%",height: "100%",autoplay: false,controls: false,
});const player = ref();
const flvPlayer = ref();const destroy = () => {if (flvPlayer.value) {flvPlayer.value.pause();flvPlayer.value.unload();flvPlayer.value.detachMediaElement();flvPlayer.value.destroy();flvPlayer.value = null;}
};
// const emits = defineEmits(['player'])
const initPlayer = () => {destroy();if (flvjs.isSupported() && props.videoPath) {const videoElement = player.value;flvPlayer.value = flvjs.createPlayer({type: "flv",url: props.videoPath,hasAudio: false,// cors: true});flvPlayer.value.attachMediaElement(videoElement);flvPlayer.value.load();nextTick(() => {flvPlayer.value.play();});flvPlayer.value.on(flvjs.Events.ERROR, (e, errorData) => {// console.error("视频播放错误", e, errorData);emits("loadError", props.videoId);// 处理错误,比如弹窗提示用户});} else {// console.error("浏览器不支持flv播放");emits("loadError", props.videoId);}
};
onMounted(() => {initPlayer();
});onUnmounted(() => {destroy();
});watch(() => props.videoPath,() => {initPlayer();}
);
</script><style lang="scss" scoped>
.player-wrap {position: relative;width: 100%;height: 100%;border-radius: 4px;.video {// position: absolute !important;width: 100%;height: 100% !important;background: transparent !important;padding-top: 0 !important;border-radius: 4px;}:deep(video) {width: 100%;height: 100%;border-radius: 4px;object-fit: cover;}
}
</style>
方法二、使用jessibuca
1、首先下载jessibuca相关文件,在public文件夹下创建jessibuca文件夹并放置下载的内容
2、代码如下
<template><div class="wsflv-warp" ref="playerContainer"></div>
</template><script setup lang="ts">
import { ref, onMounted, onUnmounted, watch } from "vue";interface Props {videoId: string;videoPath: string;autoplay?: boolean;width?: string;height?: string;
}const props = withDefaults(defineProps<Props>(), {videoId: "0",videoPath: "",autoplay: true,width: "100%",height: "100%",
});const emits = defineEmits(["error", "load", "start"]);
const playerContainer = ref<HTMLDivElement | null>(null);
let player: any = null;/*** 销毁播放器实例*/
const destroy = () => {if (player) {try {player.destroy();player = null;} catch (err) {emits("error", err);}}
};/*** 初始化Jessibuca播放器* @param url 视频流地址*/
const initPlayer = (url: string) => {if (!url || !playerContainer.value) return;try {destroy();// 使用本地的Jessibuca脚本const script = document.createElement("script");script.src = "/jessibuca/jessibuca.js";script.onload = () => {if (typeof window.Jessibuca === "undefined") {emits("error", new Error("Jessibuca加载失败"));return;}player = new window.Jessibuca({container: playerContainer.value,videoBuffer: 0.5, // 500ms缓冲,增加缓冲以减少卡顿decoder: "/jessibuca/decoder.js", // 使用本地解码器useMSE: false, // 不使用MSE,因为MSE不支持H.265useWCS: true, // 尝试使用WebCodecs硬解码isResize: true,text: "视频加载中...",loadingText: "视频加载中...",debug: true, // 开启调试以查看更多信息showBandwidth: true,operateBtns: {fullscreen: true,screenshot: true,play: true,audio: true,record: false,},forceNoOffscreen: false, // 使用离屏渲染以提高性能isFlv: true, // 使用FLV格式hasAudio: true,hasVideo: true,autoWasm: true, // 自动降级到WASM解码openWebglAlignment: true, // 解决某些分辨率下的绿屏问题});// 事件监听player.on("error", (err: any) => {console.error("播放器错误:", err);emits("error", err);});player.on("log", (msg: string) => {console.log("播放器日志:", msg);});player.on("load", () => {console.log("播放器加载完成");emits("load");});player.on("start", () => {console.log("播放器开始播放");emits("start");});player.on("timeout", (e: string) => {console.warn("播放器超时:", e);});player.on("videoInfo", (info: any) => {console.log("视频信息:", info);});player.on("audioInfo", (info: any) => {console.log("音频信息:", info);});// 开始播放player.play(url);};script.onerror = () => {emits("error", new Error("Jessibuca脚本加载失败"));};document.head.appendChild(script);} catch (err) {console.error("初始化播放器失败:", err);emits("error", err);}
};/*** 根据props.videoPath更新视频源*/
const updateVideo = () => {if (props.videoPath) {initPlayer(props.videoPath);}
};onMounted(() => {updateVideo();
});onUnmounted(() => {destroy();
});watch(() => props.videoPath,() => {updateVideo();}
);// 为TypeScript添加Jessibuca类型声明
declare global {interface Window {Jessibuca: any;}
}
</script><style lang="scss" scoped>
.wsflv-warp {position: relative;// 控制Jessibuca内置控制栏的hover效果:deep(canvas) {width: 100% !important;height: 100% !important;transform: none !important; // 移除可能的transform缩放top: 0 !important;left: 0 !important;}:deep(.jessibuca-controls) {opacity: 0 !important;transition: opacity 0.3s ease;position: absolute;bottom: 0;left: 0;right: 0;z-index: 10;}&:hover :deep(.jessibuca-controls) {opacity: 0.9 !important;}
}
</style>
总结
1.使用flv.js
- 通过flvjs.createPlayer创建播放器实例
- 支持自动播放、循环播放等配置
- 包含错误处理、资源销毁等生命周期管理
- 响应式监听视频路径变化
2. 使用Jessibuca
- 需要单独引入jessibuca相关文件
- 提供更丰富的播放控制选项
- 支持多种解码方式(WebCodecs/WASM)
- 包含完整的事件监听系统
- 自动处理分辨率适配问题
两种方法都能有效实现FLV视频播放,flv.js更轻量,Jessibuca功能更全面但需要额外资源。