实现videojs接入m3u8视频,踩了多少坑啊
实现vue3通过videojs接入m3u8视频,一天多总算搞成功了。下面就扒一扒我在实现过程中踩的那些坑。。。。。。
前言
我们最常见的mp4类型的视频,直接通过vue原生的video引入就可以了。
<video :src="video" autoPlay controls muted loop />
但是当接入的视频是直播视频流时,video是不支持的,所以我们需要通过一定的插件辅助,在实现功能前先介绍几个概念。
1.HLS,M3U8
一听需求是要接入海康的视频,什么hls,m3u8视频,孤陋寡闻的我立马去找度娘。
HLS是一个基于http的流媒体网络传输协议,传输内容包括两部分,M3U8描述文件和TS媒体文件。
M3U8文件是指UTF-8编码格式的M3U文件。M3U文件是一个文本文件,记录视频文件的索引。
概括说,hls协议将流媒体切片成的ts文件和m3u8文件,通过m3u8索引文件按序访问ts文件,客户端不停地从服务器获取视频文件,进而实现在线播放音视频的功能。
本文是通过videojs插件来实现视频接入的。
功能实现
1.安装依赖和引入
npm install --save video.js
npm install --save videojs-contrib-hls
在index.html引入
<!-- 视频取流 --><link href="https://cdn.bootcss.com/video.js/7.20.3/alt/video-js-cdn.min.css" rel="stylesheet"><script src="https://cdn.bootcss.com/video.js/7.20.3/video.js"></script><script src="https://cdn.bootcss.com/videojs-contrib-hls/5.15.0/videojs-contrib-hls.min.js"></script>
注:这里是第一个坑,看了很多方法都是直接安装依赖就可以,没有这一步。但是,如果不引入请求是成功的,但是视频却加载不出来。
加上后就能正常显示了
文件内局部引入
import videojs from 'video.js';
import 'videojs-contrib-hls';
import 'video.js/dist/video-js.css';
2.代码实现
template代码
<div id="video-box" class="video-item" v-show="showFlag"><videoid="my-video"class="video-js vjs-default-skin"controlspreload="auto"style="width: 100%;height:100%"><source id="source" :src="xxxx视频请求网址xxxx" type="application/x-mpegURL" /></video></div>
初始化
const myPlayer = ref(null);
const initVideo = () => {
//初始化配置myPlayer.value = videojs('my-video',{bigPlayButton: false,textTrackDisplay: false,posterImage: true,errorDisplay: false,controlBar: true,});// 播放myPlayer.value.play();
};onMounted(() => {setTimeout(() => {initVideo();}, 300);
});
注:第二个坑来了!当视频组件放到弹窗里,如果报错
TypeError: The element or ID supplied is not valid. (videojs)
这时就需要注意两点:
- 组件外层的div不能使用v-if,要使用v-show控制显隐
- videojs的初始化要在dom全部挂载后的,所以可以采用使用setTimeout延迟加载
以上是固定地址的写法,但是需求是要切换不同视频地址来源,还需要进一步优化
先将视频地址设为变量
<source id="source" :src="cameraURL" type="application/x-mpegURL" />const srcPath = ref<string>('');const initVideo = (url:string) => {myPlayer.value = videojs('my-video',{bigPlayButton: false,textTrackDisplay: false,posterImage: true,errorDisplay: false,controlBar: true,});// 设置urlmyPlayer.value.src(url);myPlayer.value.play();
};
注:第三个坑来了!在网上学习的过程中有些是下面这种写法,直接赋值属性值并且不在template里写source部分。我开始用这种方法,发现怎么都不生效。最后换成了上面的写法。(如果有大神知道原因还请指教)
myPlayer.src([{type: "application/x-mpegURL",src: url }]);
注:紧接着问题又来了,切换url后视频加载不出来,查看网络发现切换url后的第一个请求会显示已取消
解决方法是将这条请求过滤
videojs.hook('beforeerror', (player, err) => {// Video.js 在切换/指定 source 后立即会触发一个 err=null 的错误,这里过滤一下if (err !== null) {myPlayer.value.src(url);}// 清除错误,避免 error 事件在控制台抛出错误return null;});
请求都正常发现视频还是加载不出来,还会报错
解决办法:只能在切换来源的时候销毁原来的组件,再重新添加一个videojs并赋值。
补充:控制台报错但不影响视频正常显示。原因:video.js and videojs-contrib-hls版本冲突,解决:将videojs版本从7.20.3降为videojs 7.5.5\videojs-contrib-hls 5.15.0,无报错。
最后附上成功实现的完整代码
template部分
<template><div id="video-box" class="video-item" v-show="showVideo"></div>
</template>
Js部分
const myPlayer = ref<any>(null);
const mountedFlag = ref<boolean>(false);
// 初始化视频组件
const initVideo = (url:string) => {if (myPlayer.value) {myPlayer.value.pause();myPlayer.value.dispose();}// 向Dom中写入视频组件document.getElementById('video-box').innerHTML = '';const html = `<video id="fire-video" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" style="width: 100%;height:100%"><source id="source" src="${url}" type="application/x-mpegURL"></video>`;document.getElementById('video-box').innerHTML = html;// 初始化声明myPlayer.value = videojs('fire-video',{autoplay: 'muted',bigPlayButton: false,textTrackDisplay: false,posterImage: true,errorDisplay: false,controlBar: true,});videojs.hook('beforeerror', (player, err) => {// Video.js 在切换/指定 source 后立即会触发一个 err=null 的错误,这里过滤一下if (err !== null) {myPlayer.value.src(url);}// 清除错误,避免 error 事件在控制台抛出错误return null;});myPlayer.value.play();
};// 监听,需要视频url由其他方法赋值且组件挂载完成后,才能进行初始化
watch([cameraURL,mountedFlag,], ([url,flag,]): void => {if (url && flag) {initVideo(url);}
});onMounted(() => {setTimeout(() => {mountedFlag.value = true;}, 500);
});
// 组件销毁
onUnmounted(() => {if (myPlayer.value) {mountedFlag.value = false;}
});
参考文档:
https://cloud.tencent.com/developer/article/1782402
https://blog.csdn.net/u012961419/article/details/120989905
实现videojs接入m3u8视频,踩了多少坑啊相关推荐
- 使用videojs播放m3u8视频
vue3使用videojs 播放m3u8格式视频 videojs是一个播放视频的js库,可以通过videojs结合videojs-contrib-hls实播放m3u8格式视频.流媒体传输协议(hls) ...
- 使用videojs播放m3u8视频监控。
一 . 实现过程中解决的问题 : 1. 全屏播放 2.切换页面后进入视频无法再次播放,解决方法利用生命周期函数beforeDestroy或onUnload里面销毁创建的video实例. 二.主要代码: ...
- android xlog崩溃日志,腾讯Xlog接入指南与踩过的坑
一 为什么要接入日志打印系统? 相信大家在开发应用的时候,总会遇到bug,这个时候,如果bug是在我们本地开发的过程中发现的,那么我们把手机插入android studio进行联调,就可以马上定位到出 ...
- videojs播放m3u8后缀视频Demo
videojs播放m3u8后缀视频Demo 转载自:https://segmentfault.com/a/1190000024447688 <!DOCTYPE html><html ...
- vue关于videojs一个页面多个视频且一个播放器多个视频源的写法(播放m3u8视频格式的视频监控)
前言 突然接到一个任务是需要做一个视频回放,而且是监控视频那种. 1.首先需要能播m3u8视频 npm install --save video.js npm install --save video ...
- vue使用原生videojs 播放m3u8格式的视频——播放m3u8格式视频(一)
vue使用原生video播放m3u8格式的视频 1.安装依赖 2.页面引入插件(这里我是页面单独引入,减少项目体积) 3.页面中的使用 常见问题 4.实现过程 5.实现.m3u8格式视频播放方法 1. ...
- Linux视频切片m3u8,Rtmp转m3u8视频切片系统及方法
Rtmp转m3u8视频切片系统及方法 [技术领域] [0001]本发明涉及视频数据传输及播放技术领域,尤其涉及一种RTMP转M3U8视频切片系统及方法. [背景技术] [0002]传统的视频监控系统是 ...
- video.js播放m3u8视频
m3u8 是一种基于HTTP Live Streaming(HLS)文件视频格式,它主要是存放整个视频的基本信息和分片(Segment)组成.目前 由 Apple.inc 率先提出的 HLS 协议在 ...
- 前端展示m3u8视频
什么是m3u8视频? m3u8是苹果公司推出的视频播放标准,是m3u的一种,只是编码格式采用的是UTF-8. 在vue框架项目中如何使用? (将 展示m3u8视频的功能做成组件) 引入video.j ...
最新文章
- python读文件的解码方式_跳过Python文件读取中的不可解码字符
- python使用matplotlib可视化、使用subplots函数将可视化的画布划分为网格状的若干子区、通过nrows和ncols参数设置设置行数和列数
- 如何及时获得AI顶尖科研团队的最新论文与进展?只需要一份AI内参!
- SpringBoot集成Eureka导致返回结果由json变为xml解决方案
- 【拔刀吧少年】之正则表达式
- hashCode()方法的性能优化
- CF Gym102059 H. Fractions
- java cxf实现webservice接口方式之不依赖spring
- 图论 —— 最短路 —— Floyd 算法
- 一起学习C语言:C语言循环结构(二)
- android activity 窗口 样式
- charles抓手机app的包的操作步骤
- 4-0 Software Development OKR
- 工具系列————linux系统中安装fortran编译器(ifort)
- 网站上部署Live2D模型(moc3格式)
- Gliffy confluence插件的破解
- 订单系统设计,消息队列幂等处理思路
- android 读取wps_Android 默认使用wps打开本地文档
- 用于单眼3D物体检测的可学习深度引导卷积
- SQL数据库常用语句大全