# Document (常见问题) - - - - - - - - - - - - - > 本文档汇总了 Jessibuca 使用过程中的常见问题(FAQ),并按主题分类整理。可通过下方目录快速跳转到对应分类与问题。 ## 快速接入与配置 ### 推荐配置 #### http ``` { useMSE:true, autoWasm:true } ``` #### https ``` { useWCS:true, autoWasm:true } ``` ### vue、react 推荐 #### vue #### 关于new Jessibuca 之后的实例绑定 1. 推荐绑定在 `this` 上面,不推荐绑定在`data` 对象上面,不然会触发无效的事件监听。 2. 或者在实例的时候,绑定在`data`上面的时候,命名的时候以 `_` 或者`$` 开头,这样也不会触发无效的事件监听。 在 `vue` 中 > 以 _ 或 $ 开头的属性将不会被组件实例代理,因为它们可能和 Vue 的内置属性、API 方法冲突。你必须以 this.$data._property > 的方式访问它们。 见: https://cn.vuejs.org/api/options-state.html#data ```js // 可以挂载在Vue上面 Vue.prototype.$player = new Jessibuca({ }) ``` ```js // 也可以挂载在 $options 上面 this.$options.jessibuca = new Jessibuca({ }) ``` #### react #### 关于new Jessibuca 之后的实例绑定 推荐绑定在 `this` 上面,不推荐绑定在`state` 对象上面。 ### 是否支持npm(yarn) install 安装 > 暂不支持 因为 项目中用到了`wasm`, node_modules 对于`wasm` 支持度不友好。所以暂不支持。 #### 其他解决方案 可以考虑下把wasm文件编译成base64,然后通过打包合并到js文件中,这样就可以通过npm安装了。 > 但是会增加js的文件大小,所以酌情考虑 > 可以看下`vue-cli-plugin-jessibuca`解决方案 ### vue-cli-plugin-jessibuca jessibuca 没有提供 npm package,只能通过 script 方式引入,所以使用 vue-cli 插件形式自动引入 jessibuca 插件会自动在 html 插入 index.js 的 script 标签,所以可以在代码中直接使用 Jessibuca 全局变量 ``` npm install vue-cli-plugin-jessibuca -D # use yarn yarn add vue-cli-plugin-jessibuca -D ``` 使用 ```js const instance = new window.Jessibuca({}) ``` ### vue3 下面使用Typescript https://github.com/langhuihui/jessibuca/issues/137 https://github.com/bosscheng/jessibuca-vue-ts-demo ### 播放器内部的样式发生变形或者class 丢失 可能得原因: - 播放器样式被其他样式覆盖了,检查下是否有全局样式覆盖了播放器的样式(播放器内部会有`video`,`canvas`标签)。 - container 设置了双向绑定,导致class丢失。 推荐的 vue 写法 ```vue ``` 推荐的 react 写法 ```jsx import React, {useEffect, useRef} from 'react' export default function App() { const container = useRef(null) useEffect(() => { const player = new window.Jessibuca({ container: container.current, }) }, []) return (
) } ``` ## 播放器使用与实例管理 ### destroy释放内存 https://github.com/langhuihui/jessibuca/issues/135 > 经测试,放到node+express服务中,16画面轮询跑了14个小时没有崩溃,chrome浏览器内存达到2G左右,destroy优化的效果还是很明显的,感谢大佬! ### 关于切换 url 播放地址 为了降低内存溢出的风险,如果要切换播放地址,需要先销毁当前的实例,再创建新的实例。 ```js let jessibuca = new Jessibuca({ // 参数 }) jessibuca.play('url1') // 切换播放源 jessibuca.destroy().then(()=>{ jessibuca = null; // 从新new一个出来 let jessibuca = new Jessibuca({ // 参数 }) // 播放新的地址 jessibuca.play('url2') }); ``` ### 关于播放器内部自定义DOM(废弃) > 因为在销毁播放器的时候,如果不清空container的innerHTML,可能会导致播放器销毁的时候,有DOM内存不释放的问题。所以这个功能废弃掉了。 ~~业务需要有自己的dom在播放器内部,例如~~ ```html
``` ~~当初始化播放器,传递 `container` 参数的时候,播放器会在 `container` 内部创建播放器的`DOM`~~ ```html
// 播放器自己初始化的dom元素
``` ~~如果业务需在播放器内部有自己的`DOM`,可以直接在`container`内部创建,播放器会自动识别并不会覆盖。~~ ```html
// 播放器自己初始化的dom元素 // 业务的dom
业务自己的dom
``` ~~小结: 所以在初始化播放器的时候,业务可以通过在container内部创建自己的dom。~~ ```html
// 业务的dom
业务自己的dom
``` ~~待播放器初始化的时候,播放器只会在container内部创建自己的dom,不会覆盖业务自己的dom。~~ ~~> 调用播放器destroy() 方法的时候,播放器内部也只会销毁掉播放器创建的dom,不会销毁业务自己创建的dom。~~ ### 关于播放器自定义DOM(新) 给播放器的dom 对象是 ```html
``` 如果需要自定义DOM,可以在`container` 外部包裹一层DOM。 ```html
业务自己的dom
``` > 全屏的实现就需要业务层自己通过全屏api 来实现 `your-dom` 的全屏。全屏之后,调用下播放器的`resize()` 方法就行了,其他的照旧。 ### 直播流播放完了,能监听到吗? 回答:不能 因为播放器也不知道流什么时候结束,播放器是被动的接受流数据的,所以播放器也不知道流什么时候结束。 解决方案: 1. 可以通过业务层去监听流是否结束。 2. 可以通过监听超时事件(不建议)。 3. 监听stats里面的vbps,如果vbps为0,并且持续一段时间了,可以认为流结束了。 4. 可以同时结合监听error事件,如果fetchError或者是websocketError 然后结合vbps为0来判断推流结束了。 ### 回放流播放完了,能监听到吗? 回答:能 > pro版本可以支持播放回放流,当了回放流结束,播放器会检测流的结束状态,然和结合已经缓存的流数据是否已经播放完了,来判断回放流是否结束了。 ### 关于当前直播流正在播的时间点,想要获取画面中的时间点 如图 > 想要获取到画面中的时间点。 #### 目前播放器能够拿到的时间 目前播放器能够监听到的时间是从流里面的`时间戳`,`stats`中的`ts`,这个是流里面获取到的`pts`时间。 > 这个是流里面的时间戳,可能是相对时间戳,也可能是绝对时间戳。 #### 解决方案 ##### 方法一 如果业务上面需要获取`当前直播流正在播的时间点` 这需求,目前只能结合业务然后结合`ts`作为相对时间来计算。 1. 从服务器获取当前播放的时间点, 2. 监听播放器的stats事件,获取到`ts`,缓存一个开始时间点,通过最新的`ts`减去开始时间点,就是当前播放的时间点。 ##### 方法二 可以让流媒体服务器端,把当前播放的时间点放入到SEI中,然后播放器解析SEI,获取到当前播放的时间点。 > Pro 版本可以监听到SEI数据。 ### 关于更新播放窗口大小 1. 修改`your-container`的宽高 2. 调用播放器的`resize()`方法。 > your-container 是new Jessibuca() 的 container 参数 ```js const jessibuca = new Jessibuca({ container: document.getElementById('your-container') }) ``` ### 关于在H5中实现横竖屏自适应 > 这个需要业务层借助resize() 方法自己实现 1. 监听到横竖屏切换事件 2. 修改`your-container`的宽高 3. 调用播放器的`resize()`方法。 > your-container 是new Jessibuca() 的 container 参数 ```js const jessibuca = new Jessibuca({ container: document.getElementById('your-container') }) ``` 监听横竖屏切换事件 ```js window.addEventListener('orientationchange', function () { // 横屏 if (window.orientation === 90 || window.orientation === -90) { // 修改your-container的宽高 // 调用播放器的resize()方法 } else { // 竖屏 // 修改your-container的宽高 // 调用播放器的resize()方法 } }) ``` ### 当container窗口发生变化的时候,播放器如何自适应 播放器提供一个`resize()` 方法。当外界窗口发生变化的时候,调用该方法即可。 ```js const player = new window.Jessibuca({ container: dom, }) // 当container的宽高发生变化的时候,调用resize方法 player.resize(); ``` ### 如何实现窗口内全屏(非浏览器全屏) ### 关于切换分辨率 目前pro版本支持配置分辨率参数,会在底部UI 展示,当点击分辨率的时候,会抛出事件,然后业务层监听到事件,通过调用播放器的`play(url)` 方法来实现分辨率的切换逻辑。 体验demo:[https://jessibuca.com/pro/demo-control-dom.html](https://jessibuca.com/pro/demo-control-dom.html) ## 解码渲染与播放能力 ### 关于硬解码和软解码 #### 硬解码 1. `useMSE`和`useWCS`都是硬解码 2. `useMSE` 支持 H264, 3. `useMSE` jessibuca Pro 支持 H265(需要手动开启参数), 4. `useWCS` 只支持H264(浏览器不支持H265) 5. `useMSE` 支持http 和https 6. `useWCS` 只支持https #### 软解码 1. 支持 H264(低分辨率) 和 H265(低分辨率) 2. jessibuca Pro 支持 H264 和 H265 高分辨率高帧率解码 5. 软解码支持http 和https 如果遇到硬解码失败的时候,会自动切换到wasm软解码 > 单屏情况下,软解码可以比硬解码做到更低的延迟。 > 多屏情况下,因为软解码比较吃CPU 所以在多屏情况下,会出现解码延迟,导致播放延迟,卡顿。 > 多屏情况下,建议使用硬解码。如果硬解码不支持,可以考虑降低屏幕数量。 目前pro对于软解码和硬解码的支持情况,[连接](/pro.html#windows-%E9%BB%98%E8%AE%A4) ### 关于解码(useMSE、useWCS、wasm)优先级 #### useMSE 使用的是浏览器提供的`MediaSource`接口,来进行解码。 - 硬解码 - 兼容性好 - ios safari不支持 - 支持H264和H265解码 - 支持http和https #### useWCS 使用的是`WebCodec`接口,来进行解码。 - 硬解码 - 支持H264和H265解码 - 支持https - ios safari不支持 - 兼容性不如mse #### wasm(simd) 使用的是`webassembly`来进行解码。 - 软解码 - 兼容性好 - 支持H264和H265解码 - 支持http和https > wasm(simd) 主要是只支持`simd`指令集的浏览器,比如`chrome`,`edge`,`safari`不支持。 #### 优先级 如果同时配置了`useMSE`和`useWCS`,则优先使用`useMSE`,如果`useMSE`不支持,则使用`useWCS`,如果 `useWCS` 不支持,则降级到`wasm`解码。 > useMSE > useWCS > wasm ### 关于是否可以播放rtsp、rtmp协议 #### 回答:浏览器不支持 > 浏览器不支持rtmp:// ,rtsp:// 协议 浏览器只支持,`http(s)://`、 `ws(s)://`、`Webrtc`、`Webtransport` 等协议 因为在js的环境中,无法直接使用tcp或者udp传数据(js没提供接口),而rtsp的流是基于tcp或者udp, 所以纯web的方式目前是没办法直接播放rtsp流的,rtmp也是类似 #### 解决方案(使用M7S) https://qun.qq.com/qqweb/qunpro/share?_wv=3&_wwv=128&appChannel=share&inviteCode=21lyeGcXwMe&contentID=1qiMyF&businessType=2&from=181174&shareSource=5&biz=ka m7s 产品下载地址:[https://m7s.live/download](https://m7s.live/download) m7s 官网介绍:[https://m7s.live/](https://m7s.live/) ### 对于渲染元素 #### wasm软解码 默认是通过 `canvas` 进行渲染的 > jessibuca pro 支持 `video` 标签渲染 #### mse 硬解码 默认是通过 `video` 标签进行渲染的 > jessibuca pro 支持 `canvas` 标签渲染 #### webcodecs 硬解码 默认是通过 `canvas` 进行渲染的,也支持video渲染 > Pro 支持 `canvas webgl2` 进行渲染的 ##### 如果网页中存在大量消耗webgl性能的,会导致播放器不够webgl资源,导致canvas渲染挂掉,出现一个`哭脸表情`的表情。 消耗webgl性能的,比如说,3d背景,地图啥的。 解决方案: 1. 使用video标签渲染。 2. 网页中移除掉些消耗webgl性能的东西。 ### OffscreenCanvas这个特性需要特殊的环境和硬件支持吗 默认是关闭的. 如果开启需要设置 forceNoOffscreen 为 false 就可以了。 各个浏览器对于OffscreenCanvas支持程度。 https://caniuse.com/?search=OffscreenCanvas > 该特性是实验性特性,某些版本的浏览器会出现内存无缘无故变大的情况。谨慎使用。 > https://github.com/langhuihui/jessibuca/issues/227 ### 关于初始化webgl失败的可能性 1. 浏览器不支持webgl。 2. 浏览器支持webgl,但是被禁用了。 3. 如果是套壳在QT等环境下,可能会有webgl初始化失败的情况。检查是否选择了正确的显卡,或者显卡驱动是否正常。 #### 浏览器如何禁用/开启 webgl 要在Chrome浏览器中禁用WebGL,您可以按照以下步骤操作: 1. 打开Chrome浏览器并输入以下地址:chrome://flags。 2. 在Chrome Flags页面中,搜索框中输入"webgl",以查找与WebGL相关的标志。 3. 找到名为"WebGL"的选项,并将其设置为"Disabled"。 4. 关闭Chrome浏览器,并重新启动它以使更改生效。 完成上述步骤后,Chrome浏览器将禁用WebGL功能。请注意,这将影响所有网站上使用WebGL的内容,包括3D图形和游戏等。 ## HEVC H265 与硬件解码 ### Media Source Extensions 硬解码H265 - Windows系统下,360浏览器可播放使用MSE加速解码H265. - Windows系统下,win10商店购买hevc解码器后最新edge可硬件加速解码播放H265. > jessibuca pro 版本已经支持了。欢迎测试使用。http://jessibuca.monibuca.com/player-pro.html ### webcodecs 硬解码H265 #### Chrome/Edge 86及之后 提供的WebCodecs API来进行硬解码,为实验特性,需要手动开启 enable chrome: //flags/#enable-experimental-web-platform-features, or pass --enable-blink-features=WebCodecs flag via the command line. #### Chrome/Edge 94之后 Desktop,Android,Webview中已默认开启! 需要https加载web,播放https/wss-flv流. 如果控制台打印 "WCS is not supported or experimental-web-platform-features not enabled" 请将当前页面使用https访问 > jessibuca pro 版本已经支持了。欢迎测试使用。http://jessibuca.monibuca.com/player-pro.html ### 对于hevc(265)支持情况 [caniuse详情](https://caniuse.com/?search=hevc) #### chrome 1. Supported for all devices on macOS (>= Big Sur 11.0) and Android (>= 5.0), 2. for devices with hardware support on Windows (>= Windows 8), 3. and for devices with hardware support powered by VAAPI on Linux and ChromeOS #### edge 1. Supported for all devices on macOS (>= Big Sur 11.0) and Android (>= 5.0) if Edge >= 107, 2. for devices with hardware support on Windows (>= Windows 10 1709) when HEVC video extensions from the Microsoft Store is installed [Microsoft.HEVCVideoExtension_2.1.1803.0_neutra.zip](https://jessibuca.com/zip/Microsoft.HEVCVideoExtension_2.1.1803.0_neutra.zip) #### 实际测试情况 1. 遇到过两台电脑操作系统,浏览器版本都是一样,cpu 不一样,GPU不一样,4050显卡的所有浏览器都能走硬解码,2060显卡就有谷歌浏览器能走硬解码,预测是 HEVC video extensions 这个插件的兼容性问题。 ### 关于PRO提示MSE不支持265解码可能得原因 #### 检查下chrome(edge)的版本号 确保是较新版本。 #### 检查操作系统 ##### window 1. 确保GPU 支持 Hevc硬解 2. window10 1709 以前的版本不支持,建议升级到最新版本。 3. 需要安装 `HEVC video extensions` HEVC扩展 4. 或者安装360浏览器(最新版本) [Microsoft.HEVCVideoExtension_2.1.1803.0_neutra.zip](https://jessibuca.com/zip/Microsoft.HEVCVideoExtension_2.1.1803.0_neutra.zip) #### mac 1. macOS (>= Big Sur 11.0) 2. Edge >= 107 #### 扩展 [window chrome 如何开启HEVC硬件解码](https://jessibuca.com/document.html#chrome-%E5%A6%82%E4%BD%95%E5%BC%80%E5%90%AFhevc%E7%A1%AC%E4%BB%B6%E8%A7%A3%E7%A0%81) ### chrome 如何开启HEVC硬件解码 解决方案:https://www.nxrte.com/jishu/11365.html 主要就是检测步骤就是: 1. 判断客户机是否支持HEVC硬解码 2. chrome浏览器配置 #### 判断客户机是否支持HEVC(H265)硬解码 首先检查自己的电脑是否支持HEVC硬解码,可以下载dxva checker检测软件,DXVAChecker是一个windows系统PC检测DirectX视频加速的工具,其可检测解码是否支持GPU #### chrome浏览器配置 1. 首先安装最新版本的google chrome浏览器,打开帮助->关于,查看版本号是否大于104。 2. 地址栏输入:chrome://settings,打开配置页面,搜索”硬件加速”,使用硬件加速开启: 3. 地址栏输入:chrome://flags,搜索hardware,使能Hardware-accelerated video decode硬件解码: 4. 如果chrome浏览器没有快捷方式,建立一个快捷方式,增加启动运行参数:–enable-features=PlatformHEVCDecoderSupport 这样使用此快捷方式打开即可直接加上此运行参数,也可cmd下运行exe加上此运行参数运行,比较麻烦,这里直接添加到快捷方式上,加入方式如下( 右键->属性->目标(T) 末尾加个空格,然后赋值上面的参数): 5. 通过快捷键打开chrome,地址栏输入chrome://gpu,搜索”Video Acceleration”,验证chrome是否开启成功: ### 关于window Hevc是否支持 #### edge/chrome 自查 1.浏览器输入:`chrome://gpu/` 如果edge浏览器就`edge://gpu/` 2.全局搜索下`hevc`关键词 #### 查看设备是否支持 要知道自己的电脑支持什么格式的硬解码,可以下载DXVA Checker 下载地址:https://bluesky-soft.com/en/DXVAChecker.html 也可以直接查询BlueSky的数据库(可直接点击超链接) - AMD :https://bluesky-soft.com/en/dxvac/deviceInfo/decoder/amd.html - Intel :https://bluesky-soft.com/en/dxvac/deviceInfo/decoder/intel.html - NVIDIA :https://bluesky-soft.com/en/dxvac/deviceInfo/decoder/nvidia.html 浏览器通常采用核显加速,同时有独显核显的,参考核显的解码能力。 HEVC硬解支持的硬件较多,Intel第六代酷睿处理器及以后的核显全部支持HEVC,六代之前的部分支持,具体请看BlueSky的数据库。 AV1硬解目前仅限于AMD RX 6000系(除6500XT)、Nvidia 30系、Intel Arc显卡、Intel UHD 700系和Iris 锐炬Xe核显,后续型号应该也会支持AV1。 #### 开启Hevc硬解码 1. 开启HEVC之前需要下载HEVC插件,这个插件可以在微软商店花7块钱购买。 搜索:HEVC视频扩展(打开Microsoft Store,检索HEVC视频扩展插件,获取HEVC插件URL链接。) - 打开Microsoft Store,检索HEVC视频扩展插件,获取HEVC插件URL链接。 - 打开以下链接,在URL(link)输入框中填入在Microsoft Store拿到的插件URL即可。 打开Microsoft Store网页版地址。然后把地址复制出来 打开这个地址: > https://store.rg-adguard.net/ 然后把“Microsoft Store网页版地址” 复制进去,然后搜索,进行下载就行了。 可下载的资源 2. 也可以直接在网上免费下载,两者都是一样的。 HEVC视频拓展下载地址:https://www.free-codecs.com/hevc_video_extension_download.htm 由于以前的bug已经修复,所以可以直接下载最新版的插件,选择x64版本的HEVC Video Extension xxxx下载并安装。 或者直接下载已经下载好的:[Microsoft.HEVCVideoExtension_2.1.1803.0_neutra.zip](https://jessibuca.com/zip/Microsoft.HEVCVideoExtension_2.1.1803.0_neutra.zip) 感谢:https://www.bilibili.com/read/cv35896480/ 的解决方案。 3. 在地址栏输入edge://flags/ 进入搜索 Choose ANGLE graphics backend 选择 D3D11,选择后重启浏览器再打开。 ### 如何开启electron硬解码Hevc(H265) https://github.com/StaZhu/enable-chromium-hevc-hardware-decoding/blob/main/README.zh_CN.md > 如果是 Electron 20 (Chromium 104),则已集成好 Mac, Windows 平台的 HEVC 硬解功能,在启动时执行 > app.commandLine.appendSwitch('enable-features', 'PlatformHEVCDecoderSupport') 即可启用硬解。若要集成软解,方法同上述 > Chromium 教程相同。 见:https://www.cnblogs.com/gnz48/p/16422304.html ### 如何验证视频播放是否走硬解? 打开 `chrome://gpu`, 搜索 `Video Acceleration Information`, 如果能看到 `Decode hevc main` 和 `Decode hevc main 10` ( macOS 还会显示 `Decode hevc main still-picture` 和 `Decode hevc range extensions`) 说明支持硬解(这里 macOS 是个例外,显示仅代表支持 `VideoToolbox` 解码,至于是否硬解取决于 GPU 支持情况)。 打开 `chrome://media-internals` 并尝试播放一些 HEVC 视频 (测试页面),如果最终使用的 Decoder 是 `VDAVideoDecoder` 或 `D3D11VideoDecoder` 或 `VaapiVideoDecoder` 说明走了硬解(这里 macOS 是个例外,macOS Big Sur 以上版本,在不支持的 GPU 上,VideoToolbox 会自动 fallback 到软解,性能相比 FFMPEG 软解更好,Decoder 同样为 `VDAVideoDecoder`), 如果 Decoder 是 `FFMpegVideoDecoder` 说明走的是软解。 #### MAC 如果是 Mac,请打开 活动监视器并搜索 `VTDecoderXPCService`, 如果播放时进程的 CPU 利用率大于0说明走了硬解(或软解)。 #### Windows 如果是 Windows,请打开 任务管理器 并切换到 性能 - GPU 面板,如果 `Video Decoding` 的利用率大于0说明走了硬解。 ### 为什么我的显卡支持,但仍无法使用硬解? 1. 操作系统版本过低 2. 显卡驱动版本有问题 3. 特定硬件有问题 #### 操作系统版本过低 ##### Windows 请确保操作系统版本大于等于 `Windows 8`,这是因为 Chromium 的 `D3D11VideoDecoder` 仅支持 Windows 8 以上系统,在 Windows 8 以下操作系统使用 `VDAVideoDecoder` 进行硬解。而 `VDAVideoDecoder` 基于 `Media Foundation` 实现,`Media Foundation` 对于 HEVC 硬解的支持(`需要安装 HEVC视频扩展 插件`),系统版本需大于 `Windows 10 1709`。 ##### macOS 请确保操作系统版本大于等于 `Big Sur`,这是因为`CMVideoFormatDescriptionCreateFromHEVCParameterSets API`,在 Big Sur 以下版本有兼容问题。 #### 显卡驱动版本有问题 部分显卡驱动版本有 BUG,导致被禁用使用`D3D11VideoDecoder`,因此若你确保 GPU 支持 HEVC 硬解,请先更新到最新版本显卡驱动再尝试。 #### 特定硬件有问题 部分硬解有 BUG,导致被禁用 `D3D11VideoDecoder`,这种情况没什么办法解决,只能软解。 ### chrome/edge 等浏览器如何使用独立显卡 1. 在chrome地址栏输入:`chrome://flags/#ignore-gpu-blocklist` 2. 找到`Override software rendering list`选项 3. 将其设为Enabled 4. 重启浏览器 ### 如何设置chrome浏览器优先使用独立显卡的硬件解码器 > 默认情况下 Chrome 更倾向于使用集成显卡(如 Intel HD/UHD Graphics)来做视频解码任务,而不是独立显卡(如 NVIDIA 或 AMD)。即使你的系统有独显,Chrome 也通常不会主动使用它来做视频解码,除非特定条件满足或者你强制设置。 #### 方式一:Windows 系统层面设置默认 GPU 1. 打开设置 → 系统 → 显示 → 图形设置 2. 选择“浏览” → 添加 chrome.exe(比如 C:\Program Files\Google\Chrome\Application\chrome.exe) 3. 点击“选项”,选择“高性能”(通常是独立显卡),保存 > ⚠️ 注意:这只能控制 Chrome 的整体渲染和 GPU 使用,不一定能让视频解码器也切换到独显,因为视频解码仍依赖系统硬件解码能力 + 驱动。 #### 方式二:Chrome 启动参数添加强制 GPU 设置 ```shell --use-gl=desktop --enable-features=VaapiVideoDecoder --ignore-gpu-blocklist ``` 适用于 Windows 和 Linux,其中: - --use-gl=desktop:使用系统级的 OpenGL,而非 ANGLE(兼容层) - --ignore-gpu-blocklist:忽略 Chrome 的硬件黑名单 - --enable-features=VaapiVideoDecoder:强制启用 VA-API(通常 Linux 更有效) #### 方式三:用 chrome://flags 控制 在地址栏输入 chrome://flags,尝试打开以下 flag(取决于系统): - Hardware-accelerated video decode - Override software rendering list #### 验证是否使用了独立显卡解码 1. 在 Chrome 地址栏打开 chrome://media-internals - 播放视频时刷新页面,查看 video_decoder_name,比如是 VpxVideoDecoder/ffmpeg(软件)还是硬件的(如 D3D11VideoDecoder) 2. 查看 chrome://gpu 页面 - 重点看 Video Decode 项是否为 Hardware accelerated 3. 使用 GPU 监视工具(如 NVIDIA 控制面板 / GPU-Z / MSI Afterburner)看独显是否在解码视频时工作 ## 文件部署与加载 ### jessibuca.js decoder.js decoder.wasm文件想存放特定地址 一般情况下,建议放置在 `public` 目录下面,如果需要放置在子目录,需要修改的地方有 例如放在 `jessibuca`文件夹 index.html文件 ```html ``` 对于 new Jessibuca() 的时候 ``` { decoder:'/jessibuca/decoder.js' } ``` ### jessibuca.js decoder.js decoder.wasm文件想通过CDN加载 因为默认情况下 decoder.js 是通过相对路径引入 decoder.wam 文件的。 如果想引用CDN的地址,需要修改成CDN的绝对地址。 所以如果想通过CDN加载,需要修改decoder.js文件 需要配置`decoder` 参数为CDN绝对地址文件。 ``` { decoder:'https://your-cdn.com/decoder.js' } ``` ```js // 修改前 src/worker/index.js this.decoderWorker = new Worker(player._opt.decoder) // 修改后 src/worker/index.js const blob = new Blob([`importScripts("${player._opt.decoder}")`], {"type": 'application/javascript'}); const blobUrl = window.URL.createObjectURL(blob); this.decoderWorker = new Worker(blobUrl); ``` ```js // 修改前 src/decoder/decoder.js wasmBinaryFile = 'decoder.wasm'; // 修改后 src/decoder/decoder.js wasmBinaryFile = 'https://cdn.com/decoder.wasm'; ``` 然后需要重新执行下 `npm run build` 命令 就可以了。 > Pro版本支持在编译端通过 `rollup.config.js` 配置`WASM 的 CDN`地址。 ### IIS下wasm返回404错误 > 使用IIS作为webserver,程序已经上传到服务器,访问js文件正常,但访问wasm文件返回404错误。 To get rid of the 404 add a new Mime Type for Wasm, it’s not currently in IIS 10 (or below). Click Start > Run > type InetMgr > expand Sites > select the app > Mime Types > Add: Extension: .wasm (dot wasm) MIMEType: application/wasm ### wasm 格式返回错误 Incorrect response MIME type. Expected 'application/wasm'. falling back to arraybuffer instantiation 错误 > Uncaught (in promise) TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. > Expected 'application/wasm'. > Expected 'application/wasm'., falling back to ArrayBuffer instantiation. > These warnings refers to incorrect response MIME type of the wasm file. > In order to fix it, please try to set the MIME filetype to application/wasm > for the actual wasm file in your server config > 这个错误通常是由WebAssembly模块加载时失败而导致的。当WebAssembly模块不能成功编译时,JavaScript代码会回退到使用ArrayBuffer实例化来代替。 - 检查浏览器版本是否过旧,尝试更新下浏览器版本。 - 修复下wasm文件的MIME类型,设置为application/wasm 类似 ```shell [ERROR] wasm streaming compile failed: TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'. [ERROR] falling back to ArrayBuffer instantiation ``` 因为 从远程服务器加载的Wasm模块文件只有在其HTTP相应结果中被标识为application/wasm类型,才可以被WebAssembly.instantiateStreaming方法正确的编译和处理 查看 network 板块,就可以看到decoder.wasm 的返回格式化, 看下` Response Headers` 下面的`Content-Type` 是否是`application/wasm` #### 解决方案 1. 用的springboot的tomcat,所以修改tomcat的mime类型,多添加一个wasm的类型 2. 用的是ISS,配置下wasm类型的数据就行了。 Extension: .wasm (dot wasm) MIMEType: application/wasm ##### apache修改 mime.types,添加 ```shell application/wasm wasm ``` ##### nginx修改mime.types,添加 ```shell application/wasm wasm; ``` ##### 或者 nginx修改nginx.conf,添加 ```shell { # 配置 MIME 类型 types { application/wasm wasm; } # 开启 gzip 压缩 gzip on; } ``` #### 通过springBoot 部署的静态资源遇到 `falling back to arraybuffer instantiation` 错误问题 > decoder-pro-simd.js:1 wasm streaming compile failed: CompileError: WebAssembly.instantiateStreaming(): section (code > 1, "Type") extends past end of the module (length 11493359, remaining bytes 2877270) @+8 > decoder-pro-simd.js:1 falling back to ArrayBuffer instantiation 检查下是不是通过`maven`方式进行打包的。 > maven 进行打包的时候,使用maven进行资源过滤的时候,会把二进制文件破坏掉。导致内容变大。 https://www.mianshigee.com/note/detail/72131ooi/ ##### 解决方案 使用maven进行资源过滤的时候,只要过滤需要过滤的文件,一些二进制文件,比如https证书等,就不要参与资源过滤,否则打包后会破坏文件内容。 ### 优化加载速度 1. 将js程序进行gzip/Brotli压缩 2. 将wasm文件进行gzip/Brotli压缩 > 推荐 Brotli 压缩,Brotli 压缩比 gzip 压缩更高效(提升20%性能),更快速。 ### gzip压缩jessibuca.js 和decoder.js 和decoder.wasm 文件 linux(mac) #### jessibuca.js ``` gzip jessibuca.js mv jessibuca.js.gz jessibuca.js ``` #### decoder.js ``` gzip 和decoder.js mv 和decoder.js.gz 和decoder.js ``` #### decoder.wasm ``` gzip 和decoder.wasm mv 和decoder.wasm.gz 和decoder.wasm ``` windows 系统压缩方法 下载 gzip.exe [http://gnuwin32.sourceforge.net/downlinks/gzip-bin-zip.php](http://gnuwin32.sourceforge.net/downlinks/gzip-bin-zip.php) 解压后,将 `jessibuca.js` 和 `decoder.js`和 `decoder.wasm` 文件拖到 gzip.exe上,文件就压缩好了,也需要去掉.gz后缀 ### Brotli压缩jessibuca.js 和decoder.js 和decoder.wasm 文件 可以看下解决方案 [https://www.cnblogs.com/densen2014/p/16120778.html](https://www.cnblogs.com/densen2014/p/16120778.html) ### 关于WASM压缩优化 压缩是有效提高下载速度的方式,浏览器目前支持的主流压缩格式包括 `gzip` 和 `brotli` 两种。针对wasm包的压缩,`brotli` 算法有显著的优势。 - gzip: 一种流行的压缩文件格式,能有效的降低文件大小。 - brotli: Google 在 2015 年推出的一种压缩方式,相对于 Gzip 约有 20% 的压缩比提升。 ### 关于如何集成到qiankun这类的微前端中去 需要将jessibuca的`dist`目录下面的文件[`decocer.js`,`decoder.wasm`,`jessbuca.js`]放到`主应用`的`public`目录或者根目录下面。 然后在`子应用`使用的时候,要在index.html 下面通过`script`标签引入主应用路径下面的`jessbuca.js` ,在业务代码里面,通过配置`decoder`参数,也是主应用下面的decoder.js地址。 > 注意:`decocer.js`,`decoder.wasm`两个文件必须放同一个目录下面。 ### decoder.js 报 Unexpected token '<'错误 或者报:[decoderWorker] onerror and decoder url is xxxxx and filename:message > 对于 pro 的 decoder-xxx.js 也是会有同样的问题,需要配置正确的路径。 > 这主要是由于decoder.js 解码器或者对应的wasm加载异常导致的,根本原因还是decoder参数配置的有问题,导致加载js以及wasm资源异常了。 1.查看控制台的`network` 面板下面的 `decoder.wasm`文件有没有被正确返回。返回个格式是不是 `application/wasm`格式的。 2.查看控制台的`network` 面板下面的 decoder.js 文件有没有被正确返回。返回个格式是不是 `application/javascript` 格式的。(因为配置的路径不对,会存在vue 或者react 项目 直接被返回了index.html 内容了) 这是错误的返回(直接被返回了index.html 内容了) 3.查看`decoder`参数是否配置的正确,见[decoder参数配置](http://jessibuca.monibuca.com/api.html#decoder) ,如果配置错误,会被web服务器以找不到文件,然后返回index.html的内容。 > 需要正确的配置`decoder`参数,播放器默认引用的是根目录下面的`decoder.js` 最后检查返回的内容,正确的应该是 #### react 解决方案 见 https://github.com/bosscheng/jessibuca-react-demo/tree/v3 #### vue 解决方案 https://github.com/bosscheng/jessibuca-vue-demo/tree/v3 typescript:https://github.com/bosscheng/jessibuca-vue-ts-demo #### 网友的解决方案 https://blog.csdn.net/nbwgl/article/details/122652003 ### Failed to constructor 'Worker': Script at 'file://xxxxxxx' #### 方案一:通过http协议启动 别用`file`协议启动项目,`file`协议暂不支持`worker`。 使用`http`协议启动,可以配合`nginx`或者`node` 启动。 > ~~pro 支持通过配置参数,只使用mse解码,不启动worker。 见 demo-file.html~~ 暂不推荐,这种只能走硬解码,没法走软解码。推荐走加载CDN资源的方案。 #### 方案二:加载CDN资源 > 可以通过加载CDN资源的方式,来解决这个问题。 见 `demo-cdn-http.html`, `demo-cdn-https.html` 里面加载的是官网的 cdn 文件。 可以直接用file 协议打开这个 html 文件。 #### node 启动(解决方案) 通过 jessibuca-vue-demo 中的 preview 进行查看。 https://github.com/bosscheng/jessibuca-vue-demo/blob/v3/preview/preview.js #### nginx 配置(解决方案) 下载好pro.zip 解压后, 假设: 你的 HTML 文件路径是: /home/www/myapp/pro/index.html 你希望通过浏览器访问: http://localhost:8080/ 打开 Nginx 配置文件(`/etc/nginx/nginx.conf`) 直接添加配置信息 > 在 http { } 里面添加 ```nginx user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf; # 默认会加载 conf.d 下的所有配置文件 # 你可以在这里直接加一个 server 块👇 server { listen 8080; # 监听端口 server_name localhost; # 域名(可改成你的 IP 或域名) root /home/www/myapp/pro; # 你的 HTML 文件所在目录 index index.html; # 默认首页文件 location / { try_files $uri $uri/ =404; # 如果文件不存在则返回404 } } } ``` 然后重新加载nginx ```shell sudo nginx -s reload ``` 然后打开浏览器`http://localhost:8080/` 访问即可 ### 如何在electron中使用 jessibuca 播放视频 > 在electron中这样就是以file:///路径格式加载,而浏览器加载wasm必须以web形式加载。否则控制台报错: 而使用Electron开发App肯定是希望离线部署的,所以也不能部署到cdn来加载。 解决方法很简单,就是用nodejs创建一个http static file 服务即可。 解决方案: #### 安装 node-static ``` npm i node-static ``` #### 创建静态文件服务器 ```js const {app, BrowserWindow} = require('electron') const static = require('node-static'); const http = require('http'); // 将程序目录下的js目录设为webroot目录 const file = new (static.Server)(__dirname + "/js"); app.whenReady().then(() => { http.createServer(function (req, res) { file.serve(req, res); // 在本机上监听8080端口提供服务 }).listen(8888, "127.0.0.1"); createWindow() }) ``` #### 引用jessibuca 将 jessibuca 的 `dist`文件夹下面的 `js文件`和`wasm文件` 放到 `/js`目录下。 > pro 的文件夹是 pro/js 文件夹 #### 在html中引用 ```html Document
``` ### 如何结合m7s流媒体服务器,obs推流,然后使用播放器播放 #### m7s 下载 [https://m7s.live/download](https://m7s.live/download) #### obs 安装 [https://obsproject.com/zh-cn/download](https://obsproject.com/zh-cn/download) #### 推流配置 obs的推流配置 #### 预览 访问`http://localhost:8080/preview` 页面,即可看到推流的地址,点击进去,就可以预览了。 #### 播放器播放 ### Pro播放器出现“初始化解码Worker超时,initDecoderWorkerTimeout”异常 是因为配置的`decoder`参数不对导致的。 自查: 1. 检查下network下面加载的`decoder解码器`资源是否有正确返回js内容 由图可以发现,js返回的内容是不对的,返回的格式也不对,返回成了html 内容了,不是js 内容 2. 查看下`jessibuca-pro-demo.js`的网络地址是啥。 可以知道了,`jessibuca-pro-demo.js`的网络地址。 3. 基于上面的地址,修改`decoder参数`配置就行了。 > 需要设置的是网络地址,而不是项目中的地址。 ```js const jessibuca = new JessibucaPro({ decoder: '/static/jessibuca/decoder-pro.js', }) ``` 这样配置下就行了。 ### 使用jessibuca 多级路由嵌套时 报错window.Jessibuca is not a constructor 在1级路由下播放器是正常运行的 多级路由就不行了 > 原因是在配置 jessibuca.js 的资源引入的时候,路径配置不对导致的。一般这种情况都是通过相对路径配置的 ```html ``` > 要知道script 配置的是网络路径,不是项目里面的路径。 解决方案: 改成绝对路径去引入 ```html ``` > 这里的`/assets/jessibuca.js`是基于你访问url的路径去配置的。 同理 `decoder` 参数配置也需要配置成网络路径。 ```js const jessibuca = new JessibucaPro({ decoder: '/static/decoder.js', }) ``` ## 延迟卡顿与性能优化 ### 关于延迟丢帧(排除网络延迟) #### 开源版本 1. 支持WASM智能不花屏丢帧,长时间播放绝不累积延迟。 > 请关闭F12控制台看延迟效果。 #### pro 版本 1. 支持WASM智能不花屏丢帧,长时间播放绝不累积延迟。 2. 支持MSE硬解码智能不花屏丢帧,长时间播放绝不累积延迟。 3. 支持Webcodecs硬解码智能不花屏丢帧,长时间播放绝不累积延迟。 ### 对于播放过程中延迟慢慢越来越大的问题 如果是使用的是开源版的,并且是通过wasm解码的,遇到延迟还是慢慢积累,越来越大(从刚开始的0.3到慢慢的几秒),这种情况基本定位出来就是`网络延迟` 导致的。 #### 解释网络延迟 请求流的服务器端的出口带宽不够,导致的到客户端的时候,码率不够,导致播放器端收到的数据不够,这个是由于网络问题导致的延迟。 #### 解决方案 1. 优化网络,提高出口带宽。 2. 降低码率,降低码率,降低码率。 3. pro 可以监听到网络延迟,可以等到延迟达到一个阈值,断开连接,重新请求地址(不推荐使用,依然解决不了延迟问题)。 ### 播放器的延迟时间 实际测试 videoBuffer设置为100 毫秒,实测延迟300-400毫秒。低于1秒,达到毫秒级低延迟。 ### 多分屏超过 6 路不能播放 chrome限制同源http(协议+域名+端口)请求最多6个并发 > 浏览器对同源 HTTP/1.x 连接的并发个数有限制, 几种方式规避这个问题: 1. 通过 WebSocket 协议( chrome下ip会报安全错误,建议域名形式访问,检查下端口范围chrome浏览器是否允许,chrome会默认禁用很多端口)访问直播流,如:播放 WS-FLV 直播流 2. 开启 [HTTP/2.0](https://datatracker.ietf.org/doc/html/rfc7540), 通过 HTTP2协议访问直播流 3. 准备多个域名,每个域名上限6个并发。 #### HTTP/2.0 关于HTTP/2.0的解决方案 1. https://zhuanlan.zhihu.com/p/77803705 2. https://blog.csdn.net/u014552102/article/details/116418790 nginx开启http2 1.https://www.cnblogs.com/flydean/p/15196067.html ### 多个视频一起播放,如果有一个视频地址播放不了会导致其他地址也无法播放 #### 问题 多个ws地址视频一起播放,如果有一个视频地址播放不了会导致其他地址也无法播放(请求被堵塞住了)。 > 一般会出现在ws(s)地址播放不了,导致后续请求被堵塞住了。http(s)没有这个问题。 #### 解决方案 只要合理配置超时时间就行了。就是后面的播放视频的超时时间要大于前面的。 > 当堵塞的播放地址触发超时重播的时候,也就会释放堵塞住的请求,把请求释放出来,给其他的请求使用。 ```js function create(index) { var jessibuca = new Jessibuca({ loadingTimeout: 5 + index * 0.5, // 初始化超时时间, 0.5秒是个经验值,根据实际情况动态调整。 }); } // 创建10个视频 for (var i = 0; i < 10; i++) { create(i); } ``` ### 创建单个视频播放卡顿 是指播放器渲染的帧率太低,比如:1s 显示 3~5 帧,或者渲染完一帧后,过很久才渲染下一帧。 - 网络带宽不足(上行链路或者下行链路网络带宽不足播放) - 播放设备性能不足 - 视频流时间戳问题 #### 网络带宽不足 摄像头 -> 流媒体服务器 -> 播放器 - 摄像头的网络不好,导致推流上行不稳定 - 流媒体服务器的线路质量不好,导致分发不稳定 - 播放器的网络不好,导致拉流下行不稳定 #### 播放设备性能不足 - 增大缓冲区,有助于缓解解码不稳定带来的卡顿 - 尽量硬解码(MSE)(WCS) #### 视频流时间戳问题 播放器一般是严格根据码流中的音视频的时间戳来做音画同步的, 因此,如果码流中的音视频时间戳出现错误,肯定会影响到播放画面的渲染时机。 > 可以先通过设置 hasAudio: false 来排除音频的问题 > 确保视频流的时间戳也得增加。 ### 创建多个以上播放实例会非常卡顿,还会导致页面黑屏 例如 h265,1280*720,wasm 肯定会卡顿的。 建议降低分辨率。还需要增大videoBuffer 大小。 #### 可能存在的问题 1. 分辨率过高 2. 带宽是否跟得上 3. 是否是H265编码 #### 自查 监听下`stats` 事件,查看 `fps` 是否达到了预期的值。 #### h265 优化方案 1. 降低分辨率 2. 增大videoBuffer大小,一般1s,2s,3s都是可以的 3. 设置hasAudio 为false,不demux和decode音频数据。 4. ~~条件允许(支持OffscreenCanvas)也可以配合设置 forceNoOffscreen 为 false 开启离屏渲染模式,提升性能。~~ 5. pro版本支持H265硬解码(需要显卡支持)。 http://jessibuca.monibuca.com/player-pro.html 6. pro版本支持SIMD解码,尤其是1080p及以上的分辨率,会有很强的效果。http://jessibuca.monibuca.com/player-pro.html 7. pro版本支持多线程(wasm/simd),可以开启多线程解码,提升性能。http://jessibuca.monibuca.com/player-pro.html 7. 如果是服务器端出口带宽跟不上的情况,增大服务器端出口带宽。 > 某些显卡在支持OffscreenCanvas上面会存在问题,所以谨慎使用。 > https://github.com/langhuihui/jessibuca/issues/227 #### h264 优化方案 1. 降低分辨率 2. 增大videoBuffer大小,一般1s,2s,3s都是可以的 3. 设置hasAudio 为false,不demux和decode音频数据。 4. ~~条件允许(支持OffscreenCanvas)也可以配合设置 forceNoOffscreen 为 false 开启离屏渲染模式,提升性能。~~ 5. 如果是https情况下 设置 useWCS 为 true。 6. 如果是http情况下 设置 useMSE 为 true。 > 某些显卡在支持OffscreenCanvas上面会存在问题,所以谨慎使用。 > https://github.com/langhuihui/jessibuca/issues/227 ### 播放过程中出现了延迟 #### 对于开源版 - wasm解码`做了`丢帧(消除延迟)`逻辑,保证`前台`长时间在设置的延迟范围内 - mse解码`没有`做丢帧(消除延迟)逻辑 - wcs解码`没有`做丢帧(消除延迟)逻辑 > 浏览器切换到后台(最小化,tab窗口被关闭),导致的窗口不可见的情况,会导致延迟增大。 #### 对于pro版 - wasm解码`做了`丢帧(消除延迟)逻辑,保证`前台和窗口不可见的情况下`长时间在设置的延迟范围内 - mse解码`做了`丢帧(消除延迟)逻辑,保证`前台和窗口不可见的情况下`长时间在设置的延迟范围内 - wcs解码`做了`丢帧(消除延迟)逻辑,保证`前台和窗口不可见的情况下`长时间在设置的延迟范围内 > pro播放器在窗口不可见的情况下是利用黑科技实现的消除延迟的逻辑。 ### 关于延迟造成的原因 可能的原因 - 网络加载的延迟 - 软解码的延迟 - 渲染的延迟 一般来说,如果在用户`网络环境`较好的情况下,渲染由于使用了WebGL,很难造成瓶颈(操作很单一),其中一般会因为软解码性能不足造成不停卡顿及延迟。 优化因为软解码性能不足造成的延迟,我们一般从几个地方着手: - 视频的profile:相比于main/high而言,baseline不包含B帧,解码消耗更低 - 视频帧率:过高的帧率会造成软解码跟不上,可以试着降低帧率,例如24fps - 视频码率:码率越高,视频富含的细节越多,也越清晰,但是会消耗更多的解码性能,可以试着降低码率 - 视频分辨率:过高的视频会造成单帧传递的数量极大 #### 解决方案 - 可以使用jessibuca pro 的 simd 解码,尤其正对于HEVC的1080p的解码能力提升很多。 - jessibuca pro 还支持 mse 解码 HEVC(H265) ### 关于超低延迟(300ms)以内 目前想要超低延迟,只能使用wasm解码。目前开源版的超低延迟最多只能支持到`1s`以内 推荐的配置 #### 对于开源版 ``` { videoBuffer:0.1 } ``` #### 对于PRO pro 由于使用了解码性能更强的simd解码,所以推荐使用simd 解码来提升解码性能,所以可以做到更低的延迟(300ms以内)。 ``` { videoBuffer:0.1, videoBufferDelay:0.2 useSIMD:true } ``` ### 首屏打开慢 - 网络不好,导致拉流慢。 - 首帧不是I帧,播放器为了等I帧。 - 流媒体服务器的线路质量不好,导致分发不稳定。 ### 理解loadingTimeout 和 delayTimeout #### loadingTimeout loadingTimeout 是指在`播放器在请求url的时候`,接口是返回200状态码了,但是数据还迟迟没有推送给web端 ,如果在`loadingTimeout` 时间内,没有收到流数据,则会抛出`loadingTimeout`错误。 #### delayTimeout delayTimeout 是指在`播放器播放过程中`,如果在`delayTimeout`时间内,没有收到流数据,则会抛出`delayTimeout`错误。 #### loadingTimeoutReplay(delayTimeoutReplay) 与 loadingTimeoutReplayTimes(delayTimeoutReplayTimes) > 如果在`loadingTimeout`时间内,没有收到流数据,则会抛出`loadingTimeout`错误,如果设置了`loadingTimeoutReplay` > ,则会重新播放,会重试`loadingTimeoutReplayTimes`次。 ### 多屏需求 #### 如果不需要播放音频 可以设置`hasAudio`为`false`,这样就不会解码音频数据了,可以提升性能。 ### 页面首次加载超时检测 目前播放器的默认配置是 ``` { loadingTimeout: 10, loadingTimeoutReplay:true, loadingTimeoutReplayTimes:3 } ``` > 如果想要如果想无限次重试,可以设置loadingTimeoutReplayTimes为-1 ### 页面播放过程中超时检测 目前播放器的默认配置是 ``` { heartTimeout: 10, heartTimeoutReplay:true, heartTimeoutReplayTimes:3 } ``` > 如果想要如果想无限次重试,可以设置heartTimeoutReplayTimes为-1 ### 加载视频等待画面时长过长 可能的原因: 1. 检查下请求地址是否正常,是否有返回数据,以及相应的时长。 2. 检查下首帧是否推送的I帧数据,如果没有I帧数据,会导致等待画面时长过长。 ### 在已经使用硬解码基础上,播放多路视频,会出现卡顿,内存开始飙升 > 在播放1路到4路的情况下,硬解码是没有问题的,但是播放到5路以上,就会出现卡顿,内存飙升的情况。 这种情况大概率是因为显卡的解码性能跟不上导致的。 解决方案 1. 升级显卡 2. 降低分辨率/帧率 3. 降低播放路数 > 如果是 pro 的话,可以通过配置配置 `最大缓冲区丢帧` 参数,把参数调整大些,来对抗卡顿的情况。 ### 关于使用window电脑,在使用显卡解码(H264/H265)的时候,会出现显卡解码器不稳定的情况,造成画面卡顿 > 会出现,同一个流,同样的访问页面,在不同的电脑上面播放的时候,会出现差异性。 #### 现象 正常播放的GPU资源损耗 异常的GPU资源损耗 可能的原因 #### 操作系统 1. window 10 可能性比较大 2. window 11 老版本 #### 显卡驱动 1. 显卡驱动版本过低 #### 浏览器版本 1. 浏览器版本过低 #### 解决方案 1. 升级操作系统,如果是11的话,升级到最新版本(不要用装机版本) 2. 升级显卡驱动(建议升级到最新版本) 3. 升级浏览器版本(建议升级到最新版本) ### 轮训业务推荐配置 如果业务上面有轮训的业务需求,比如 30秒轮训一次,为了尽可能的减少资源开销,可以优化如下配置 ``` { hasAudio: false, // 关闭音频解码 } ``` ### 播放直播流的时候,一上来会出现卡顿,丢帧,画面突然快进的情况 一般这种情况是由于服务器端一上来就推送了大量的数据过来,播放器端会基于缓存机制,触发丢帧逻辑,造成了卡顿情况。而且画面上面会一下子快进了很多帧。 导致原因: 1. gop设置的过大,导致流媒体服务器端一上来就推送了一个gop的数据过来。 解决方案: 1. 检查下流媒体服务器端的gop设置,是否过大,如果是直播流,建议设置成1-2秒的gop时间。 #### 什么是gop > 在音视频编码中,GOP 指的是 Group of Pictures(图像组),是视频编码中的一个重要概念。 ```shell I B B P B B P B B I ... ``` GOP 长度 = 两个 I 帧之间的帧数(例如 30 表示每 30 帧一个 I 帧)。 ## 音频问题 ### 如果只需要播放音频数据 > jessibuca pro 已经有了单独的音频播放器,支持播放音频数据 音频直播流(支持移动端(平板端)息屏和后台播放) https https://jessibuca.com/pro/audio-player-demo.html http http://jessibuca.monibuca.com/pro/audio-player-demo.html ### g711系列的音频,听起来为啥都是杂音。 确认下是否是服务器端推送音频数据的时候,把g711a 的推 成了g711u的格式,或者反过来了。导致播放器在解码格式的时候,听起来全是杂音。 ### 播放过程中,音频会出现卡顿的情况 - 检查下流数据是否存在丢数据的情况(推流端漏数据) - 检查下推流过来的音频和视频数据是否按照正常的时间顺序给到播放器端的(会存在流数据是先给段500ms视频数据,然后接着给500ms音频数据),这样会导致播放器端不是按照正常的顺序来解码和播放音视频数据的。 #### 解决方案 - 如果是推流端漏数据导致的,可以看下推流端是什么协议推流的,如果是`rtsp协议`推流,因为默认采用的udp,不能保证数据的完整性,可以尝试使用`rtmp协议`推流(使用的是tcp)推流。 - 如果是推流端音视频数据不是按照正常的时间顺序给到播放器端的,可以检查下推流端的音视频数据是否是按照正常的时间戳来推送的。 ## 录制与截图 ### 将录制的视频保存在安卓手机相册中,显示的时长为0,并且无法播放。 https://github.com/langhuihui/jessibuca/issues/126 现象:将录制的视频保存在安卓手机相册中,显示的时长为0,并且无法播放。但是在对应的文件路径中找到源文件是能播放的,但是依然不显示时长。 这是录制的是webm 格式的视频,对于移动端的兼容性不是很好。等后续支持录制MP4格式(MPEG-4)的视频录制就可以解决这个问题了。 另外: > MP4格式支持在IOS VLC播放器显示时长播放,Android VLC播放器无法显示时长播放,PC VLC播放器可以播放 > Jessibuca Pro 可以录制MP4格式(MPEG-4)的视频,就可以解决这个问题了。 ### 无音频的flv视频流,无法录制,录制的文件大小都是0 原问题:https://github.com/langhuihui/jessibuca/issues/128 - 1、无音频视频录制不成功,文件大小为0 - 2、静音视频录制不成功,文件大小为0 解决方案: ### 如果没有音频数据 设置 hasAudio 为false 就可以解决了。 > 目前如果声音在静音或者没有音频数据的时候,一定要设置hasAudio,不然MediaRecorder会录制失败。 ### UniApp 或者内嵌其他App(XX小程序) 里面webview,需要截图下载或者录制视频下载。 > 由于webview的限制,无法像浏览器那样直接截图,或者录制视频可以通过a.download 下载。 > 暂不支持微信/飞书的webview 环境下录制视频下载。 解决方案: 对于截图: 可以通过`screenshot(filename, format, quality,'base64')`返回base64数据,然后通过`jsbridge`传给app,app再通过`base64` 转成图片,然后保存到本地。 > XX小程序可以通过`postMessage` 将base64传给小程序,小程序再使用系统级别api保存到本地。 对于录制视频: 目前 开源版暂不支持录制的视频返回`blob`格式。 > pro版本支持录制视频返回`blob`格式。 可以通过`jsbridge`传给app,app再通过`blob`转成视频,然后保存到本地。 > XX小程序可以通过`postMessage` 将blob转换成ArrayBuffer传给小程序,小程序再通过系统级别api(wx.writeFile)保存到本地。 ### 飞书/微信/其他 webview h5 环境下实现截图下载或者录制视频下载。 > 同样是禁用了a标签的下载功能,所以无法通过a标签的download属性来实现下载了。 #### 图片 直接用 `` 弹出浮层,提示用户长按保存,这在所有 WebView 中都可靠工作 #### 视频 由于 Blob 体积大且 WebView 限制多,最稳妥的方案是走服务端中转:上传 Blob → 返回临时 URL → window.location.href = url 触发浏览器原生下载行为。 ## 自动播放与声音策略 ### 关于 play() failed because the user didn't interact with the document first. 错误 背景:用户希望打开页面的时候就直接自动播放`带音频`视频(单屏或者多屏),但是浏览器的自动播放策略是,必须是用户手动触发了事件之后,才能自动播放。 会抛出`DOMException: play() failed because the user didn't interact with the document first. https://goo.gl/xX8pDD` 错误。 > 手动刷新页面也会出现这个异常。 > 这个报错是浏览器的规范,浏览器规定,必须要用户主动触发才能播放带音频的视频。 优先使用`canvas`进行渲染或者静音状态。这样就可以规避掉浏览器的规范了。 > mse、wcs是硬解码,wasm是软解码 #### 为啥其他大厂的播放页面打开就能播放? 1. 可以通过在Chrome浏览器地址栏输入 chrome://media-engagement 来查看您网站的“媒体参与度”评分。评分越高,您的网站获得“自动播放带声音”权限的可能性就越大。 2. 对于 Safari 浏览器, 可以通过配置网站的权限,授权网站自动播放声音, 具体设置如下:【地址栏右键】 =>【此网站设置】=>自动播放】 #### 解决方案 1. 静音状态下播放,添加一个交互事件,让用户手动触发下,再去播放视频。 2. 浏览器允许点击连接跳转打开页面允许自动播放并支持声音。 可以看下demo实现 https https://jessibuca.com/pro/demo-auto-play.html http http://jessibuca.monibuca.com/pro/demo-auto-play.html ### 关于浏览器报:The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. 错误 背景:用户希望打开页面的时候就直接自动播放`带音频`视频(单屏或者多屏),软解码音频的时候。但是浏览器的自动播放策略是,必须是用户手动触发了事件之后,才能自动播放。 浏览器会抛出:`The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://goo.gl/7K7WLu` 错误 #### 解决方案 1. 静音状态下播放,添加一个交互事件,让用户手动触发下,再去播放视频。 2. 浏览器允许点击连接跳转打开页面允许自动播放并支持声音。 可以看下demo实现 https https://jessibuca.com/pro/demo-auto-play.html http http://jessibuca.monibuca.com/pro/demo-auto-play.html ### 支持浏览器打开连接立即播放视频 在浏览器的规范里面,是不允许自动播放的,必须要用户主动触发才行。 所以说,硬解码是没法支持的。 > 可以用软解码去实现 配置如下参数下: ``` useMSE:false, useWCS:false ``` > 但是声音这块也是没法支持的,因为声音是需要借助浏览器提供的API去播放。 ### The play() request was interrupted because video-only background media was paused to save power 错误 通常发生在网页应用尝试自动播放视频时,但浏览器出于节能目的暂停了视频的播放。 可以看下[chrome的自动播放策略](https://developer.chrome.com/blog/autoplay?hl=zh-cn) 1. 浏览器的自动播放策略:许多现代浏览器,尤其是移动设备上的浏览器,会限制在不同条件下自动播放媒体内容,尤其是如果媒体内容没有与用户的互动。这是为了节约数据和电池。 2. 视频内容的属性:如果视频是静音的或不包含音频轨道,某些浏览器可能会允许自动播放。但如果视频包含音频,且页面没有得到用户的明确互动(如点击),浏览器可能会阻止自动播放。 3. 电源节约模式:在某些设备上,如果启用了电源节约模式,浏览器可能会限制背景媒体的播放,以减少电量消耗。 解决方案: 1. 用户交互:确保在用户与页面互动(如点击按钮)后再播放视频。 2. 静音视频:如果视频不需要音频,可以尝试将其设置为静音。 3. 检查浏览器设置:用户可以查看浏览器的隐私或安全设置,看看是否有限制自动播放媒体的选项。 4. 检查设备设置:用户可以查看设备的电源设置,看看是否有限制自动播放媒体的选项。 5. 顶级帧可以将自动播放权限委托给其 `iframe`,以允许有声自动播放(测试了没有啥效果)。 ```html ``` 这样就可以触发全屏了。 ### 关于IOS不能系统全屏 IOS 全屏效果 > IOS是不存在全屏API的,调用全屏会进入系统播放模式 解决方案: 可以通过配置`useWebFullscreen:true` 使用css全屏的方式进行模拟(即网页内全屏)。 参考demo: http://jessibuca.monibuca.com/mobile-fullscreen.html #### IOS实现全屏效果 1. 业务层自己修改 `container`的宽高 + `resize()` 方法实现全屏效果 > 缺点:没法使用到播放器提供的底部控制栏,因为控制栏不会跟着变化。 2. 参数`useWebFullScreen`配置为`true` > 播放器会检测当前环境是否支持系统级别的全屏方法,如果不支持,则会使用web全屏 > `jessibucaPro播放器`内部会自动判断,根据当前环境是否支持系统级别的全屏方法,来降级选择使用web全屏。 ### Android端webview全屏调用无效问题 会抛出:`TypeError:Fullscreen is not supported`的异常错误。 > android webView内默认是没有实现视频全屏的,调动dom.requestFullscreen没有任何响应,这个会表现为点击全屏按钮无效 解决方案: 该问题的解决必须依赖native端的开发,具体实现请参考以下方式WebView 实现全屏播放视频的示例代码 https://cloud.tencent.com/developer/article/1741520 ### IOS端无法内联播放(行内播放) > 对于webrtc模式下 > canvas 渲染不存在这样的问题 ios10以下不支持内联播放 解决方案: 如果在webview内该属性不生效,则说明webview没有开启该属性,请找自己app native开发同学给webview容器对应的setting设置为true, 具体实现参考一下文档 https://developer.apple.com/documentation/uikit/uiwebview/1617960-allowsinlinemediaplayback https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/1614793-allowsinlinemediaplayback ### Failed to execute 'requestfullscreen' on 'Element': APl can only be initiated by a user gesture. 这个错误是因为全屏操作必须是用户手动触发的,不能是程序触发的。 ### 在 iOS Hybrid App 的 WebView 中默认全屏播放 问题表现:在 App WebView 里播放视频默认全屏播放。 解决方案: 1. 配置 WebView 的参数 allowsInlineMediaPlayback = YES 允许视频行内播放,即禁止 WebView/UiWebView 强制全屏播放视频。 ### 视频激活播放后强制全屏 在单击视频激活播放后,直接全屏播放,通常出现在 Android、iOS 的微信、手机 QQ、QQ 浏览器等浏览器中。 解决方案: 1.如需实现页面内(非全屏)播放,需要在 video 标签中加入 playsinline 和 webkit-playsinline 属性, > Jessibuca Pro 版本 默认会在 video 标签中加上 playsinline 和 webkit-playsinline 属性。iOS10+ 识别 playsinline 属性,版本小于10的系统识别 webkit-playsinline 属性 > 由于 Android 的开放性,出现了许多定制浏览器,这些属性不一定生效。 ### 视频无法被其他元素覆盖 无法将其他元素覆盖到视频区域上,播放器控件为浏览器自带控件。 解决方案: 1. 可以使用ws播放地址 + wasm+canvas的方式播放视频,这样视频是渲染在canvas上面的。 ### 播放器出现广告、下载、推荐视频等内容 视频在播放、暂停、结束时,视频区域出现广告内容,或者下载按钮。 解决方案: 1. 可以使用ws播放地址 + wasm+canvas的方式播放视频,这样视频是渲染在canvas上面的。 ### 全屏相关问题 这里主要介绍全屏相关的问题,首先需要了解屏幕全屏(系统全屏)、网页全屏(页面全屏、伪全屏)两个概念。 #### 屏幕全屏 是指在屏幕范围内全屏,全屏后只有视频画面内容,看不到浏览器的地址栏等界面,这种全屏需要浏览器提供接口支持。支持屏幕全屏的接口有两种,一种称为 Fullscreen API,通过 Fullscreen API 进入屏幕全屏后的特点是,进入全屏后仍然可以看到由 HTML CSS 组成的播放器界面。另一种接口为 webkitEnterFullScreen,该接口只能作用于 video 标签,通常用于移动端不支持 Fullscreen API 的情况,通过该接口全屏后,播放器界面为系统自带的界面。 #### 网页全屏 是指在网页显示区域范围内全屏,全屏后仍可以看到浏览器的地址栏等界面,通常情况下网页全屏是为了应对浏览器不支持系统全屏而实现类似全屏的一种方式,所以又称伪全屏。该全屏方式由 CSS 实现。 #### 支持程度 1. x5 内核(包括 Android 端的微信、手机 QQ 和 QQ 浏览器):不支持 Fullscreen API,支持 webkitEnterFullScreen,全屏后进入 x5 内核的屏幕全屏模式。 2. Android Chrome:支持 Fullscreen API,全屏后进入带有腾讯云播放器 UI 的屏幕全屏模式。 3. iOS (包括微信、手机 QQ、Safari):不支持 Fullscreen API,支持 webkitEnterFullScreen,全屏后进入 iOS 系统 UI 的屏幕全屏模式。 4. IE8/9/10:不支持 Fullscreen API,不支持 webkitEnterFullScreen,全屏为网页全屏模式。 5. 桌面端微信浏览器:不支持 Fullscreen API,不支持 webkitEnterFullScreen,全屏为网页全屏模式 (macOS 微信浏览器目前不支持任何全屏模式)。 6. 其他桌面端现代浏览器:通常支持 Fullscreen API,全屏后进入带有腾讯云播放器 UI 的屏幕全屏模式。 ## 画面异常与渲染问题 ### 视频颜色变灰色(软解码) 原因 - 视频流的格式 不是 yuv420p 可能的视频格式是:yuvj422p 格式。 可能是webgl 渲染的问题导致的。 > jessibuca pro 支持video 标签渲染数据,不会出现视频颜色变灰色的情况 ### 视频渲染发绿(软解码) #### 原因 - 对于宽度不是8的倍数的时候就会出现这样的问题 原问题: https://github.com/langhuihui/jessibuca/issues/152 例如:540x960 分辨率 在使用WebGL对YUV420P进行渲染时,WebGL图像预处理默认每次取4字节的数据,但是540x960分辨率下的U、V分量宽度是540/2=270不能被4整除,导致绿屏。 #### 解决方案 1. ~~可以通过设置`gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);` 的方式来解决,但是会损耗一部分性能。~~ 2. ~~将`openWebglAlignment` 设为 `true`。~~ 3. 最新解决方案,程序会自动检查分辨率,如果不是标准的分辨率,会自动更新webgl 渲染规则 4. jessibuca pro 支持video 标签渲染数据,不会出现视频渲染发绿的情况 ### 有数据,但是没有画面出来 可能的原因 #### 时间戳导致的 通过监听`stats` 事件,查看下面的`ts` 看是否都是相同的时间戳。 #### 开启调试 debug:true 通过设置` debug:true `,然后重新播放视频源,通过日志查看是否有报错信息。 ### 对于出现渲染页面直接倒过来180度的解决方案 #### 问题 通过webgl渲染(canvas)的时候,会出现部分机型画面倒挂,一般这种情况都是出现在 `wasm` 渲染模式上面的。 #### 原因 这是由于在部分A卡上面,webgl渲染会存在兼容性bug,导致了画面180度倒挂。 #### 解决方案 1. 如果是h264的源,建议使用MSE 硬解码 通过设置`useMSE:true`,使得渲染元素是video标签。 2. 如果是h265的源,推荐使用 `jessibuca pro` 目前pro 版本支持 `mse` `wasm` `webcodecs`解码之后通过video标签渲染。 3. 提供一个操作按钮,让用户可以手动的旋转画面,播放器提供了`setRotate`方法,可以通过`setRotate`方法旋转画面。 ### 关于绿屏和花屏 现象: 播放画面出现图像紊乱,大面积的异常颜色的方块图,或者绿屏现象 可能得原因: #### 流媒体服务器-> 播放器端 - 网络不好,编码后的数据发不出去,导致丢失参考帧。 - 推过来的流,不是从i帧开始的,会导致首帧解码出现绿屏或者花屏的情况。 - 推过来的流,码流中视频尺寸发生变化,会导致绿屏或者花屏的情况。 - 码率不够,比如我们告诉视频编码器要输出1280 720高清分辨率的画面,但同时要求它只用 200 kbps的码率*(码率是指编码器每秒产生的视频数据大小 ),编码器此时能做的事情就是无底线地降低画质,就会导致大面积的马赛克。 - 传输切分为多个NALU单元的帧,解码器会认为这样的帧是不完整的,会出现局部绿屏的情况。 #### 推流端->流媒体服务器 - 如果是`rtsp协议`推流,因为默认采用的udp,不能保证数据的完整性,可以尝试使用`rtmp协议`推流(使用的是tcp)推流。 #### 播放器端 - 系统低内存,队列里面无法承受更多的帧数据。 - 硬编硬解的兼容性问题 #### 自查 1. 同样的播放地址,用客户端播放器(例如客户端的vlc)播放是否正常,检查是否流本身的问题。 2. 同样的播放地址,用其他浏览器播放是否正常,检查是否浏览器的问题,检查是否浏览器的问题。 3. 同样的播放地址,用其他的web播放器([video.js](https://videojs.com/),[xgplayer.js](https://h5player.bytedance.com/) ),播放是否有问题,检查是否Jessibuca的问题。 > 千万不要web端跑的是http协议的 ,然后用rtsp协议这样的协议去vlc播放测试,这也是毫无意义的,因为不同的封装协议,不同的传输协议,不同的编码协议,都会导致不同的问题。 > 一定要用同样的协议,同样的封装,同样的编码,同样的传输协议,去测试,这样才能正常是否是流本身的问题导致的绿屏。 ### 黑屏,但是网速一直有数据 检查下播放地址,有没有带文件后缀,目前播放器是根据后缀来分析协议的,例如`.flv`后缀分析成flv格式。 对于地址如果没有带任何后缀的,播放器会默认识别为`m7s`的私有格式。 需要检查下 `isFlv` 参数。 #### 没有文件后缀,但是希望解析成flv协议。 配置`isFlv:true` 就行了。 #### 其他可能性 如果不是上述可能的原因,就看下`f12`控制栏上面是否有报错信息。 > 建议开启`debug:true` 参数,这样可以看到更多的日志信息。 ### PC电脑端播放视频,整个显示器会突然白屏一下 1. 看下浏览器有没有关闭硬解码。 2. 看下显卡驱动是不是好久没有更新了。 > 显卡驱动太老的话,会有可能导致硬解码出现问题,导致整个显示器画面白屏下的。 ### 浏览器播放视频过程中,整个显示器会突然的白屏下 > 大概率是显卡驱动问题,可以尝试升级显卡驱动,或者降级浏览器版本。 可以看下这个解决方案: https://blog.csdn.net/DYxiao666/article/details/136072932 ### 关于分辨率高的视频在设置container的宽高较小的时候,会出现锯齿状的画面效果。 > 这个问题是出现在,分辨率比较大(1080p及以上),在小的可视区域显示(300*400) ,就会出现局部锯齿状的画面效果。 暂时没有找到好的解决方案,如果有人有好的解决方案,可以分享出来,方便大家一起解决,可以联系我微信:bosswancheng ### 关于一些特殊分辨率的视频播放不了 > 原因在于web端不支持`基数分辨率`的流,尤其是 wasm、webcodec,都不支持解码`基数分辨率` 基数分辨率类似:`1923*1081`、`1281*723` 这种特殊分辨率 正常的分辨率类似:`1920*1080`、`1280*720` 这种常规分辨率 ### 播放4k的视频源,发现有一半/三分之一的画面是绿屏/花屏/马赛克的效果 如图: 可能得原因: 1. 流媒体服务器端采用了分包拆帧来传输流数据,播放器端没有多包拼帧。 2. 流媒体服务器端缓冲区设置过小,导致数据包丢失。 #### 解决方案 1. 检查下流媒体服务器端的配置,是否开启了分包拆帧。 2. 检查下流媒体服务器端的缓冲区设置,是否过小。 > 如果修改过了流媒体服务器端的缓冲区设置之后还是不行的话,去看下系统的内核最大缓冲区设置是不是过小导致的,也需要配合一起修改下。 ### 硬解码MediaSource/WebCodecs花屏,软解码可以正常解码且渲染正常 可能得原因: - 流的分辨率是不规范的分辨率,例如:1920 * 1088, 这种分辨率高度不是 16 的倍数, - H.264/H.265 等视频编码标准通常要求 宏块/CTU 对齐: - H.264 使用 16×16 的宏块; - H.265 使用 64×64 的 CTU(但很多解码器仍然会按 16 对齐)。 - 1920×1080 是标准的 1080p,能整除 16。 > 但是 1920×1088 的高度 1088 不能被 16 整除,导致解码器在处理最后一行宏块时,无法正确参考上方的宏块,从而引发花屏。 ### 播放器出现黑边 现象:播放视频时,播放器区域内出现黑边。 > 主要出现在IOS系统的Safari浏览器中。 解决方案: 设置播放器的尺寸比率与视频实际的尺寸比率一致, 例如,视频的分辨率为1280 x 720,播放器的尺寸可以设置为640 x 360或者1280 x 720等,只要满足16:9(1280:720)的宽高比,就能完全显示视频,播放器不会出现黑边。如果视频自带黑边,则需要在转码的时候切掉视频的黑边内容,改变视频的分辨率。 ## WebRTC ### WebRTC 原生H265支持情况 > ~~WebRTC标准是不支持h265的。~~ > Windows10/11 的Google(138+) 、MacOS的 Google(138+)/Safari(26.5) 已经支持原生WebRTC H265 > jessibuca pro 版本结合M7S已经支持了。欢迎测试使用。 http://jessibuca.monibuca.com/player-pro.html #### 相关资料 [is-webrtc-hevc-supported](https://chris.hiszpanski.name/posts/is-webrtc-hevc-supported/) [vdo.ninja/h265](https://vdo.ninja/h265) #### 小结 [document-webrtc-h265](https://jessibuca.com/document-webrtc-h265.html) #### 关于播放webrtc 的 H265格式的视频(原生浏览器不支持的情况下) 目前 `pro版本` 是支持`[M7S流媒体服务器](https://m7s.live/)`来播放 webrtc 的 H265格式的视频。 > 同时也支持音频 是借助DataChannel实现的。 可以看网友的基于DataChannel 实现的 H265 的方案。 https://juejin.cn/post/7215608036394614844 > 当然 pro 可以做到1s以内的更低延迟。 > 对于ZLMediaKit,目前官网版本是不支持DataChannel的,需要自己实现。如需要对接集成,可以联系Pro作者:bosswancheng ### 关于播放webrtc 报: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to parse SessionDescription. Duplicate a=msid lines detected 解决方案:https://blog.csdn.net/dualvencsdn/article/details/137049065 ## 跨域网络与安全策略 ### http vs https #### http 在http 协议里面,是不能播放https 或者 wss 协议的,会报跨域报错。 #### https 在https 协议里面,是不能播放http 或者 ws 协议的,会报跨域报错。 ### chrome无法访问更私有的地址 触发了 Chrome 安全策略 - 私有网络控制(CORS-RFC1918) 升级chrome 91后,默认无法从开放的地址往更私有的地址访问。 比如从公网访问web,播放内网的流媒体地址。 | 外网访问内网 | http | https | |--------|----------------|-------------| | http | Chorme 94禁止 | Chorme 94禁止 | | https | 安全内容加载不安全内容,禁止 | 取跨域策略 | ```shell Access to fetch at 'http://192.168.0.2:8000/live/test.flv' from origin 'http://jessibuca.monibuca.com/' has been blocked by CORS policy: The request client is not a secure context and the resource is in more-private address space `private`. ``` 打开浏览器的 > chrome://flags/#block-insecure-private-network-requests 将这项设置为关闭 > 将Block insecure private network > requests配置禁用掉(Disable)。但是一定要注意,修改了配置后必须点击Chrome此时在右下角出现的“重启”(Restart)按钮才能生效。自己主动关闭浏览器全部页面再打开是不会触发Chrome更新配置的。 ### 监听请求流的失效(404)或者500报错 可以监听`play`方法的`catch` ```js jessibuca.play(url).catch((err) => { // err 就是错误信息 }) ``` > 注意:这个是初次请求的时候,如果流失效,会触发`catch`,如果流有效,但是后面流失效了,不会触发`catch`。 > 播放过程中流发生500报错,会触发`error`事件。 > 播放过程中由于网络切换(网络动荡),导致流失效,会触发`error`事件。 ### 关于移动端(H5)切换网络的时候,播放器会触发什么事件。 #### http请求 会触发`fetchError`事件 ```js jessibuca.on("fetchError", function (msg) { console.log('fetchError:', msg) }) ``` > pro 版本只需要监听一个事件 playFailedAndPaused 即可 #### websocket请求 会触发`websocketError`事件 ```js jessibuca.on("websocketError", function (msg) { console.log('websocketError:', msg) }) ``` > pro 版本只需要监听一个事件 playFailedAndPaused 即可 #### 小结 或者可以通过监听`error`错误事件,来监听所有的错误事件。 ```js jessibuca.on("error", function (error) { console.log('error:', error) if (error === jessibuca.ERROR.fetchError || error === jessibuca.ERROR.websocketError) { // 这里统一的做重连。 jessibuca.destroy().then(()=>{ jessibuca = null; jessibuca = new Jessibuca(); jessibuca.play(url); }); } }) ``` > pro 版本只需要监听一个事件 playFailedAndPaused 即可 ```js jessibuca.on("playFailedAndPaused", function (msg) { console.log('playFailedAndPaused:', msg) // 直接重新播放失效地址。 jessibuca.play(url); }) ``` ### Websocket 1006 异常断连 1006 是websocket的一个异常码,表示连接异常断开。 | 状态码 | 名称 | 描述 | |------|----------------|-------------------| | 1006 | CLOSE_ABNORMAL | 用于期望收到状态码时连接非正常关闭 | > WebSocket 关闭状态码 1006 是由于服务器在接收到客户端的连接请求后,在建立连接前发生了错误导致连接失败。 #### 可能的原因 1. 在客户端和WebSocket服务器之间的全双工连接中,有时候连接上可能没有数据流。在这个时候,网络中介可能中止连接。 > 就是可能会在一段时间内没有数据流,导致网络中介认为连接已经断开了。 > 也有可能是播放器端进程卡住了,导致接受推流的速度变慢,导致流媒体推流端推流到播放器变慢,甚至直接没法接收到流媒体传输过来的数据,导致网络中介认为没有流数据了,为连接已经断开了,也有可能是服务器端检测到堆积量过大,从而断开了ws连接,从而导致浏览器抛出了1006 错误。 > 有可能是本地的网络带宽上限要低于流媒体服务器端推流的码率,比如流媒体服务器端推流的码率是2M,而本地的网络带宽只有1M,这样就会有1M的数据堆积没法到达播放器端,导致服务器端堆积过多就会断开连接,然后播放器抛出了1006 > 错误。 > 通讯层(浏览器底层)断连了,但是应用层还是连接着,这个时候浏览器就会抛出1006错误。 2. 大多情况都是因为websocket 连接在nginx 配置的 proxy_read_timeout 内没有收到数据,nginx主动发起的连接断开(不是客户端主动断开,也不是服务端主动断开的) > client->proxy->ws-server 如果proxy和ws-server之间通信有问题 client就会收到1006错误码。 3. 网络连接问题:网络中断、防火墙设置等因素可能导致WebSocket连接异常关闭。 4.在播放倍率流的时候,如果服务器端是高倍率推流,比如8倍,这个时候如果电脑的性能跟不上,就会导致解封装和解码跟不上,因为js是单线程的,会导致解码和解封装的速度跟不上,导致堆积量过大,从而堵塞了接收流数据,从而触发了服务器端数据堆积过大,从而从物理层断开ws连接,从而导致浏览器抛出了1006 错误。 #### AI 回复的: 1. 服务器端程序崩溃或异常关闭:如果WebSocket服务器在处理连接请求时崩溃或异常关闭,连接将被重置,导致1006错误。 2. 客户端网络连接问题:客户端与服务器之间的网络连接出现故障,如网络断开、防火墙拦截等,也可能导致连接重置并出现1006错误。 3. 服务器端资源限制:如果服务器端资源受限,如内存不足、线程数达到上限等,可能导致服务器关闭连接以释放资源,从而引发1006错误。 4. WebSocket服务器配置问题:WebSocket服务器配置错误,如端口号不正确、认证设置不正确等,也可能导致连接重置并出现1006错误。 #### 排查 ##### 服务器端原因: 这个错误通常是由于服务器端的问题导致的,比如服务器端的程序出现了 bug 或者服务器端的硬件出现了故障。 这种情况下可以考虑检查服务器端的程序和硬件是否正常工作, 查看`服务器端的日志`和`监控数据`来找出问题所在。 ##### 网络原因 检查网络是否正常,网络是否稳定,网络是否有丢包,网络是否有延迟等。 #### 解决方案 1. 需要在nginx加入一段proxy的timeout超时设置,加了500s 2. `Pro播放器`支持内部检测到1006错误,会内部自动重连。 #### 资料 1. https://zhuanlan.zhihu.com/p/351747258 ### 火狐(firefox),chrome,等浏览器报ws地址连接不上 可能得原因: 1. 如果ws地址是`IP`的话,检查下`端口`是否是浏览器禁用的端口端。 2. 检查下`https` 下面是否请求的 `wss`地址,`http`下面是否请求的`ws`地址。 ### 播放内网https地址报错(ERR_CERT_COMMON_NAME_INVALID 错误) > 一般这种情况是浏览器端不认可https证书的缘故。 解决方案: 方案1:修改自签名证书 https://www.dyxmq.cn/network/err_cert_common_name_invalid.html 方案2: 通过chrome 浏览器设置 `隐私和安全` -> `允许显示不安全内容` 配置让浏览器端认可这个内网https证书。 ### 测试的时候遇到请求的连接(播放地址)跨域报错 #### 方法1:使用扩展程序 安装`CORS`扩展: 在`Chrome Web Store`中搜索并安装一个允许跨域请求的扩展程序,如“`CORS Unblock` ”或“`Allow CORS: Access-Control-Allow-Origin`”。 启用扩展程序: 安装完成后,在浏览器扩展程序栏中找到该扩展并启用。 配置扩展程序: 根据需要配置扩展程序的设置,以允许特定的跨域请求。 > 如果chrome没法安装成功,可以在Edge浏览器已经安装也是可以的。插件名称:CORS Unblock #### 方法2:修改浏览器启动参数 关闭所有Chrome实例: 确保所有Chrome窗口都已关闭。 修改启动快捷方式: 右击Chrome的启动快捷方式,选择“属性”。 添加参数: 在“目标”字段中,Chrome.exe后添加参数 `--disable-web-security --user-data-dir=[某个文件夹路径]。`例如: `"C: \Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir=C:\ChromeDevSession`。 重启Chrome: 使用修改后的快捷方式启动Chrome。 ### 公网访问内网地址的时候报跨域错误 比如在`https://jessibuca.com` 访问 `http://192.168.xxx.xxx/test.flv` 地址,会报`the request client is not a secure context and the resource is in more-private address space 'private'` 错误 #### 方法1:修改flags 参数 打开 `chrome://flags/` 搜索 `Block insecure private network requests`,将其设置为 `Disabled`,然后重启浏览器。 #### 方法2:使用扩展程序 安装`CORS`扩展: 在`Chrome Web Store`中搜索并安装一个允许跨域请求的扩展程序,如“`CORS Unblock` ”或“`Allow CORS: Access-Control-Allow-Origin`”。 启用扩展程序: 安装完成后,在浏览器扩展程序栏中找到该扩展并启用。 配置扩展程序: 根据需要配置扩展程序的设置,以允许特定的跨域请求。 ### 公网访问内网地址(websocket/http) 的时候直接pending不通了 > Chrome 147 开始,把“公网页面 → 局域网 IP 的 WebSocket”也纳入了 Local Network Access(LNA)限制,默认是会被拦/挂起的。 https://support.google.com/chrome/a/answer/7679408?hl=eN 原文:Chrome 147 expands Local Network Access restrictions to include WebSocket and WebTransport connections. > Chrome 147 on Android, ChromeOS, Linux, macOS, Windows: Local Network Access restrictions expanded to include WebSocket and WebTransport connections. 解决方案: 1. 开启 `chrome://flags/#local-network-access-check` ### Mixed Content: The page at 'https://jessibuca.com' was loaded over HTTPS, but requested an insecure resource 'http://xxx.com/xxx.flv'. This request has been blocked; the content must be served over HTTPS. 这个错误是因为页面是https,但是请求的资源是http,浏览器不允许这种请求。 解决方案: 1. 使用 http://jessibuca.monibuca.com/ 地址 代替 https://jessibuca.com 地址 同理,如果是http页面,请求的资源是https,也会报同样的错误。 解决方案 1. 使用 https://jessibuca.com 地址 代替 http://jessibuca.monibuca.com 地址 ### https的播放地址,播放报错,ffplay可以正常播放。 看下network tab 下面的状态码, 如果是 `ERR_CERT_DATE_INVALID`、`ERR_CERT_COMMON_NAME_INVALID` 状态码,则表示网站的 SSL/TLS 证书 时间无效或者不匹配。 ERR_CERT_DATE_INVALID 可能得原因: 1. 证书已过期(最常见原因)。 2. 证书尚未生效(服务器证书开始时间在未来)。 3. 本地系统时间不正确(客户端电脑/手机的时间和时区不对,也会导致证书验证失败)。 ERR_CERT_COMMON_NAME_INVALID 可能得原因: 1. 证书的域名和访问的域名不匹配(比如证书是 www.example.com,但访问的是 example.com)。 2. 访问的子域名未被覆盖(证书只对 example.com 有效,但用户访问 sub.example.com,证书里没有包含这个子域名) 3. 使用了 IP 地址访问(大部分证书只针对域名签发,如果你用 https://192.168.1.1 这种方式访问,而证书没有绑定这个 IP,就会报错。) 4. 伪造或自签名证书(如果证书是自签发的,且 Common Name 与实际访问域名不符,也会触发这个错误。) 5. 域名重定向或配置错误(比如 Nginx/Apache 配置了错误的证书,导致请求的域名和加载的证书不一致。) ## 移动端与 WebView ### 是否支持原生、小程序(UniApp,小程序)等 #### 对于UniApp | Vue2 | Vue3 | |------|------| | √ | √ | | App | 快应用 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节小程序 | QQ小程序 | |------|------|--------|---------|--------|--------|-------| | × | × | × | × | × | × | × | | 钉钉小程序 | 快手小程序 | 飞书小程序 | 京东小程序 | |-------|---------|-------|--------| | × | × | × | × | | H5-Safari | Android Browser | 微信浏览器(Android) | QQ浏览器(Android) | Chrome | IE | Edge | Firefox | PC-Safari | |------------|------------------|-----------------|-----------------|---------|----|--------|----------|-----------| | √ | √ | √ | √ | √ | √ | √ | √ | √ | #### 对于小程序 > 例如 微信小程序、快手小程序、钉钉小程序、飞书小程序、京东小程序 只支持内嵌 webview 模式播放。 ### 就是在webview中使用写好的网页,ios工程会找不到Jessibuca这个对象 > 用的cdn方式就可以了。 ### Android端webView灰色按钮(默认的播放按钮)问题 > android端自动起播在首帧出来之前会有一个灰色的播放按钮闪现,不同的手机或者android版本会略有不同,这个是webview中video内置的poster导致,前端无法隐藏 解决方案: 方案一:找android webView的开发同学,参考以下方式实现隐藏 HTML5 video remove overlay play icon https://stackoverflow.com/questions/18271991/html5-video-remove-overlay-play-icon https://www.mengke.me/blog/202312/Remove_Android_WebView_video_poster You can hide this picture. For example: ```java WebView mWebView = (WebView) findViewById(R.id.web_view); mWebView.setWebChromeClient(new WebChromeClientCustomPoster()); ``` Chrome client class: ```java private class WebChromeClientCustomPoster extends WebChromeClient { @Override public Bitmap getDefaultVideoPoster() { return Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); } } ``` 方案二:设置Video的poster属性为一个透明的图片,或者'noposter' ``` // 透明 base64