vue3 + video.js 加载多种视频流(HLS、FLV、RTMP、RTSP)封装开箱及用,发布npm

2024-06-04 9586阅读

vue3 + video.js 加载多种视频流(HLS、FLV、RTMP、RTSP)封装开箱及用,发布npm

提示:这里兼容了rtmp数据流,但是前提需要下载支持flash插件的浏览器


文章目录

  • vue3 + video.js 加载多种视频流(HLS、FLV、RTMP、RTSP)封装开箱及用,发布npm
  • 前言
    • 封装组件

      前言

      上一偏我们使用vue3和vite封装了一个audio插件发布npm官网,这里我们将封装一个视频video插件并发布npm供大家参考


      提示:下面不涉及新建项目和打包npm流程,需要的请看上一篇

      vue3 + vite自定义封装vue+audio ,并发布到npm详情介绍

      封装组件

      一. 用video.js实现视频播放

      1. 安装video.js插件,这里我们使用的是在index.html中引入的本地css
           //引入video插件
         
         
         //如果需要播放rtmp直播流,需安装一下插件
         
         //引入键盘控制video插件
         
        
        1. 在组件代码里使用
           
                

      不支持播放

      video的class “vjs-big-play-centered” 播放按钮默认在左上角,会遮挡,不过这个是可以根据参数修改的,只需要给video标签加一个class(vjs-big-play-centered)就可以居中显示了

      1. 定义常用video.js 配置项
      • autoplay:true/false 播放器准备好之后,是否自动播放 【默认false】
      • controls:true/false 是否拥有控制条 【默认true】,如果设为false, 界面上不会出现任何控制按钮,启动视频播放的唯一方法是使用autoplay 属性或通过Player API
      • height: 视频容器的高度,字符串或数字(以像素为单位),比如: height: 300 或者 height: ‘300px’
      • width: 视频容器的宽度, 字符串或数字(以像素为单位)
      • loop : true/false 视频播放结束后,是否循环播放
      • muted : true/false 是否静音
      • poster: 播放前显示的视频画面,播放开始之后自动移除。通常传入一个URL
      • language: “zh-CN”
      • errorDisplay :是否显示错误提示
      • fluid : 跟随外层容器变化大小,跟随的是外层宽度
      • controlBar: 是否显示控制条,设为false不渲染控制条DOM元素,只设置controls为false虽然不展示,但是存在
      • notSupportedMessage :允许覆盖Video.js无法播放媒体源时显示的默认信息
      • techOrder:定义Video.js技术首选的顺序 [‘html5’, ‘flash’]
      • plugins:放插件的地方是否支持热键
        • hotkeys:过键盘按键来控制视频播放的功能
          • volumeStep: 0.1 调整音量的步长
          • seekStep: 5, 快进/快退的时间(秒)
          • fullscreenKey:(event, player)=>{} 监听键盘按键
          • preload: 预加载
            • ‘auto’:立即开始加载视频(如果浏览器支持)。某些移动设备不会预加载视频,以保护用户的带宽/数据使用。
            • ‘metadata’:仅加载视频的元数据,其中包括视频的持续时间和尺寸等信息。有时,元数据将通过下载几帧视频来加载。
            • ‘none’:不要预加载任何数据。浏览器将等待用户点击“播放”开始下载。
            • children: Array | Object 可选子组件 从基础的Component组件继承而来的子组件,数组中的顺序将影响组件的创建顺序

              这里我们设置一个变量储存videojs使用的配置项以便后期批量使用

              const videoParameter = ref({
                autoplay: isautoplays.value, // 是否自动播放
                language: "zh-CN",
                controls: iscontrols.value, // 是否显示控制为false时用户不可以与之交互控件
                preload: "auto", // 自动加载 预加载 建议浏览器是否应在加载元素后立即开始下载视频数据。
                errorDisplay: true,// 错误展示
                fluid: true, // 跟随外层容器变化大小,跟随的是外层宽度
                controlBar: iscontrolBar.value,
                // textTrackDisplay: false,  // 不渲染字幕相关DOM
                // 是否支持热键|过键盘按键来控制视频播放的功能
                plugins: {
                 //这里需要引入本地插件videojs.hotkeys.min.js,这里我引入了v0.2.13版本,因为其他版本有线上依赖项
                  hotkeys: {
                    // 定义快捷键和对应的操作
                    volumeStep: 0.1,  // 调整音量的步长
                    seekStep: 5,      // 快进/快退的时间(秒)
                    fullscreenKey: function (event, player) {
                      // 自定义全屏快捷键,按下 F 键时触发全屏切换
                      if (!document.fullscreenElement) {
                        player.requestFullscreen();
                      } else {
                        document.exitFullscreen();
                      }
                    }
                  }
                },
                notSupportedMessage: '此视频暂无法播放,请稍后再试', //允许覆盖Video.js无法播放媒体源时显示的默认信息
                techOrder: PlayOrder.value, // 定义Video.js技术首选的顺序
                //自动播放属性,muted:静音播放
                muted: true,
              })
              
              1. 这里我们就开始初始化video,这里还做了监听error并做出处理重新加载,里面还控制了是否禁用键盘事件,播放rtmp时我把键盘和暂停/播放/快进等禁用了,这里是因为在播放rtmp直播流时这些暂停RTMP直播后,VideoJS无法播放,大家有什么好的解决办法欢迎来共商大计♡
              //初始化视频
              const showvideo = (val, url) => {
                nextTick(() => {
                //这里是因为要支持rtmp需要使用flash
                //因为,这种播放方式html已经不能很好的进行播放了,需要用到flash来播放,videojs在这个地方就用到了这个。代码就是下面这样。
                  videojs.options.flash.swf = 'public/static/js/video-js.swf';
                  player.value = videojs(
                    "myVideoBig",
                    videoParameter.value,
                    function () {
                      videojs.log('播放量+1!'); // 比如: 播放量+1请求
                      player.value.on('ended', function () {
                        videojs.log('Awww...这么快就结束了?!');
                      });
                      //监听error在页面插入一个重播按钮
                      player.value.on("error", function () {
                        var errorMessage = player.value.error().message;
                        console.log('Video.js 播放器遇到错误:', errorMessage);
                        var myVideoDivles = document.querySelectorAll("#myVideoBig");
                        if (myVideoDivles.length == 0) return
                        myVideoDivles[0].innerHTML = ``;
                        // 获取按钮元素并添加事件
                        RefreshButton.value = document.querySelector('.Refresh');
                        RefreshButton.value.addEventListener('click', function (event) {
                          clickRefresh()
                        });
                        return ElMessage({
                          message: "视频播放失败,请检查并刷新",
                          type: "warning",
                          duration: 5000,
                          offset: 80,
                        });
                      });
                    }
                  );
                  videojs("myVideoBig").src({
                    type: format.value,
                    src: url,
                  });
                  // 禁用键盘事件
                  if (val == 1) {
                    disableKeyboardControl(player.value)
                  }
                });
              }
              

              初始化的时候插入了一个重播按钮需要初始化video,上代码

              //刷新视频
              const clickRefresh = async (val) => {
                var myVideoDivles = document.querySelectorAll("#myVideoBig");
                if (myVideoDivles.length == 0) return
                myVideoDivles[0].innerHTML =
                  "";
                nextTick(() => {
                  playerolder.value = videojs("myVideoBigs", videoParameter.value, function () {
                    playerolder.value.on("error", function () {
                      var myVideoDivles = document.querySelectorAll("#myVideoBig");
                      if (myVideoDivles.length == 0) return
                      myVideoDivles[0].innerHTML = ``;
                      // 获取按钮元素
                      RefreshButton.value = document.querySelector('.Refresh');
                      RefreshButton.value.addEventListener('click', function (event) {
                        clickRefresh()
                      });
                      return ElMessage({
                        message: "视频播放失败,请检查并刷新",
                        type: "warning",
                        duration: 5000,
                        offset: 80,
                      });
                    });
                  });
                  videojs("myVideoBigs").src({
                    type: format.value,
                    src: props.videoSrc,
                  });
                  //videojs("myVideoBigs").play();
                }, 100);
              }
              

              这样就可以刷新重新播放☝

              1. 处理rtmp

                代码中需要同时支持MP4,m3u8和rtmp,所以要做一些处理

              //初始化监听vieo的src是什么格式做处理
              watch(() => props.videoSrc, (newVal, oldVal) => {
                if (newVal) {
                  console.log(newVal)
                  if (newVal.includes('rtmp')) {
                    videoParameter.value.controls = false
                    videoParameter.value.controlBar = false
                    videoParameter.value.autoplay = true
                    //以flash为先
                    videoParameter.value.techOrder = ['flash', 'html5']
                    isautoplays.value = true
                    iscontrols.value = false
                    iscontrolBar.value = false
                    PlayOrder.value = ['flash', 'html5']
                   //修改格式
                    format.value = 'rtmp/flv'
                    showvideo(1, newVal)
                  } else if (newVal.includes('.mp4')) {
                    format.value = 'video/mp4'
                    currency(newVal)
                  } else if (newVal.includes('.m3u8')) {
                    format.value = 'application/x-mpegURL'
                    currency(newVal)
                  }
                }
              }, { deep: true, immediate: true });
              
              //通用
              const currency = (newVal) => {
                videoParameter.value.controls = true
                videoParameter.value.controlBar = true
                videoParameter.value.autoplay = props.isautoplay
                videoParameter.value.techOrder = ['html5', 'flash']
                isautoplays.value = props.isautoplay
                iscontrols.value = true
                iscontrolBar.value = true
                PlayOrder.value = ['html5', 'flash']
                showvideo(2, newVal)
              }
              

              ★★★★★★提示一下rtmp格式需要支持flash的浏览器

              谷歌,360,火狐,qq浏览器都是不支持的

              vue3 + video.js 加载多种视频流(HLS、FLV、RTMP、RTSP)封装开箱及用,发布npm 第1张

              vue3 + video.js 加载多种视频流(HLS、FLV、RTMP、RTSP)封装开箱及用,发布npm 第2张

              只有falsh官网的浏览器所支持

              vue3 + video.js 加载多种视频流(HLS、FLV、RTMP、RTSP)封装开箱及用,发布npm 第3张

              1. 常用事件
              • 播放 this.play()
              • 停止 – video没有stop方法,可以用pause 暂停获得同样的效果
              • 暂停 this.pause()
              • 销毁 this.dispose()
              • 监听 this.on(‘click‘,fn)
              • 触发事件this.trigger(‘dispose‘)

                这里我还做了一个销毁参数closeVideo传值true,做了两个销毁,第一次判断是否有重播时的渲染,第二个销毁初始化的video

                watch(() => props.closeVideo, (newVal, oldVal) => {
                  if (newVal) {
                    handleLog()
                  }
                }, {
                  deep: true, immediate: true
                })
                //关闭销毁vieobox
                const handleLog = () => {
                  var myVideoDivles = document.querySelectorAll("#myVideoBigs");
                  if (myVideoDivles.length > 0) {
                    playerolder.value.dispose();
                    playerolder.value = null;
                  }
                  player.value.dispose();
                  player.value = null;
                }
                

                video.min.js:18 VIDEOJS: ERROR: (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) No compatible source was found for this media.

                报错是因为所加载的url不支持

                1. 测试地址

                https://sdk-release.qnsdk.com/VID_20220207_144828.mp4

                rtmp://liteavapp.qcloud.com/live/liteavdemoplayerstreamid

                http://cdn3.toronto360.tv:8081/toronto360/hd/playlist.m3u8

                //失败测试

                https://sdk-release.qnsdk.com/1080_60_5390.mp4

                1. 插件参数
                videoSrcvideo 的 url
                isautoplay是否自动播放,默认false,rtmp格式强制true
                posterSrc播放前的图片展示
                closeVideo是否销毁vido ,默认false

                好啦啦啦!!!这里我们就完成了代码部分直接npm publish发布☺☺

                请下载使用吧,有什么问题或者有更好的可以联系我哦,谢谢大家☺☺

                npm i l-vue3-video

                源码


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]