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

相关文章

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

python项目环境切换的几种实现方式

《python项目环境切换的几种实现方式》本文主要介绍了python项目环境切换的几种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 如何在不同python项目中,安装不同的依赖2. 如何切换到不同项目的工作空间3.创建项目

SpringBoot项目整合Netty启动失败的常见错误总结

《SpringBoot项目整合Netty启动失败的常见错误总结》本文总结了SpringBoot集成Netty时常见的8类问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、端口冲突问题1. Tomcat与Netty端口冲突二、主线程被阻塞问题1. Netty启动阻

SpringBoot整合Kafka启动失败的常见错误问题总结(推荐)

《SpringBoot整合Kafka启动失败的常见错误问题总结(推荐)》本文总结了SpringBoot项目整合Kafka启动失败的常见错误,包括Kafka服务器连接问题、序列化配置错误、依赖配置问题、... 目录一、Kafka服务器连接问题1. Kafka服务器无法连接2. 开发环境与生产环境网络不通二、序

springboot+mybatis一对多查询+懒加载实例

《springboot+mybatis一对多查询+懒加载实例》文章介绍了如何在SpringBoot和MyBatis中实现一对多查询的懒加载,通过配置MyBatis的`fetchType`属性,可以全局... 目录springboot+myBATis一对多查询+懒加载parent相关代码child 相关代码懒

Qt实现删除布局与布局切换功能

《Qt实现删除布局与布局切换功能》在Qt应用开发中,动态管理布局是一个常见需求,比如根据用户操作动态删除某个布局,或在不同布局间进行切换,本文将详细介绍如何实现这些功能,并通过完整示例展示具体操作,需... 目录一、Qt动态删除布局1. 布局删除的注意事项2. 动态删除布局的实现步骤示例:删除vboxLay

MyBatis延迟加载与多级缓存全解析

《MyBatis延迟加载与多级缓存全解析》文章介绍MyBatis的延迟加载与多级缓存机制,延迟加载按需加载关联数据提升性能,一级缓存会话级默认开启,二级缓存工厂级支持跨会话共享,增删改操作会清空对应缓... 目录MyBATis延迟加载策略一对多示例一对多示例MyBatis框架的缓存一级缓存二级缓存MyBat

Vue3视频播放组件 vue3-video-play使用方式

《Vue3视频播放组件vue3-video-play使用方式》vue3-video-play是Vue3的视频播放组件,基于原生video标签开发,支持MP4和HLS流,提供全局/局部引入方式,可监听... 目录一、安装二、全局引入三、局部引入四、基本使用五、事件监听六、播放 HLS 流七、更多功能总结在 v

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

在Node.js中使用.env文件管理环境变量的全过程

《在Node.js中使用.env文件管理环境变量的全过程》Node.js应用程序通常依赖于环境变量来管理敏感信息或配置设置,.env文件已经成为一种流行的本地管理这些变量的方法,本文将探讨.env文件... 目录引言为什么使php用 .env 文件 ?如何在 Node.js 中使用 .env 文件最佳实践引