Video.js 加载视频失败切换其它 source

2024-08-23 01:18

本文主要是介绍Video.js 加载视频失败切换其它 source,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Video.js 加载视频失败切换其它 source

使用 Video.js 加载视频(本例为 m3u8 直播视频源)时,如果失败就会显示错误提示 UI。

一些场景下无法进行手动刷新,所以需要对加载失败的场景进行处理,尝试加载其它可用的视频源。

本例介绍 Video.js 如何切换 source、如何捕获错误,以及一些细节。

Video.js 提供的 API 有多种方式可以实现这个功能,本例只是其中一个方案。

示例代码

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Video.js 加载失败切换其它视频源</title><link href="https://vjs.zencdn.net/7.15.4/video-js.css" rel="stylesheet" /><script src="https://vjs.zencdn.net/7.15.4/video.min.js"></script></head><body><video id="my-video" class="video-js"></video><script>// 测试用的视频源const sources = [{src: 'https://aaa/.m3u8',type: 'application/x-mpegURL'},{src: 'https://bbb/.m3u8',type: 'application/x-mpegURL'},// 第三个真实可用{src: 'https://live.unified-streaming.com/scte35/scte35.isml/.m3u8',type: 'application/x-mpegURL'}]let index = 0 // 当前加载的视频源序号var player = videojs('my-video', {width: 500,controls: true,preload: 'auto',autoplay: 'muted', // 实现视频自动播放的关键sources: sources[index]})videojs.hook('beforeerror', (player, err) => {console.log('hook - beforeerror', index, player.src(), err)// Video.js 在切换/指定 source 后立即会触发一个 err=null 的错误,这里过滤一下if (err !== null) {player.src(sources[++index])}// 清除错误,避免 error 事件在控制台抛出错误return null})player.ready(() => {// 丢失 source 事件处理player.tech().on('retryplaylist', function () {console.log('event - retryplaylist')player.src(sources[++index])})})// 其它可以观察进度的事件和钩子// videojs.hook('error', (player, err) => {//   console.log('hook - error')//   return err// })// player.on('error', () => {//   console.log('event - error')// })// player.on('loadeddata', () => {//   console.log('event - loadeddata')// })// player.on('loadedmetadata', () => {//   console.log('event - loadedmetadata')// })// player.on('loadstart', () => {//   console.log('event - loadstart')// })</script></body>
</html>

细节说明

自动播放

以前可以通过给 video 元素或 Video.js 选项设置 autoplay 自动播放(非静音的),但是后来 Chrome 做出了限制,禁止音频自动播放。

这就导致当 Video.js 自动或手动调用 player.play() 执行播放时,Chrome 控制台会报错:DOMException: play() failed because the user didn't interact with the document first.

Chrome 的目的是避免音频的自动播放骚扰到用户的意外情况,但也划定了允许视频自动播放的条件,例如设置静音的视频允许自动播放。

你可以在 video 元素上设置 muted 和 autoplay 属性,也可以在调用 Video.js 的 play() 方法前先设置静音,例如:

// 当前视频加载到足够持续播放的数据后触发 loadeddata
// 也可以使用 loadedmetadata 事件,它在加载完视频元数据后触发,也足够播放视频了
player.on('loadeddata', () => {// 先设置静音player.muted(true)// 再执行播放player.play()
})

又或者设置 autoplay 选项为 muted,它的效果相当于上面的代码。

虽然官方说 autoplay: 'muted' 选项 会在 loadstart 时自动执行 player() 方法,但是 loadstart 事件只是完成开始加载事件时触发,执行事件处理函数时,并不能保证加载的视频数据片段足够进行播放甚至可能加载失败,所以在 loadstart 事件中手动执行 player() 依然会报错,可是通过设置 autoplay: 'muted' 选项并未报错,大概是调用时机比文档中说的要靠后些。(简单看了下源码不太好找就放弃了)

关于 Chrome 禁止自动播放声音请查看:Chrome 66禁止声音自动播放之后

错误捕获

示例代码中用了两个钩子 beforeerrorerror,它们都是当捕获到错误时触发。

beforererror 钩子

beforererror 用于捕获到错误,并在浏览器控制台抛出错误前触发。

它必须返回一个错误信息或代表错误已清除的 null

如果它返回有效的错误信息(不是 null),则会触发 error 事件和钩子,并作为参数传递过去。

如果返回 null,就不会触发 error 事件和钩子。

默认情况下它就是把错误直接 return。

error 钩子

error 用于捕获 beforerror 返回的错误信息,默认情况下,它会直接将错误展示在浏览器的控制台。

player.on('error', event => {// 可以通过 event 获取 player 实例const currentPlayer = event.target.player// console.log(currentPlayer === player) // true// 可以通过 error() 方法获取当前抛出的错误信息(可通过beforeerror钩子自定义返回的错误对象)console.log(player.error())
})
使用选择

如果不想在控制台抛出错误信息,可以使用 beforeerror,处理业务逻辑后最终返回 null 清理错误。

beforeerror 在切换/指定 source 后立即会触发一个 err=null 的错误,所以内部还需要额外判断一下触发时是否真的是错误导致。

如果不想进行额外的判断,且无所谓控制台是否显示错误信息,则可以直接使用 error 事件或钩子,简单省事。

请注意:用于钩子处理函数是全局添加的,在实际开发中请记得在必要时机移除(removeHook)钩子处理函数,在存在多个不同处理的视频播放的页面中可能还需要定义判断播放器的逻辑。

丢失视频源

视频已成功播放后,网络突然变得不稳定甚至断网,导致Video.js 请求 .m3u8 返回 404,直播视频就会持续 loading。

Video.js 会在控制台抛出警告:VIDEOJS: WARN: Problem encountered with playlist 0-https://xxxx.m3u8. Trying again since it is the only playlist.

这个期间 Video.js 认为视频源丢失,一直在尝试重新加载,当网络恢复,加载成功后,就又会继续播放。

但有的服务器为直播视频地址设置了有效期,一定时间没有请求就会失效,需要使用新生成的地址。

而 Video.js 的 error 钩子和事件无法监听这个场景。

这样就导致一旦断网时间超过地址有效期,网络恢复后重新加载视频源仍会失败,但是没有定义有效的重载机制,Video.js 就会一直重试这个过期的地址。

好在通过源码搜索这段警告,发现 Video.js 的 tech 在告警重试后主动触发一个 retryplaylist 事件,我们可以通过 tech 监听这个事件执行自定义重载机制。

源码:

if (playlists.length === 1 && blacklistDuration !== Infinity) {videojs.log.warn("Problem encountered with playlist " + currentPlaylist.id + ". " + 'Trying again since it is the only playlist.');this.tech_.trigger('retryplaylist'); // if this is a final rendition, we should delayreturn this.masterPlaylistLoader_.load(isFinalRendition);
}

注意: tech 要在播放器准备就绪后才会初始化完成,所以要在 ready 中添加回调函数绑定 retryplaylist 事件处理函数。

推荐

关于更多 Video.js 请阅读官方文档,或本人翻译的不完整的中文文档:Video.js v7.15.6 中文文档

这篇关于Video.js 加载视频失败切换其它 source的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1097941

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求,要求做一款播放器,发现能力上跟EasyPlayer.js基本一致,满足要求: 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏(单屏/全屏) 多分屏(2*2) 多分屏(3*3) 多分屏(4*4) 播放控制 播放(单个或全部) 暂停(暂停时展示最后一帧画面) 停止(单个或全部) 声音控制(开关/音量调节) 主辅码流切换 辅助功能 屏

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

使用JS/Jquery获得父窗口的几个方法(笔记)

<pre name="code" class="javascript">取父窗口的元素方法:$(selector, window.parent.document);那么你取父窗口的父窗口的元素就可以用:$(selector, window.parent.parent.document);如题: $(selector, window.top.document);//获得顶级窗口里面的元素 $(

js异步提交form表单的解决方案

1.定义异步提交表单的方法 (通用方法) /*** 异步提交form表单* @param options {form:form表单元素,success:执行成功后处理函数}* <span style="color:#ff0000;"><strong>@注意 后台接收参数要解码否则中文会导致乱码 如:URLDecoder.decode(param,"UTF-8")</strong></span>