如何手动停止 videojs 直播视频流 m3u8 请求?

简介: 在可视化大屏项目中,多个VideoJS组件播放m3u8流时,即使暂停仍持续请求,导致页面卡顿。通过监听display属性,结合`dispose()`销毁实例并重建同ID的video DOM元素,有效释放资源且保留组件结构,解决性能问题,提升用户体验。

问题描述

在公司某个可视化大屏项目中,大屏页面会有多个 videojs 组件,每个组件都会对应一个视频流地址。每当视频开始播放,视频流m3u8 会不断请求,即便是暂停了播放,这个请求也不会终止。大量的请求会导致页面卡顿,长此以往会带来性能问题,导致浏览器卡死甚至崩溃。

而大屏操作中,经常会用到组件联动,点击百度地图的点位,出现一个视频弹窗,点击关闭视频,其实是隐藏了视频,而视频的请求还在继续。为了解决这个问题,我花了一些时间研究,找到了解决办法。

解决办法

从videojs官方文档可以查到,有一个 dispose 方法。这个方法是用来销毁 videojs 对象的。但这个方法不能直接使用,直接使用会导致一个新的问题,那就是销毁实例后 ,原本的 video 标签dom 元素也一并销毁了,这个特性从官方文档中可以看出。

Videojs Removing Players

请在此添加图片描述

其实我个人觉得,这个方法的操作 2 的特性非常不好,这样导致关闭后组件直接被销毁,导致下次触发视频弹窗(业务需求是点击百度地图图例,出现弹窗播放视频直播流),没有视频组件可以显示播放。

于是我针对这个项目组件,写了一个 Vue 的watch,用来监听监听 display 属性。在这个项目中,这个属性每个组件都有,display 为 false 是显示,true 是隐藏(别问为什么是反的,我也不知道)。代码示例如下:

<template>
  <div :style="styleObject" ref="myvideojs">
    <!-- <video
      :id="videojsId"
      class="video-js vjs-big-play-centered vjs-fluid"
      style="width: 100%; height: 100%; object-fit: fill"
    ></video> -->
    <!-- padding-top: 0,解决减小高度到一定数值后,高度不能自适应的问题 -->
    <video :id="videojsId" class="video-js vjs-big-play-centered vjs-fluid" style="width: 100%; height: 100%; object-fit: fill; padding-top: 0" ref="videoPlayer"></video>
  </div>
</template>
 watch: {
    ...
    display: {
      handler(newVal) {
        // true 代表隐藏
        if (newVal) {
          console.log("隐藏 :>> ")
          if (this.myVideo) {
            this.$nextTick(() => {
              // 必须先暂停,后销毁,销毁后 dom 元素也会被移除,所以需要手动添加相同 id 的 dom
              this.myVideo.dispose()
              // 下面这个 dom 跟 video 标签属性一致
              const videoElement = document.createElement("video")
              videoElement.setAttribute("id", this.videojsId) //注意 id 要一致
              videoElement.setAttribute("class", "video-js vjs-big-play-centered vjs-fluid")
              videoElement.setAttribute("style", "width: 100%; height: 100%; object-fit: fill; padding-top: 0")
              videoElement.setAttribute("ref", "videoPlayer")
              this.$refs.myvideojs.appendChild(videoElement) //添加相同 DOM
              this.myVideo = null
            })
          }
        } else {
          console.log("显示 :>> ")
        }
      },
    },
  }

下面是绘制组件的方法:

methods: {
    // 绘制方法
    drawChar(result) {
      let that = this
      if (result.length > 1) {
        console.log(this.MapPoiChange)
        console.log(this.option.Playtype)
        let key = this.MapPoiChange ? this.MapPoiChange : this.option.Playtype ? this.option.Playtype : "SXT"
        result = result.filter(v => {
          return v.key == key
        })[0]
      } else {
        result = result[0]
      }
      // 这些options属性也可直接设置在video标签上,见 muted
      // 实例化过,修改最新的url
      if (this.myVideo) {
        this.myVideo.src({ type: result.type, src: result.value })
      } else {
        let options = {
          autoplay: this.option.autoplay, // 设置自动播放
          controls: true, // 显示播放的控件
          width: this.component.width,
          height: this.component.height,
          sources: [
            {
              src: result.value,
              type: result.type, // 告诉videojs,这是一个hls流
            },
          ],
        } // videojs的第一个参数表示的是,文档中video的id
        this.myVideo = Videojs(this.videojsId, options, function onPlayerReady() {
          this.on("error", function () {
            // 报错信息
            var mediaError = this.error()
            console.log("mediaError", mediaError)
            // 异常处理
            that.updateData()
          })
        })
      }
    },
  },

以上代码的核心有3点:

  1. 关闭的时候,销毁 videojs;
  2. 销毁后立即创建一个与先前videojs 相同的 dom,尤其是 id 要保持一致;
  3. 显示时候重新初始化渲染 videojs(因为全局方法默认会调用绘制 drawChar,否则需要再显示逻辑里面新增绘制方法)

只要注意到这三个核心点,类似的问题也能迎刃而解。

注意事项

  1. 销毁要包裹在\$nextTick里面,不然会出现报错。

请在此添加图片描述

Error:Invalid target for nutl#on;must be a DOM node or evented object
  1. 需要通过 appendChild,添加一个跟之前 videojs 一样的根 dom,不然会报错找不到这个元素的 id:

请在此添加图片描述

TypeError: The element or ID supplied is not valid. (videojs)

总结

关于 videojs,实际项目用到的比较多,坑也是真的坑。文档不太好找,搜索查询了好长时间,才摸索出一套可行的解决方案。面对这类问题,需要善用搜索,从别人的文章和问答中寻找解决问题的思路和方案。查阅官方文档也是个不错的选择,但并不是每个类库框架的官方文档写的都易于理解。videojs 新版的文档和旧版本有些区别,很多 API 看起来并不十分直观,所以版本问题也要注意下。

以上是我解决这个问题的经验分享,欢迎评论区交流。

参考

vue使用videojs控制后台m3u8数据请求 - bomdeyada - 博客园

目录
相关文章
|
4天前
|
JavaScript 前端开发 开发工具
前端开发必备的 VSCode 插件推荐(第三期)
本文推荐两款提升Vue开发效率的VSCode插件:vue-helper,支持代码扩选、快速跳转与变量定位;别名路径跳转插件,解决@路径无法跳转问题。配置简单,实用高效,助力前端开发提速。
97 0
|
4天前
|
人工智能 前端开发 搜索推荐
前端开发必备的 VSCode 插件推荐(第二期)
本文由喵喵侠推荐三款实用VSCode插件:background自定义编辑器背景、Codeium提供AI智能补全、colorize实现颜色值实时高亮,提升开发效率与视觉体验,适合前端开发者使用。
79 0
|
4天前
|
人工智能 JavaScript UED
如何实现两个下拉选择框 select选中联动效果?
本文通过一个公司与产品联动的下拉选择案例,详细讲解了Element UI中双向联动下拉框的实现方法。涵盖数据过滤、回显处理、重置功能及注意事项,结合Vue实战代码,帮助开发者提升表单交互体验,适用于各类关联选择场景的开发参考。(238字)
78 0
如何实现两个下拉选择框 select选中联动效果?
|
4天前
|
人工智能 前端开发 Go
前端开发必备的 VSCode 插件推荐(第一期)
本文推荐三款提升前端开发效率的VSCode插件:Live Server实现网页实时预览,Tencent Cloud AI Code Assistant提供智能补全与代码优化,WakaTime记录编程时长。助力开发者高效编码,欢迎交流分享使用心得。
70 0
前端开发必备的 VSCode 插件推荐(第一期)
|
4天前
|
自然语言处理 前端开发 Windows
推荐一款很好用的VSCode变量翻译插件
本文介绍VSCode插件“var-translate-en”,可一键将中文翻译为英文并转为小驼峰等命名格式,支持百度、腾讯、阿里等翻译服务。通过简单配置与快捷键设置,提升变量命名效率,解决命名难题。
92 0
|
4天前
|
安全 网络安全 开发工具
解决 Host key verification failed 报错的三种方法(含 SSH 安全建议)
本文由喵喵侠撰写,详解Git提交时常见报错“Host key verification failed”的成因与解决方案。当SSH密钥变更或服务器重装系统时,本地记录的主机密钥会失效,导致连接被拒。文章提供三种解决方法:使用`ssh-keygen -R`删除旧密钥、手动编辑`known_hosts`文件,或临时禁用严格检查(不推荐生产环境)。同时强调安全建议:确认服务器状态、核对密钥指纹、启用`VerifyHostKeyDNS`防范中间人攻击。帮助开发者快速定位问题,保障代码提交顺畅。
100 0
|
4天前
|
JavaScript 数据可视化 前端开发
从零开始:使用 Vue-ECharts 实现数据可视化图表功能
本文介绍如何使用 Vue-ECharts 在 Vue 项目中快速开发图表,重点讲解安装、引入方式及分组柱状图的实现,帮助开发者高效完成数据可视化。
98 0
|
4天前
|
移动开发 前端开发 JavaScript
uni-app实战案例:实现H5页面麦克风权限获取与录音功能
本文介绍如何在uni-app的H5页面中实现麦克风权限获取与录音功能,涵盖音频流转换为Blob、Base64及文件下载的完整方案,助力前端语音交互开发。
115 0
|
9月前
|
弹性计算 安全 Linux
阿里云服务器镜像解析:镜像类型对比、适用场景与选择策略参考
阿里云服务器镜像,作为ECS实例的“装机盘”,不仅提供了操作系统,还包含了初始化应用数据和预装软件,云服务器镜像的选择对于云服务器的性能和稳定性起着至关重要的作用,选择合适的镜像对于云服务器的性能和稳定性至关重要。本文将深入解析阿里云服务器提供的多种镜像类型,从公共镜像到社区镜像,全面介绍每种镜像的特点、优势以及选择建议,帮助用户根据自身需求做出适合自己的选择。
1228 12
|
10月前
|
人工智能 自然语言处理 前端开发
20分钟上手DeepSeek开发:SpringBoot + Vue2快速构建AI对话系统
本文介绍如何使用Spring Boot3与Vue2快速构建基于DeepSeek的AI对话系统。系统具备实时流式交互、Markdown内容渲染、前端安全防护等功能,采用响应式架构提升性能。后端以Spring Boot为核心,结合WebFlux和Lombok开发;前端使用Vue2配合WebSocket实现双向通信,并通过DOMPurify保障安全性。项目支持中文语义优化,API延迟低,成本可控,适合个人及企业应用。跟随教程,轻松开启AI应用开发之旅!

热门文章

最新文章