[toc]

播放器 API

JessibucaPro(options)

options 支持的参数有:

container

  • 类型DOM or string
  • 用法

播放器容器。

若为 string ,则底层调用的是 document.querySelector(container)

源码


let $container = options.container;
if (typeof options.container === 'string') {
    $container = document.querySelector(options.container);
}
if (!$container) {
    throw new Error('jessibucaPro need container option');
    return;
}

if ($container.nodeName === 'CANVAS' || $container.nodeName === 'VIDEO') {
    throw new Error(`jessibucaPro container type can not be ${$container.nodeName} type`);
    return;
}

container 不能是 video 或者canvas 标签

// demo
const jes = new JessibucaPro({
    container: '#player' // or document.querySelector('#player')
});

videoBuffer

  • 类型number
  • 默认值1
  • 用法: 设置缓冲时长,单位秒。

// demo

const jes = new JessibucaPro({
    videoBuffer: 0.3 // s
});

videoBufferDelay

  • 类型number
  • 默认值1
  • 用法: 设置最大缓冲延迟时长,单位秒,如果延迟超过该值,就会进行丢帧处理。

播放器会在缓冲数据大于videoBuffer + videoBufferDelay的时候,进行丢帧处理。

关于播放器延迟(超过延迟触发丢帧)设置

// demo

const jes = new JessibucaPro({
    videoBufferDelay: 1 // s
});

playType

  • 类型string
  • 默认值player
  • 可选值player,playbackTF,playVod

主要是为了给 回放流还有点播文件加快初始化用的,

decoder

  • 类型string
  • 默认值decoder-pro.js
  • 可选值decoder-pro.jsdecoder-pro-simd.js
  • 用法

worker地址:目前播放器可支持的软解码器有两个,一个是decoder-pro.js,一个是decoder-pro-simd.jsdecoder-pro.js 是纯js解码器,decoder-pro-simd.js是使用simd加速的解码器,性能更好,但是兼容性不如decoder-pro.js

播放器js下面的文件需要放在同一个目录下面。

可以只配置decoder-pro.js的路径,然后结合 useSIMD:true 参数,播放器内部会切换成引用decoder-pro-simd.js地址。

通过配置useMThreading:true 参数,可以开启多线程解码,播放器会根据是否使用simd解码来调用decoder-pro-mt.js 或者decoder-pro-simd-mt.js解码器的。

对于其他decoder-pro-audio.js,decoder-pro-hard.js,decoder-pro-mt.js,decoder-pro-simd-mt.js 等解码器,是播放器内部根据不同的解码环境调用的。不需要配置。

如果配置的参数是相对地址,是针对于http地址上面的相对地址。

例如当前页面的是 http://test.com/a/b/c.html

如果new 播放器的时候配置的 decoder的参数是相对地址'./decoder.js',则会去请求 http://test.com/a/b/decoder.js

如果业务需要配置CDN地址,则需要二次重新编译播放器,需要修改rollup.config.js文件,里面注释的 JESSIBUCA_PRO_WASM_URL 这些地址修改为CDN的地址,然后再次编译就行了。

// demo

const jes = new JessibucaPro({
    decoder: 'js/decoder-pro.js' // 网络地址(相对或者绝对),不是js文件的相对地址
});

wasmMp4RecorderDecoder

  • 类型string
  • 默认值jessibuca-pro-mp4-recorder-decoder.js
  • 用法:支持相对路径,也支持绝对路径(cdn)

wasm mp4 录制模块, 需要额外的引入 jswasm 文件。

wasmMp4RecorderDecoder 是mp4录制的解码器,如果不配置,默认是jessibuca-pro-mp4-recorder-decoder.js

可以根据业务的js存放目录,然后动态配置wasmMp4RecorderDecoder参数

wasmMp4RecorderDecoder: './js/jessibuca-pro-mp4-recorder-decoder.js' // 相对路径

wasmMp4RecorderDecoder:'/js/jessibuca-pro-mp4-recorder-decoder.js' //

如果走的是CDN的地址,则需要额外的配置个 window.JESSIBUCA_PRO_MP4_RECORDER_WASM_URL 地址为CDN地址。

// demo

//
window.JESSIBUCA_PRO_MP4_RECORDER_WASM_URL = 'https://test-cdn.com/js/jessibuca-pro-mp4-recorder-decoder.wasm'
const jes = new JessibucaPro({
    wasmMp4RecorderDecoder: '/js/jessibuca-pro-mp4-recorder-decoder.js' // 网络地址(相对或者绝对),不是js文件的相对地址
});

forceNoOffscreen(废弃)

  • 类型boolean
  • 默认值:true
  • 用法

是否不使用离屏模式(提升渲染能力)

由于目前浏览器兼容性太差,会出现慕名奇妙的错误问题,目前播放器内部禁用离屏渲染。

useOffscreen(废弃)

  • 类型boolean
  • 默认值:false
  • 用法

是否使用离屏模式(提升渲染能力)默认是不开启的

主要是为了替代forceNoOffscreen 参数使用的。

hiddenAutoPause

  • 类型boolean
  • 默认值:false
  • 用法

是否开启当页面的'visibilityState'变为'hidden'的时候,自动暂停播放。

// demo


const jessibuca = new JessibucaPro({
    hiddenAutoPause: true
});

hasAudio

  • 类型boolean
  • 默认值:true
  • 用法

是否有音频,如果设置false,则不对音频数据解码,提升性能。

// demo


const jessibuca = new JessibucaPro({
    hasAudio: false
});

hasVideo

  • 类型boolean
  • 默认值:true
  • 用法

是否有视频,如果设置false,则不对视频数据解码,只播放音频数据。

// demo

const jessibuca = new JessibucaPro({
    hasVideo: false
});

rotate

  • 类型number
  • 默认值:0
  • 用法

设置旋转角度,支持,0(默认) ,90,180,270 四个值。

rotate: 0|90|180|270

// demo


const jessibuca = new JessibucaPro({
    rotate: 90
});

mirrorRotate

  • 类型string
  • 默认值none
  • 用法:镜像翻转,支持水平(level)和垂直(vertical)
mirrorRotate: 'none'|'level'|'vertical'

// demo

const jessibuca = new JessibucaPro({
    mirrorRotate: 'level'
});

isResize

  • 类型boolean
  • 默认值true
  • 用法
  1. 当为true的时候:视频画面做等比缩放后,高或宽对齐canvas区域,画面不被拉伸,但有黑边。 等同于 setScaleMode(1)
  2. 当为false的时候:视频画面完全填充canvas区域,画面会被拉伸。等同于 setScaleMode(0)

在IOS端上,如果是通过video标签渲染的时候,因为css在控制video样式的时候,尤其是拉伸的时候,会有部分画面被遮挡看不到,所以在这种环境下会禁用这个设置。

// demo

const jessibuca = new JessibucaPro({
    isResize: false
});

isFullResize

  • 类型boolean
  • 默认值false
  • 用法
  1. 当为true的时候:视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全。等同于 setScaleMode(2)

在IOS端上,如果是通过video标签渲染的时候,因为css在控制video样式的时候,尤其是拉伸的时候,会有部分画面被遮挡看不到,所以在这种环境下会禁用这个设置。

// demo

const jessibuca = new JessibucaPro({
    isFullResize: true
});

isFlv

  • 类型boolean
  • 默认值false
  • 用法
  1. 当为true的时候:ws/http协议不检验是否以.flv为依据,进行协议解析。

// demo

const jessibuca = new JessibucaPro({
    isFlv: true
});

isFmp4

  • 类型boolean
  • 默认值false
  • 用法
  1. 当为true的时候:ws/http协议不检验是否以.fmp4,.mp4为依据,进行协议解析。

// demo

const jessibuca = new JessibucaPro({
    isFmp4: true
});

isMpeg4

  • 类型boolean
  • 默认值false
  • 用法
  1. 当为true的时候:ws/http协议不检验是否以.mpeg4为依据,进行协议解析。

// demo

const jessibuca = new JessibucaPro({
    isMpeg4: true
});

isNakedFlow

  • 类型boolean
  • 默认值false
  • 用法:是否是裸流,如果是裸流,则不会进行解封装,直接解码渲染。
  1. 当为true的时候:ws协议不检验是否以.h264,.h265为依据,进行协议解析。

// demo

const jessibuca = new JessibucaPro({
    isNakedFlow: true
});

isH265

  • 类型boolean
  • 默认值false
  • 用法:是否是H265流

这个参数是优化性能的参数,可以初始化播放器的时候,提前判断浏览器是否支持硬解码H265格式,如果不支持,就直接初始化wasm(simd) 软解码。

如果视频是H264的源,不建议设置这个参数,会使得本身是可以使用mse硬解码的,但是额外判断了不支持h265解码,而降级到了wasm( simd)软解码,导致性能下降。

播放器之前的逻辑是需要等请求到流了,然后再根据当前的解码器来判断是否支持H265解码,如果不支持就会降级到wasm(simd) 软解码。这样会导致在切换解码器的时候,出现加载中效果。

如果设置为true,则会在初始化解码器的时候,就会检查浏览器是否支持硬解码解码H265格式,如果不支持,就直接初始化wasm(simd)软解码。

// demo

const jessibuca = new JessibucaPro({
    isH265: true
});

isWebrtcForZLM

  • 类型boolean
  • 默认值false
  • 用法: 是否zlm的webrtc播放地址

当检测到是webrtc的时候,才会判断该参数。

会根据url参数是否带有/index/api/webrtc来判断是否是zlm webrtc的播放地址。

// demo

const jessibuca = new JessibucaPro({
    isWebrtcForZLM: true
});

isWebrtcForSRS

  • 类型boolean
  • 默认值false
  • 用法:是否srs的webrtc播放地址

当检测到是webrtc的时候,才会判断该参数。

会根据url参数是否带有/rtc/v1/play/来判断是否是srs webrtc的播放地址。

// demo

const jessibuca = new JessibucaPro({
    isWebrtcForSRS: true
});

webrtcForSRSBySDK

  • 类型boolean
  • 默认值false
  • 用法:是否srs的webrtc sdk请求地址

播放路径是 webrtc://127.0.0.1/rtc/v1/play/live/xxx/xxx 这种格式,建议设置为true

// demo

const jessibuca = new JessibucaPro({
    isWebrtcForSRS: true,
    webrtcForSRSBySDK:true
});

webrtcForSRSByWhipWhep

  • 类型boolean
  • 默认值false
  • 用法:是否srs的webrtc whip/whep请求地址

播放路径是 webrtc://127.0.0.1/rtc/v1/whep/?app=live&stream=xxxxxx 这种格式,建议设置为true

这里对接的是新版本的 SRS 的 whip/whep 协议,2021 + 以上的版本。

// demo

const jessibuca = new JessibucaPro({
    isWebrtcForSRS: true,
    webrtcForSRSByWhipWhep:true
});

webrtcForSRSByWhipWhepOldVersion

  • 类型boolean
  • 默认值false
  • 用法:是否srs的webrtc whip/whep请求地址

播放路径是 webrtc://127.0.0.1/rtc/v1/whep/?app=live&stream=xxxxxx 这种格式,建议设置为true

这里对接的是新版本的 SRS 的 whip/whep 协议,2021 - 以前的版本。

const jessibuca = new JessibucaPro({
    isWebrtcForSRS: true,
    webrtcForSRSByWhipWhep:true,
    webrtcForSRSByWhipWhepOldVersion:true
});

isWebrtcForQiNiu

  • 类型boolean
  • 默认值false
  • 用法:是否七牛云的webrtc播放地址

当检测到是webrtc的时候,才会判断该参数。

// demo

const jessibuca = new JessibucaPro({
    isWebrtcForQiNiu: true
});

isWebrtcForDJI

  • 类型boolean
  • 默认值false
  • 用法:是否大疆的webrtc播放地址

当检测到是webrtc的时候,才会判断该参数。

// demo

const jessibuca = new JessibucaPro({
    isWebrtcForDJI: true
});

isWebrtcForOthers

  • 类型boolean
  • 默认值false
  • 用法:是否其他的webrtc播放地址

当检测到是webrtc的时候,才会判断该参数。

当设置isWebrtcForOtherstrue的时候,就会直接请求播放地址的url获取sdp信息,然后进行播放。

// demo

const jessibuca = new JessibucaPro({
    isWebrtcForOthers: true
});

isM7sCrypto

  • 类型boolean
  • 默认值false
  • 用法:是否M7S加密流

// demo

const jessibuca = new JessibucaPro({
    isM7sCrypto: true
});

isSm4Crypto

  • 类型boolean
  • 默认值false
  • 用法:是否Sm4加密流

// demo

const jessibuca = new JessibucaPro({
    isSm4Crypto: true
});

debug

  • 类型boolean
  • 默认值false
  • 用法: 是否开启控制台调试打印

// demo

const jessibuca = new JessibucaPro({
    debug: true
});

debugLevel

  • 类型string
  • 默认值warn
  • 用法

debug模式下的日志级别,支持debugwarn,默认是warn

debugLevel: 'debug' | 'warn'

// demo

const jessibuca = new JessibucaPro({
    debug: true,
    debugLevel: 'debug'
});

timeout

  • 类型number
  • 默认值10 单位秒
  • 用法
  1. 设置超时时长, 单位秒
  2. 在连接成功之前(loading)和播放中途(heart),如果超过设定时长无数据返回,则回调timeout事件

不推荐使用,只是为了兼容v2版本的参数,推荐使用loadingTimeoutheartTimeout 参数,单独配置。

// demo

const jessibuca = new JessibucaPro({
    timeout: 10 // s
});

heartTimeout

  • 类型number
  • 默认值10 单位秒
  • 用法
  1. 设置超时时长, 单位秒
  2. 播放中途,如果超过设定时长无数据返回,则回调timeout事件

如果请求地址报错了,会触发playFailedAndPaused异常事件,会暂停播放,不会触发delayTimeout事件,也不会触发重试机制的。

// demo

const jessibuca = new JessibucaPro({
    heartTimeout: 10 // s
});

heartTimeoutReplay

  • 类型boolean
  • 默认值true
  • 用法: 是否开启心跳超时之后自动再播放

heartTimeout 心跳超时之后自动再播放,不再抛出异常,而直接重新播放视频地址。

当配置了playFailedAndReplay:false的时候,超时的时候,不会自动重新播放。

只会在播放地址是正常能够访问通的情况下,才会重新播放。像http 404,500等错误,不会重新播放。ws连接失败也不会重新播放。 这种会走到异常事件。

关于重播的逻辑可以看

const jessibuca = new JessibucaPro({
    heartTimeoutReplay: false
});

当超时的时候,会触发playFailedAndPaused事件。

heartTimeoutReplayTimes

  • 类型number
  • 默认值3
  • 用法: heartTimeoutReplay 重试次数

heartTimeoutReplay 重试失败之后,不再重新播放视频地址。

是整个生命周期中重试的次数(连接成功之后不会重置次数)。

如果想无限次重试,可以设置为-1。

const jessibuca = new JessibucaPro({
    heartTimeoutReplayTimes: 5 // 重试5次
});

loadingTimeout

  • 类型number
  • 默认值10 单位秒
  • 用法
  1. 设置超时时长, 单位秒
  2. 在刚开始播放的时候,在连接成功之前,如果超过设定时长无数据返回,则回调timeout事件

对于fetch 是等待 response 的时间,对于websocket 是等待 open 事件的时间。

如果是请求地址状态码不是200,则会触发playFailedAndPaused异常事件,会暂停播放,不会触发timeout事件,也不会触发重试机制的。

同理websocket请求也是一样的,如果地址异常,会触发playFailedAndPaused异常事件,会暂停播放,不会触发timeout事件,也不会触发重试机制的。

const jessibuca = new JessibucaPro({
    loadingTimeout: 10 // s
});

loadingTimeoutReplay

  • 类型boolean
  • 默认值true
  • 用法: 是否开启loading超时之后自动再播放

loadingTimeout 心跳超时之后自动再播放,不再抛出异常,而直接重新播放视频地址。

当配置了playFailedAndReplay:false的时候,超时的时候,不会自动重新播放。

只会在播放地址是正常能够访问通的情况下,才会重新播放。像http 404,500等错误,不会重新播放。ws连接失败也不会重新播放。 这种会走到异常事件,。

const jessibuca = new JessibucaPro({
    loadingTimeoutReplay: false
});

当超时的时候,会触发playFailedAndPaused事件。

loadingTimeoutReplayTimes

  • 类型number
  • 默认值3
  • 用法: loadingTimeoutReplay 重试次数

loadingTimeoutReplay 重试失败之后,不再重新播放视频地址。

是整个生命周期中重试的次数(连接成功之后不会重置次数)。

如果想无限次重试,可以设置为-1

const jessibuca = new JessibucaPro({
    loadingTimeoutReplayTimes: -1 // 无限次重试
});

loadingTimeoutRetryEndShowPlayBtn

  • 类型boolean
  • 默认值false
  • 用法:重试 loadingTimeoutReplayTimes 次数失败之后,暂停播放之后显示重播按钮
const jessibuca = new JessibucaPro({
    loadingTimeoutRetryEndShowPlayBtn: true // 加载失败之后,暂停播放之后显示重播按钮
});

supportDblclickFullscreen

  • 类型boolean
  • 默认值false
  • 用法: 是否支持屏幕的双击事件,触发全屏,取消全屏事件。
const jessibuca = new JessibucaPro({
    supportDblclickFullscreen: true // 开启双击事件
});

showBandwidth

  • 类型boolean
  • 默认值false
  • 用法: 是否显示网速
const jessibuca = new JessibucaPro({
    showBandwidth: true // 显示网速
});

showPerformance

  • 类型boolean
  • 默认值false
  • 用法: 是否显示性能面板
const jessibuca = new JessibucaPro({
    showPerformance: true // 显示性能面板
});

operateBtns

  • 类型object

  • 用法: 配置底部操作按钮

  1. fullscreen Boolean 是否显示全屏按钮
  2. screenshot Boolean 是否显示截图按钮
  3. play Boolean 是否显示播放暂停按钮
  4. audio Boolean 是否显示声音按钮
  5. record Boolean 是否显示录制按钮
  6. ptz Boolean 是否显示PTZ轮盘按钮
  7. quality Boolean 是否显示清晰度按钮
  8. close Boolean 是否显示关闭按钮(会销毁播放器)
  9. zoom Boolean 是否显示电子放大
  10. scale Boolean 是否显示scale(拉伸、缩放)按钮
  11. performance Boolean 是否显示性能按钮
  12. face Boolean 是否显示人脸识别按钮
  13. fullscreenFn Function 绑定全屏按钮的自定义方法,如设置了,点击全屏按钮的时候触发。
  14. fullscreenExitFn Function 绑定退出全屏按钮的自定义方法,如设置了,点击退出全屏按钮的时候触发。
  15. screenshotFn Function 绑定截图按钮的自定义方法,如设置了,点击截图按钮的时候触发。
  16. playFn Function 绑定播放按钮的自定义方法,如设置了,点击播放按钮的时候触发。
  17. pauseFn Function 绑定暂停按钮的自定义方法,如设置了,点击暂停按钮的时候触发。
  18. recordFn Function 绑定录制按钮的自定义方法,如设置了,点击录制按钮的时候触发。
  19. recordStopFn Function 绑定停止录制按钮的自定义方法,如设置了,点击停止录制按钮的时候触发。
// demo
const jessibuca = new JessibucaPro({
    operateBtns: {
        fullscreen: true,
        screenshot: true,
        play: true,
        audio: true,
        record: true,
        ptz: true,
        quality: true,
        close: true,
        zoom: true,
        scale: true,
        performance: true,
        face: true,
        //
        fullscreenFn: function () {
            console.log('fullscreenFn');
        },
        fullscreenExitFn: function () {
            console.log('fullscreenExitFn');
        },
        screenshotFn: function () {
            console.log('screenshotFn');
        },
        playFn: function () {
            console.log('playFn');
        },
        pauseFn: function () {
            console.log('pauseFn');
        },
        recordFn: function () {
            console.log('recordFn');
        },
        recordStopFn: function () {
            console.log('recordStopFn');
        }
    }
});

qualityConfig

  • 类型array
  • 默认值[]
  • 用法: 配置清晰度 ,例如 ['普清', '高清', '超清', '4K', '8K']

点击回调的参数为当前清晰度的值,比如点击了高清,回调的参数就是高清

当在ui上面选择了清晰度,会触发streamQualityChange事件

默认值是数组的第一个。

const jessibuca = new JessibucaPro({
    qualityConfig: ['普清', '高清', '超清', '4K', '8K']
});

defaultStreamQuality

  • 类型string
  • 默认值:``
  • 用法: 默认显示的清晰度,如果不设置,会显示第一个清晰度
const jessibuca = new JessibucaPro({
    qualityConfig: ['普清', '高清', '超清', '4K', '8K'],
    defaultStreamQuality: '超清'
});

watermarkConfig

  • 类型object | array
  • 默认值{}
  • 用法: 配置播放器播放过程中水印显示,支持图片文字自定义HTML

支持单个对象 或者 数组

水印是基于播放流的宽高(分辨率)来定的,而不是基于播放器的container宽高来定的。在使用 topleft的时候请注意。

支持的参数有:

const jessibuca = new JessibucaPro({
    watermarkConfig:{
        left: '', //
        right: '', //
        top: '', //
        bottom: '', //
        opacity: 1, // 透明度
        backgroundColor:'',// 背景颜色 同css backgroundColor
        // 图片配置
        image: {
            src: '',
            width: '100',
            height: '60'
        },
        // 文字配置
        text: {
            content: '',
            fontSize: '14',
            color: '#000',
            width:'', // 可选
            height:'' // 可选
        },
        // 自定义html
        html: ''
    }
})

图片配置

支持 url 或者 base64 格式

const jessibuca = new JessibucaPro({
    watermarkConfig: {
        image: {
            src: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAS4AAABgCAYAAACjZZ/rAAAK4mlDQ1BJQ0MgUHJvZmlsZQAASImVlwdUU1kagO976SEhkIQISAm9SW8BpIQeivQqKiEJJJQQE4KCDZXBERwVRESwDOCoiIKjIyBjQSxYUWzYB2RQUNbBgg2VfcASZmbP7p7937nvfufPf/9yz705/wOAHMKVSDJhFQCyxDnSyABvZnxCIhP3DOAAA9CBA7Dm8mQSdnh4CEBkev6rvL8LoIn5luWEr3///b8KlS+Q8QCAkhBO4ct4WQi3I2OEJ5HmAIA6jOgNluRIJvg2wnQpkiDCgxOcNsVfJjhlktEqkzbRkT4IGwKAJ3G50jQASDaInpnLS0P8kMIRthHzRWKECxD24Am5fISRuGBOVlb2BA8jbIrYSwAg0xFmpfzJZ9pf/Kco/HO5aQqeqmtS8L4imSSTm/d/bs3/lqxM+XQMY2SQhNLASGRWR/bvXkZ2sILFKfPCplnEn7SfZKE8MGaaeTKfxGnmc32DFWsz54VMc6rIn6Pwk8OJnmaBzC9qmqXZkYpYqVIf9jRzpTNx5RkxCr1QwFH4zxdGx01zrih23jTLMqKCZ2x8FHqpPFKRv0Ac4D0T119Re5bsT/WKOIq1OcLoQEXt3Jn8BWL2jE9ZvCI3vsDXb8YmRmEvyfFWxJJkhivsBZkBCr0sN0qxNgc5nDNrwxV7mM4NCp9m4Av8QAjyMEEMsAPOwBawQAQIzREszZkoxidbkicVpQlzmGzkxgmYHDHPag7TzsbODoCJ+zt1JN5GTt5LiHFqRpe9BznK75E7UzqjSykHoKUICf1gRme4CwBKIQDNHTy5NHdKh554YQARUJB/Bg2gAwyAKbBE8nMCbsALyTgIhIFokAAWAh4QgiwgBUvAcrAaFIESsBlsBVVgN6gD+8EhcAS0gBPgDLgAroAb4A54CHrBAHgJRsB7MAZBEA4iQzRIA9KFjCALyA5iQR6QHxQCRUIJUDKUBokhObQcWguVQGVQFVQD1UM/Q8ehM9AlqBu6D/VBQ9Ab6DOMgkkwHdaGjWFrmAWz4WA4Gl4Ap8GL4Xy4EN4IV8K18EG4GT4DX4HvwL3wS3gUBVBKKAZKD2WJYqF8UGGoRFQqSopaiSpGVaBqUY2oNlQn6haqFzWM+oTGomloJtoS7YYORMegeejF6JXoDegq9H50M/oc+ha6Dz2C/oYhY7QwFhhXDAcTj0nDLMEUYSowezHHMOcxdzADmPdYLJaBNcE6YwOxCdh07DLsBuxObBO2HduN7ceO4nA4DZwFzh0XhuPicnBFuO24g7jTuJu4AdxHvBJeF2+H98cn4sX4NfgK/AH8KfxN/HP8GEGFYERwJYQR+IQ8wibCHkIb4TphgDBGVCWaEN2J0cR04mpiJbGReJ74iPhWSUlJX8lFKUJJpFSgVKl0WOmiUp/SJxKVZE7yISWR5KSNpH2kdtJ90lsymWxM9iInknPIG8n15LPkJ+SPyjRlK2WOMl95lXK1crPyTeVXFALFiMKmLKTkUyooRynXKcMqBBVjFR8VrspKlWqV4yo9KqOqNFVb1TDVLNUNqgdUL6kOUnFUY6oflU8tpNZRz1L7aSiaAc2HxqOtpe2hnacN0LF0EzqHnk4voR+id9FH1KhqDmqxakvVqtVOqvUyUAxjBoeRydjEOMK4y/g8S3sWe5Zg1vpZjbNuzvqgPlvdS12gXqzepH5H/bMGU8NPI0OjVKNF47EmWtNcM0JzieYuzfOaw7Pps91m82YXzz4y+4EWrGWuFam1TKtO66rWqLaOdoC2RHu79lntYR2GjpdOuk65zimdIV2aroeuSLdc97TuC6Yak83MZFYyzzFH9LT0AvXkejV6XXpj+ib6Mfpr9Jv0HxsQDVgGqQblBh0GI4a6hqGGyw0bDB8YEYxYRkKjbUadRh+MTYzjjNcZtxgPmqibcEzyTRpMHpmSTT1NF5vWmt42w5qxzDLMdprdMIfNHc2F5tXm1y1gCycLkcVOi+45mDkuc8Rzauf0WJIs2Za5lg2WfVYMqxCrNVYtVq+sDa0TrUutO62/2TjaZNrssXloS7UNsl1j22b7xs7cjmdXbXfbnmzvb7/KvtX+tYOFg8Bhl8M9R5pjqOM6xw7Hr07OTlKnRqchZ0PnZOcdzj0sOiuctYF10QXj4u2yyuWEyydXJ9cc1yOuf7hZumW4HXAbnGsyVzB3z9x+d313rnuNe68H0yPZ40ePXk89T65nredTLwMvvtder+dsM3Y6+yD7lbeNt9T7mPcHH1efFT7tvijfAN9i3y4/ql+MX5XfE399/zT/Bv+RAMeAZQHtgZjA4MDSwB6ONofHqeeMBDkHrQg6F0wKjgquCn4aYh4iDWkLhUODQreEPppnNE88ryUMhHHCtoQ9DjcJXxz+awQ2IjyiOuJZpG3k8sjOKFrUoqgDUe+jvaM3RT+MMY2Rx3TEUmKTYutjP8T5xpXF9cZbx6+Iv5KgmSBKaE3EJcYm7k0cne83f+v8gSTHpKKkuwtMFixdcGmh5sLMhScXURZxFx1NxiTHJR9I/sIN49ZyR1M4KTtSRng+vG28l3wvfjl/SOAuKBM8T3VPLUsdTHNP25I2JPQUVgiHRT6iKtHr9MD03ekfMsIy9mWMZ8ZlNmXhs5Kzjoup4gzxuWyd7KXZ3RILSZGkd7Hr4q2LR6TB0r0ySLZA1ppDRxqlq3JT+XfyvlyP3Orcj0tilxxdqrpUvPRqnnne+rzn+f75Py1DL+Mt61iut3z18r4V7BU1K6GVKSs7VhmsKlw1UBBQsH81cXXG6mtrbNaUrXm3Nm5tW6F2YUFh/3cB3zUUKRdJi3rWua3b/T36e9H3Xevt129f/62YX3y5xKakouTLBt6Gyz/Y/lD5w/jG1I1dm5w27dqM3SzefLfUs3R/mWpZfln/ltAtzeXM8uLyd1sXbb1U4VCxextxm3xbb2VIZet2w+2bt3+pElbdqfaubtqhtWP9jg87+Ttv7vLa1bhbe3fJ7s8/in68VxNQ01xrXFtRh63LrXu2J3ZP50+sn+r3au4t2ft1n3hf7/7I/efqnevrD2gd2NQAN8gbhg4mHbxxyPdQa6NlY00To6nkMDgsP/zi5+Sf7x4JPtJxlHW08RejX3Ycox0rboaa85pHWoQtva0Jrd3Hg453tLm1HfvV6td9J/ROVJ9UO7npFPFU4anx0/mnR9sl7cNn0s70dyzqeHg2/uztcxHnus4Hn794wf/C2U525+mL7hdPXHK9dPwy63LLFacrzVcdrx675njtWJdTV/N15+utN1xutHXP7T510/PmmVu+ty7c5ty+cmfene67MXfv9ST19N7j3xu8n3n/9YPcB2MPCx5hHhU/Vnlc8UTrSe1vZr819Tr1nuzz7bv6NOrpw35e/8vfZb9/GSh8Rn5W8Vz3ef2g3eCJIf+hGy/mvxh4KXk5Nlz0D9V/7Hhl+uqXP7z+uDoSPzLwWvp6/M2Gtxpv971zeNcxGj765H3W+7EPxR81Pu7/xPrU+Tnu8/OxJV9wXyq/mn1t+xb87dF41vi4hCvlTrYCKGTAqakAvNmH9McJANBuAECcP9VfTwo09U0wSeA/8VQPPilOANT1ABC9DICQawBsr0JaWsQ/BfkuCKcgejcA29srxr9ElmpvN+WL5Im0Jo/Hx9+aAoArBeBr6fj4WN34+Nc6JNmHALTnTfX1E6JyEIAacxtH+5D7VPMC8DeZ6vn/VOPfZzCRgQP4+/xPeFgcU9phDh8AAABsZVhJZk1NACoAAAAIAAQBGgAFAAAAAQAAAD4BGwAFAAAAAQAAAEYBKAADAAAAAQACAACHaQAEAAAAAQAAAE4AAAAAAAAAkAAAAAEAAACQAAAAAQACoAIABAAAAAEAAAEuoAMABAAAAAEAAABgAAAAADApncsAAAAJcEhZcwAAFiUAABYlAUlSJPAAAB1BSURBVHgB7V0HeBTVFj6b3fRCAgSQ3qSKIuoDRESx8OzloaIIiqhYUIEHiIJIU6QpVkRRwMaTp4INBBsoRZQiIFhACL1DQtpusuWdf8IsM7Ozu0nYDQzvnO/bzMyd2+a/N/+ce+65d2w+FhIRBAQBQcBCCMRYqK5SVUFAEBAEFASEuKQjCAKCgOUQEOKyXJNJhQUBQUCIS/qAICAIWA4BIS7LNZlUWBAQBIS4pA8IAoKA5RAQ4rJck0mFBQFBQIhL+oAgIAhYDgEhLss1mVRYEBAEhLikDwgCgoDlEBDislyTSYUFAUFAiEv6gCAgCFgOASEuyzWZVFgQEASEuKQPCAKCgOUQEOKyXJNJhQUBQUCIS/qAICAIWA4BIS7LNZlUWBAQBIS4pA8IAoKA5RAQ4rJck0mFBQFBQIhL+oAgIAhYDgEhLss1mVRYEBAEhLikDwgCgoDlEBDislyTSYUFAUFAiEv6gCAgCFgOASEuyzWZVFgQEASEuKQPCAKCgOUQEOKyXJNJhQUBQcBxqkDgK8gmT+5+Ik8RuTYvJtefC6l430YiO9fQxj+mWHvluhTX4GJKaNKFYhLSKSaRf8nV+L7w76nSjlIPQaAiELD5WCqioGBlFGetJOfGb8nNJFW07RciX3EJUamEpR7BTfgdIzGcO6o1pbja7Siu1gUU37BLsCIkXBAQBE4zBE4qcR2adDV5cnYxVxWUkJKWnFTCUo/ae+r5saMtLoHsabUordMzFFvjvNOsieRxBAFBwIhAhROXz5VPBd+/SfmLppHP42LC8lGMzcOjPS/5mIhsdi+H8bmdL2LwYyUsxkY+W2yJtqXRuBQNjO9rNbHElt0piX+O9DONzyrX/0cIbNuxm5yuImrcoA7Z7Xj7iZxOCFQocRVvX0f5C14h18bvFdtVrLeQSctNNlsx2RwgK4bWwSNXPvrY+uaz8zkfvUxiIC6fL5a8nqQSolIJSz1qCM2eXo/SLhxJcTU7nE5tJc9SCgQKCp3Ub9hztHzlWiV2g7q16OWxQ6le7TN0qQ8dyaZNW7bpwtIrpVGzxg10YXJxaiJQYcTlWruQjr4/mLxF+WRnO1a8O5e1K59CVipBBSMukBgnUjQyctjI40xnEovTE5iGuFRNLLXdcEpqdicnxk1ryr4Dh2jjn3/rKp+YGE/tzjtHFyYXJQhMmjKTZvxnrg6O885pSTNeGqMLm//tEho8apIu7KK2bWjK+Kd0YXJxaiIASoi6OFfNY9J6nMhdSHFuF8V62KYFzapc4iN78mHyulOYBJM5h+CklLvqObaf5VByy/uZ5JjoLCi/rPmNnnhmsq7mdWrWoHmzpujC5KIEgdXreCbaIGs3/MEvOh9r9sH7iiGJXJ7iCGCgFVVxrf2ajr43hMhVQPGF+RTHx0iILSGPbMk5nFUIAmTXivyNb5Nrz5JIFCl5WACB2mdUD6hlzerVhLQCULF2QFSJy5t7iPK/eZt8RYUU73KSw10UHi28FRPSKCa1JtmrNKH4s3tRUscxFN+sO9krNWK/rZqsrSUq+djinGRLyg2Zp68ol7IX9yFPwb6Q8eTm6YHAQ/fcThlsq1IlNtZBg/r2Ui/leJogENWhYt6ciVS8eSVrWYUUW+xSDO6hcLMlVaa49veQo3FnctRtx1FNVHufh1xbPqaiXQvIuX022RLz2XDP1nwnho3B5ch3d1LGJdPInlIveCS5Y3kEYISfM/NFgg3LxbOKl3S4gBrVr2P555IH0CMQNeJy78uiwmUfM2k5FW1L8YDXl627sjfqRAk3jCM7O5WGFCap+Ea3Uly9aym+8W2Us+QORevyFUELC65AevK2k2vvckpqLMQVEt/T4GaVjHS6s+u1p8GTyCMEQyD4f3qwFKUI97F2dWRsV7J5veQoYk/4MGKvfS4l3zc3PGlp8rE5ktjd4UpKa/8G2eIqkS0t21RB8yfxeSl39Qj2HSv0B8mJICAIWBOBqGhczhWfk4+N8Ha3mxzF7pBDxNhzb6aEnm+WG734OjdTWoydcpb3YNsX29A8IWYPeZiZt34SpbYeVu7yrJgwNy+fdu7ZR3v2HqD8wkKqnlmFzqieSbVqVGMf3/K/u5xOF/35dxYdPpJD2UdzKSU5iapkVKKGPDRLT0stF1TRyLNcFTmWyOv10a69+2jrtl38fIlUu2Z1yqxS+ZQ29hcVF9PuPftp74GDtO/AYUpMiKeqVTKobq0zqGrl9HLDgZnZv7N2cL6H6Eh2DhtybFSZ27ta1crKcLwiZ20jTlw+1mzcO34nn7uY7EXukCDFZDaiuC7sJmFmywqZUn8zvtYNlNZ2KuUsGsTEpb9nvCrY9M7/BXGhky395Vea9cmXtGTFasI/oFHQ4bped6Xyy+SOXVpZ+vMaev/jL+nn1evIZaJRx/BKh3NaNqV/XXMFXdflUiZHE1ulobBI5Tn70wU04bXputxv/GdnGtqfXWLKIAcPZ9Pz7BO2cPEyxVamTVqtahXqeet1Cm7JSSUTRdr76vnAERNp8fKV6qVyHDnoIbr68ot1YcaLT7/6nsa8MFUXfPnF7Wjs0H66MOPF739toY++WEhffv0D5RcEjixALGiXa6/sRF2vvaLUKwqwCmHa+5/QDz+tVF5SxnJxDUK8pMM/6L4eXakmvxSjLREnLu/BXeRa841S74RCNsiHWG1hb345xVSPzNIcR/q55Khcm9x7DoXBzEcuNuzH1zp9F2VDw8I/zTImrlCy/+Bhem36f2j6rLk0dthjdFlHTIgEF/wzPDFmMn2/9OfgkfgOSHLN+j+U3wdz5tGLY4ZQjWpVTdNEOk+3x03Q2rQCDaQsMu+bH2j081MpL9/cdWf/wUM08bUZCnm/OWkE1avDM90mgnKNdXF7wrxZOR83j1SM6YpMXhBqkR7OE/V576Mv1CDTI15mv/72h/L7+POv6ZknH6UzGwa3+SL+5Knv0szZnxHKCCUg+o8+X0hffL2YBjxwF91+01Whop/wvfKPE4IU7XPmk+fwbnavCnzDG5PEXTvUGFTua0dqM3LUaFmq9M6d80oVz4qRdu87QN0ffDwsaWmfrdDppP5PjVcITBuuPcc/0oODR4UlLW0anMPrv9djwwgd2yjRyNNYRlmvUd+nnnslKGlp89vDWPfo+wRt3rpdG1yh52i7ewc8HZa0jJX6fdMWuvvRYbRl207jLf/10GdfordnzQlLWv4EfII2fXbyGzRn3rfa4IifR5y4irPWK5W0u0MztK1SDbIlpET0gRJq3liq/HxerhsPaU83gaYzZPTztHX7roBHgy0Lw4TrrrzEVJVX3q5vvENmnufIDENDaFFGObdVM+rT8xYa9XhfuvWGLooNyBhn5+59/OZ+xxgclTwDCilDAJZXDXh6Amk1NIfDTkmJCUFzOZJ9lIaPe0XxzA8aKYo3oGmt/HWDaQkYsrVt04qan9nQ9BmO5ubRg4NGBWh3yOyr75bQ5wsXmeabkZ5Gl/KwsGO786iWicMvEo1hjRW2z2hJxIeKzqVzlLrGeEITQ8Jdr0f8meKqdipVnl7nAfK6DvFmhNEfi5eqQhGK9P7HX5iSC1T3rtddQakpx33dtu3cw8O+F2j975v8pYP4ho19mT6ZPpkS2KCrlZkffqq9VM773d+Dene/2R9+09WXKeewVz02dKzO/oV/gn59euqMw9HI01+ZcpxoF11f0am9Yq9p2qi+MoFx4NAR+viLr9nW83GAzQsYQsO4+ZrLy1Fq+ZMAZ9j0jAIj/MjBD9P5rY+PQGCLfO+/n9Or02dRMU+YqQINfdac+dTrdv1Lf8qMD9Uo/iPyGzHwId3QGC+8+Uxyw8a+pMsX5D/7swX0wF23+tNH8iTiGlfR5jVK/Xj1dsh62ng300iLLfa4x3SovD1528hbwMPZ00jcrOFOfWd2wBPdc/tNSqfUkhYiwVHzpWefVGYXtYl27N5L3/64QhtEsIUdyTmqC8Nb9+5uN+jC1IsO/ziXut10tXqpHEGK6zb86Q+LRp7+zE/wpHPHtvT8qMGKpqLOumLyAv+ETw14wDR3aKQVLW+xwdwo8XGxSt21pIU4CMdL5ul/P2hMEjDMhA3POITETPSkEYN0pIWMYPC/+rKOdH+PWwLyXbP+94CwSAVEXOMiNo7C2dQTbg8kdmE4WQJty+M6gh1zThv5iWf4co7m6Z4HuyL069NDF6a9wEzQ+OEDqMfDT2iDlWHCNVccn/mCsd8oCfHxIWelHul9R4ATaFrqcdNANPI01rE81yD0Z554NGjSG/55KWu1vyvalzbSX+wWsnf/waCTENq4kTiHzXDVug0BWQ3u25uaNq4fEK4G3HBVZ8KEiXbHERDVLnaXUYd9aSkpitatpsERbg/4BRO8rF59e5bu9q69+3XXkbyI2v+u1xFGmeMF0CKRQ2DBd0sDMmt//jlh/Y3ObsHrQfltrHVrWPrLGmU4FB9f4hPXoG5tZZipJRsYpqfOnE19ggwFkDbYTCIqGo08AwAoR0D/B3oq/mihkg55pDfNnf9dgNH6x59W0S3XV8xs9XesFUOL1QrWaMLOGE7688sMu45oRTt8hJkg1GyjNp16Dtcao+Tlmc/KGuOV5zpqxOUL49joO/A3UbVG5amzpDFBQGufUW9XYY0KQ7JwUomdRbXx0In38VsYthII/LBghP9h+SpdVq/wG/YLdh3AUAFvXBiBsai5NBKNPEtTbrg4zZuE75P4x67PLhBwxtQK7IYVJVk7Aidg4PhbGsFebpHaz83Lq2NymaCgsVWklK6XlaFGtvgEdj51Kim8TF687Z9p6sKZD1PK+OOGYdNIUQq0J9XkLwRVj1LuJydbGI+NMnLCa8agUl8f5PxU4kKi3nfczG/pDYTpd61k8QwmfMHwi4uNpeZNGlLrs5oRtL3zW5+laHPa+NrzaOSpzb+s5/D8L63zZOMGdQOICzOMFSUHDwe2d+NSEldZ64jZ1kXLfqE/N2cpBIVrkFVePm/DzjvOngyJOHHFt76MnCtLDJXO5ARKLAi0jygPmn+IvHk8s5dSpcKf255Sl0Bep4tgyICtiCMpRr+rNme3oNcnPMW+XKODdlbMJK1lAzx+mDGEVzlm2u7t/i9T+0g08jwRDJqEcMY05ouh1ILv9cPzwxFuA2OZ2muzF1Wkd8GAFj/+len006q12qJPifMwhqiy1zGxY1d/IuwVD60rmLhm3hfsVlTDbXEZvCFqcENjVAuPSua8rXWE/dLMPLxBNLOmTqDu/7pGt+dVsEeCV/y7PAUP4z+m3c0kGnmalVOaMFuIvmpMb7YuT29xMqaI7HWMybdEuRdErBD4cXXtPeCUJC08ZMQ1rpi0qn7wPA4HudlIG1tsrk569/5F3m0rKabe+f40FXFi1ukqotxolYEp+8rplQK808fxjKF2U72ylB/MONuwXm0a8ui9NPChXgRjNNbiQcPasm1HgLFYLW/7rj10V98n6d1Xx5oa7KORp1p2WY5mdsJg6Tdv3RZwC21QUWK2WNpocytvXTb8uVnZLhz2K63AGfcCHv5Ds8N6zdTUZEpj30C42hTw4v1+w8Zpo0f1POLEZUvJ4E0AW/BC641KxV1syAxGXL4c/oTU7AGUNHARO4QE18zCIVC46UNKPPO2cNFO+n34WsFhTyvhjNlGmxLSqrN92nyqVs4IIC6QFmxN0RB04ksv+ofyQ/5Y17du419swF9J8775McDvC64CXy9eTj1uuS5odaKRZ9DCTG7AkxyuAfinDCebtmwPiBLKXUCNXGhYR6mGa4+wL4YT7PZglL+zdhqDynX9xrsf8XpJvW0as88TRwwM8PtTC4DdqyKl/GwRpJb2jOq8zXJ7/13MLuamp8NTzR+mPfHs/o2ODqrC2zuXferUx9vU5K8ZzYurW2mzLMW5eV1KkfCEolx9x4PU5vJbdD/1M1rBMsZyGaOY7eRQnz/DZRSsR6sogWH7wgtaK9rYlx+8xt8zDHQwXrW25GVW2jpFI89wZf+xKStcFMV1xGxWTzuZgUxiecRhFLiRhJOsneGdo/HZNaNsMcxyGu+r1/DhwioA7U9br+W/BNq04O+HrZCCSUWv14w4ceHB4pq3I1usZn0Xk1ZBcjJvsRy8uIIpXaj41w+D4RIQ7snfRQVrx1LeL7wdcxmX7sSwjetkSKvmZwYUiy1nQskqk6/WmPnMYImKUcw6oDEOrjGVjc6MIcJvf2xWlgFp/XqghYBAtT/tej5jnhg6GJeQIM4fm7f6o0YjT3/mJ3DyAq+pNNNytVlOfHV6gEaC+x3btdFGU/Ym0wXwBfANJfCVW/JT6D6B9J0vaqssRdLmhdUNHzEhhRI822P83ckRPOOs/akjAcyMGp8fLxDVOTVY3kZXmWDxIhUe+EqIQM5xZ3WimPRM8hw67uficcRSoT2VkgpzTEvw7PmNCub2I8eqt3nf+YcotsX1HC9QM/J53VS4bhK5smZT0W72UcL3Fcso3uLcMqaITHQscl64aJkus8947yWs8TPTUDC0gv3IKDBoG+ViXvCamJCg63SYDXp52vv0yL3djdH91/A9uvXeAbqZQnTSeR9M8ceZ8OoMxZveH8AnqDMWVgcTh4m2gWUjqkQjTzXvEzlCcxgx/jWCfdBM5n37I/1n7vyAW/BWN2okZkPOFavWKS8Gs5cYMkV7YVPGcIJh6QW8dnDF6vW6qM+9NI1acz8z60+I+PqM2YqHvzYRXEBq8qaSELMF5TADYCiobT9tetgG5zMuFSnBVaATqQVrWFXGLOQPWRxf4oHsvLwMKD8lnWca7ea5sxHfvX0FFXx0F2U/m0HZL9Sm/C96UQFvEJg793o6PK0m/ypTwc/jqWgH2wE85eRd/iDtyZDzeQmOUdBJ7+3/NH224HtF84FrA4zZr7NXuvGDpUgLL/crL7nQmI2yKNpsn3XYK/CBVLO9pRYvW0n38ZYoRl+cbjf+U3E6VQvBDgNGwaJi7FtlJujkM3iPL6PATqJKNPJU8z7RI8gJ37KEsVvVRNBO2OIFpGYmd9x8TUBw+wvM7YsPsUsJXmCq1oo2x44ejzzxrLLgOSCjIAH3sG+dUfCBkP7Dx+sWzyMO9tPC0PCd/35mTEK333x8XSnsp2YE9eQzL5rODGPPt5488WJcyxpQSIQDovol6/yveDO2TyeWfMMCFIkflCibj2J9Lr4sIrutmDcbZIM1c1C4L1l7KY47Ujx/DDaR8+KMjuWZefcy/mxZyfh73zQejqllqeWBJ1HusfCEuldTpbYvckDFC9RzdKBgYmdyD7VpG1wRMKtnJhjedesziLBuziiYeWzBzqFnt2hKBw4dpr/4LYmdLY2CGb73p4zTLXvBP8P1PfqadlzEx0zTua2a01Ee5sDOgs3kjEQJb/P5s1737w4RjTzxLB/wjq9jX5ymeyz4kmG3BK2YfckadsI8fgatDxv+kRP4Z1wHqs0L2hMwM5utvur2B5Qhtja+eo42qVkjkw4dztFpylgvafTCx8tq0shBalL/ceTEKcoGfv4AzQnapk6tGtwWhUyMO023mYGW+Pl7r+ochaH14YVnJphRbNvmbEUDw6aEqv8gNDXjCxAfLVk0d7pZNiccVk6VpXTlJl12FxX9vZKKNi7SJ2CNrNjONjBbPE8m8pepyUUOG4zz+hk3JPL52Pe+OJGN9/yDjQxGfhCQRpxbF1DSWXcqITZHPG+15dLcPbVOBz3ci31j1gVdIhGKtJo0qk/9eYuaYIIZShhR+wwcqXQsbTxMbcO+EsrGgjft1IlP60gLeeCfd9SQR+jhIWMCtnTBLgL4ffjpV9ridOf4B8WWxdop/GjkqSu0HBf4mOw9d9ykaMCqKwAIFr9ggplbDJnNSAtphva7X3HaNUuPMoyTLxfx0qnL2F5Z2lUP6E94Waw22YlBbRuzshEGW+Rr44bpSAvhPW69XlnepbVJIhwCLdTodoF8Xhj9OOM2vCRSBfw1UEBkS4SBPr33CxRbu3mQjG1MVTHkjkkkZ0wV/lUlJ2WS05tJLk8mq9LVeI+fTNawUpjAVLUpMKvcJaPBcMqNytfPCYxgCPHk7yRvYeBsnSFaVC7hTY6tjEOt4DcrGPaxV58bGtDJjHHxRvzwzYnUhjWgsgjWrr31wihTPyvkg6Hd1AnDlQ8jlCVf2GKeHzXIdJ/1aORZlrqZxYX2CI02nJsK0oLoZ77ybFB7EuJc1LYN9eWdMoIRG+KoglnJ0bwzBQYHpRVoOm9NHl2qxdXaPNFP0N5mtjB86GTGy89Q2/PO1iYxPUf5aF+s3axIsY9giWaBNkccxbfqTO79W8hzMKtkyIaWCfcDpSKOegwZn7W2lBoUm9mS1yBWJnf2ZvLk8OyNmsaQh6/oIMVV73DSPg4LzQMfqUjntzXUbdXWwU8bIDCcwpaBoY52W5iAiJoAdKbru1xC0NDgm7SLv/hiJvCbAiGOYW3qwV63cX1SzaL5w2DA7XbjVcpSHgynDmebT7QgAYYp3XjfcWiAzRo38OdhPIl0ntjUzzhTi/WT2LFTKzDCY/JDK3V5iHbtFZ0IQ7+reOH4Tt6bDPuTGVzveLYwnfef6kpjmGTM7EHaPHEO22bLpo2V/Mz8nbDGEx+ZGDf834pDJz56gbWBWgHRdLm0gzbIfw6NtlP78xV3FGhxWWwCCKa544V592030Ghu8+rVjk+W+DM7doI6XdW5IzlZ29zOEzhOl34Ug76DPjyZX8JNGtZXPs7xDu9NrxX0w7u73agNith5VG1c2lrCT+vIy3dS8Q6eBQGRqGSinmuPIBxVwVKP6n3cU881x7ha7Sjj2rf5XizPNi6hnMX9yFvM/1javNT4HJbSaiAlN+2jreJJOcce3TDMlqj1O9gB8oiyrg++Wi2aNqJzecFyad7WoSoPOwSGJHACzWYjM8gQH3jA58lgUyuvYEcJzChl5+QqBJnMn++C9zhIS52lKmve0cizrHXQxsd2P7APwR4It4DaNWsouOEftzyCfLbyzg77+bNhldJSFKzQFiCKSAlsTdvYFwztDTwT4uKUz5PVq13TdGvtcOWCBGETRZ29vLSsfp1aVIdxKC8G4corzf0KIy61MtnT+1LRX0vJV5x3XKNSCUU9asmmlMQFgko6525KbT9UKSp/w9uU9+vzPJXJb4ogeWRes5xi4o8vUVLrKEdBQBA4tRGocOLyuYuoOGsN5cz6N3mPsp1JJSvtsZzEFZOUQZk9f/Yj7tr5PeWtnUzunI16kkT+XF5c9Qspo8NMf3w5EQQEAWsgUOHEpYXFufozyp03lrzObDauu4+TWFmIi4c6MUmVKK5+Z6rUaTQTVOBEac6ygeTau5iLYMc+G6/BOkZccKlIOrMXpbYYzGHlU/21zyPngoAgUDEInFTiUh6RPxVWsGIWf4sxi4p3r6finatLiEUd3qlHVSM7Rjr2Kg0pvkEnsqeeQYln3c58pVliZIKdj73lC7d+wiS5l5z8QVhP4Q6FKG3xaZTS7BFKanC3SSoJEgQEgVMRgZNPXCoqbPTz5rPxL++gEuIpOMhLhrbwcHKXsqNqTEZtcmQ24ZnAkp1LbfGpZE/DFCyYrGwCdwifO4/c/LWfgi1v8Ycz9lHm5YvLlonEFgQEgZOGwKlDXCcNAilYEBAErIYABmAigoAgIAhYCgEhLks1l1RWEBAEgIAQl/QDQUAQsBwCQlyWazKpsCAgCAhxSR8QBAQByyEgxGW5JpMKCwKCgBCX9AFBQBCwHAJCXJZrMqmwICAICHFJHxAEBAHLISDEZbkmkwoLAoKAEJf0AUFAELAcAkJclmsyqbAgIAgIcUkfEAQEAcshIMRluSaTCgsCgoAQl/QBQUAQsBwCQlyWazKpsCAgCAhxSR8QBAQByyEgxGW5JpMKCwKCgBCX9AFBQBCwHAJCXJZrMqmwICAICHFJHxAEBAHLISDEZbkmkwoLAoKAEJf0AUFAELAcAkJclmsyqbAgIAgIcUkfEAQEAcshIMRluSaTCgsCgsD/AFt/MVAlcetCAAAAAElFTkSuQmCC',
            width:150,
            height:48
        },
        right: 10,
        top:10
    }
})
const jessibuca = new JessibucaPro({
    watermarkConfig: {
        image: {
            src:"http://jessibuca.monibuca.com/jessibuca-logo.png",
            width:150,
            height:48
        },
        right: 10,
        top:10
    }
})

文字配置


const jessibuca = new JessibucaPro({
    watermarkConfig:{
        text:{
            content:'jessibuca-pro',
            fontSize:'14',
            color:'#000'
        },
        right: 10,
        top:10,
        left:10,
        bottom:10
    }

})

HTML


const jessibuca = new JessibucaPro({
    watermarkConfig:{
        html:'<div>this is a <span style='color:red'>test</span> html</div>',
        right: 10,
        top:10,
        left:10,
        bottom:10
    }

})

在单个配置项上面:优先级 image > text > rect > html

多个水印配置

配置成数组就可以支持多个水印效果。


const jessibuca = new JessibucaPro({
    watermarkConfig:[
        {
            html:'<div>this is a <span style='color:red'>test</span> html</div>',
            right: 10,
            top:10,
            left:10,
            bottom:10
        },
        {
            text:{
                content:'jessibuca-pro',
                fontSize:'14',
                color:'#000'
            },
            right: 10,
            top:10,
            left:10,
            bottom:10
        }
    ]

})

keepScreenOn

  • 类型boolean
  • 默认值true
  • 用法: 开启屏幕常亮,在手机浏览器上, canvas标签渲染视频并不会像video标签那样保持屏幕常亮。

只会在移动端生效,默认开启。

const jessibuca = new JessibucaPro({
    keepScreenOn:false
})

isNotMute(废弃)

  • 类型boolean
  • 默认值false
  • 用法: 是否开启声音,默认是关闭声音播放的。

推荐使用muted参数

是否不是静音 = 是否开启声音

配置了不一定会生效,因为浏览器的限制,只有在用户主动触发事件后才能播放声音。

优先级低于muted,已经废弃,推荐使用muted参数。

muted

  • 类型boolean
  • 默认值true
  • 用法: 是否静音。

优先级高于isNotMute

const jessibuca = new JessibucaPro({
    muted:false // 开启声音
})

loadingIcon

  • 类型boolean
  • 默认值true
  • 用法: 加载过程中的时候,是否显示加载icon。
const jessibuca = new JessibucaPro({
    loadingIcon:false
})

loadingIconStyle

  • 类型object
  • 默认值{}
  • 用法: 加载过程中的时候,加载icon的样式。

支持的参数有

const jessibuca = new JessibucaPro({
    loadingIconStyle:{
        width:50, // number类型 默认值 50
        height:50, // number类型 默认值 50
        background:'https://www.jessibuca.com/loading.gif', // 默认值 系统自带的background, 参考:background-image: url(${options.background}) 的值
        hasAnimation:true // 默认值 true
    }
})

loadingText

  • 类型string
  • 默认值:``
  • 用法: 加载过程中文案。
const jessibuca = new JessibucaPro({
    loadingText:'疯狂加载中...'
})

background

  • 类型string
  • 默认值:``
  • 用法: 播放前的背景图片(海报),只会出现在播放器初始化且未播放的状态下。

主要设置 background-image: url(${options.background}) 的值。

const jessibuca = new JessibucaPro({
    background:'https://www.jessibuca.com/background.jpg'
})

poster

  • 类型string
  • 默认值:``
  • 用法: 等同于background参数。poster 优先级高于background
const jessibuca = new JessibucaPro({
    poster:'https://www.jessibuca.com/poster.jpg'
})

backgroundLoadingShow

  • 类型boolean
  • 默认值false
  • 用法: 如果配置了background参数,在loading 过程中的时候还继续显示background配置的图片。

是否在loading的时候显示背景图片

const jessibuca = new JessibucaPro({
    background:'https://www.jessibuca.com/background.jpg',
    backgroundLoadingShow:true
})

useMSE

  • 类型boolean
  • 默认值false
  • 用法: 是否开启MediaSource硬解码

视频编码支持H.264视频(Safari on iOS 需要到17.1版本以上才支持)

Chrome 107及以上支持H.265硬解码

Safari on iOS不支持H.265硬解码

> 不支持 forceNoOffscreen 为 false (开启离屏渲染)

优先级高于useWCS:true

const jessibuca = new JessibucaPro({
    useMSE:true
})

mseUseCanvasRender(废弃)

  • 类型boolean
  • 默认值false
  • 用法: MediaSource硬解码通过canvas播放流数据

推荐使用useCanvasRender 参数

推荐使用videoRenderType 参数

const jessibuca = new JessibucaPro({
    videoRenderType:'canvas' // 使用canvas渲染
})

hlsUseCanvasRender(废弃)

  • 类型boolean
  • 默认值false
  • 用法: hls通过canvas播放流数据

推荐使用useCanvasRender 参数

推荐使用videoRenderType 参数

const jessibuca = new JessibucaPro({
    videoRenderType:'canvas' // 使用canvas渲染
})

webrtcUseCanvasRender(废弃)

  • 类型boolean
  • 默认值false
  • 用法: webrtc通过canvas播放流数据

推荐使用useCanvasRender 参数

推荐使用videoRenderType 参数

const jessibuca = new JessibucaPro({
    videoRenderType:'canvas' // 使用canvas渲染
})

useWCS

  • 类型boolean
  • 默认值false
  • 用法: 是否开启Webcodecs硬解码

视频编码只支持H.264视频 (需在chrome 94版本以上,需要https或者localhost环境)

Chrome 107及以上支持H.265硬解码

Safari 16.4版本之后正式提供的WCS硬解码(视频)H.264支持

> 支持 forceNoOffscreen 为 false (开启离屏渲染)

如果同时设置了useMSE:true, 则优先使用useMSE

const jessibuca = new JessibucaPro({
    useWCS:true
})

wcsUseVideoRender(废弃)

  • 类型boolean
  • 默认值true
  • 用法: Webcodecs硬解码之后通过video播放流数据,仅仅useWCS 为true的时候有效

推荐使用 useVideoRender 参数

推荐使用videoRenderType 参数

const jessibuca = new JessibucaPro({
    videoRenderType:'video' // 使用video渲染
})

wcsUseWebgl2Render

  • 类型boolean
  • 默认值false
  • 用法: Webcodecs硬解码之后通过canvas 渲染的时候,使用webgl2播放流数据,仅仅useWCS 为true的时候有效

只有在canvas渲染的时候才会生效。

const jessibuca = new JessibucaPro({
    useWCS:true, // 需要https 环境
    videoRenderType:'canvas', // 使用canvas渲染
    wcsUseWebgl2Render:true
})

useSIMD

  • 类型boolean
  • 默认值false
  • 用法: 是否使用SIMD 软解码,仅仅wasm软解码的时候有效

只会在wasm解码的时候才会生效

使用Chrome/Edge 91, Firefox89及之后正式提供的SIMD指令集加速解码, 在1080P以上分辨率带来100%-300%的性能提升

尤其在HEVC的解码上提升非常明显.

Safari暂不支持

const jessibuca = new JessibucaPro({
    useSIMD:true
})

isFFmpegSIMD

  • 类型boolean
  • 默认值false
  • 用法: 是否使用FFmpeg SIMD 软解码,useSIMD:true时才会生效

只会在useSIMD:true的时候才会生效,需要捆绑一起使用。

const jessibuca = new JessibucaPro({
    useSIMD:true,
    isFFmpegSIMD:true, // 配置使用 FFmpeg SIMD 软解码
})

wasmUseVideoRender(废弃)

  • 类型boolean
  • 默认值false
  • 用法: wasm软解码之后通过video播放流数据,仅仅wasm软解码的时候有效

推荐使用 useVideoRender 参数

推荐使用videoRenderType 参数

const jessibuca = new JessibucaPro({
    videoRenderType:'video' // 使用video渲染
})

wasmDecodeErrorReplay(废弃)

  • 类型boolean
  • 默认值true
  • 用法: 是否开启解码失败重新播放

推荐使用:playFailedAndReplay参数

wasm解码报错之后,不再抛出异常,而是直接重新播放视频地址。

当配置了playFailedAndReplay:false的时候,解码失败的时候,不会自动重新播放, 会抛出playFailedAndPaused事件。

const jessibuca = new JessibucaPro({
    playFailedAndReplay:false //
})

mseDecodeErrorReplay(废弃)

  • 类型boolean
  • 默认值true
  • 用法: mse解码报错之后,是否重新播放

推荐使用:playFailedAndReplay参数

mse解码报错之后,不再抛出异常,而是直接重新播放视频地址。

当配置了playFailedAndReplay:false的时候,解码失败的时候,不会自动重新播放,会抛出playFailedAndPaused事件。

const jessibuca = new JessibucaPro({
    playFailedAndReplay:false //
})

wcsDecodeErrorReplay(废弃)

  • 类型boolean
  • 默认值true
  • 用法: wcs解码报错之后,是否重新播放

推荐使用:playFailedAndReplay参数

wcs解码报错之后,不再抛出异常,而是直接重新播放视频地址。

当配置了playFailedAndReplay:false的时候,解码失败的时候,不会自动重新播放,会抛出playFailedAndPaused事件。

const jessibuca = new JessibucaPro({
    playFailedAndReplay:false //
})

autoWasm

  • 类型boolean
  • 默认值true
  • 用法: 在使用MSE或者 Webcodecs 播放H265的时候,是否自动降级到wasm模式。

在MSE或者WCS解码出现错误的时候,如果配置的playFailedAndReplay:true的前提下。

如果配置了autoWasm:true, 则会自动降级到wasm模式播放。

在多屏的情况下,如果解码失败,配置了autoWasm:true,则会自动降级到wasm模式播放,会加大CPU的负担。

playFailedAndReplay:false的时候,解码失败的时候,不会自动降级到wasm模式播放。

如果decoderErrorAutoWasmhardDecodingNotSupportAutoWasm 没有配置,初始化的时候会被赋予和autoWasm一样的值。

这个参数只会在初始化播放器的时候,用于初始化decoderErrorAutoWasmhardDecodingNotSupportAutoWasm 这两个值,业务判断的时候是不会用到autoWasm了。

const jessibuca = new JessibucaPro({
    autoWasm:false // 不自动降级到wasm模式
})

decoderErrorAutoWasm

  • 类型boolean
  • 默认值true
  • 用法在播放过程中:如果解码出现错误,是否自动降级到wasm模式。

如果decoderErrorAutoWasm 没有配置,初始化的时候会被赋予和autoWasm一样的值。

const jessibuca = new JessibucaPro({
    decoderErrorAutoWasm:false // 如果解码出现错误,不自动降级到wasm模式
})

hardDecodingNotSupportAutoWasm

  • 类型boolean
  • 默认值true
  • 用法在播放器初始化播放的时候:如果硬解码不支持,是否自动降级到wasm模式。

如果hardDecodingNotSupportAutoWasm 没有配置,初始化的时候会被赋予和autoWasm一样的值。

const jessibuca = new JessibucaPro({
    hardDecodingNotSupportAutoWasm:false // 如果硬解码不支持,不自动降级到wasm模式
})

hotKey

  • 类型boolean
  • 默认值false
  • 用法: 是否开启键盘快捷键

目前支持的键盘快捷键有:

  1. esc -> 退出全屏;
  2. arrowUp -> 声音增加;
  3. arrowDown -> 声音减少;

playVod 点播模式下额外支持

  1. arrowLeft -> 快退;
  2. arrowRight -> 快进;
const jessibuca = new JessibucaPro({
    hotKey:true
})

controlAutoHide

  • 类型boolean
  • 默认值false
  • 用法: 控制栏是否自动隐藏

只有鼠标聚焦到播放器内部才会显示,移除之后,会消失。

只支持pc端,移动端不生效。

const jessibuca = new JessibucaPro({
    controlAutoHide:true
})

controlAutoHideDelayTime

  • 类型number
  • 默认值5
  • 用法: 控制栏自动隐藏延迟时间,单位秒
const jessibuca = new JessibucaPro({
    controlAutoHide:true,
    controlAutoHideDelayTime:10
})

playbackConfig

playback-api

openWebglAlignment

  • 类型boolean
  • 默认值false
  • 用法: webgl渲染是否每次取1字节的数据,仅在使用canvas webgl渲染的时候生效。

当播放的流的宽高不是4的倍率的时候,就有可能出现webgl渲染发绿的问题。

const jessibuca = new JessibucaPro({
    videoRenderType:'canvas',
    openWebglAlignment:true
})

为了解决 视频渲染发绿(软解码)

playbackForwardMaxRateDecodeIFrame

playback-api

useVideoRender(废弃)

  • 类型boolean
  • 默认值true
  • 用法:是否使用video标签进行渲染

方便一键式配置渲染元素。

ios 不支持wasm解码video标签渲染,所以如果是ios,会自动切换成canvas渲染。

目前这种方式会有个弊端,需要一次性设置两个参数,比如设置video渲染

则需要配置

{
    useVideoRender:true,
    useCanvasRender:false
}

所以升级了参数

推荐使用videoRenderType 参数

const jessibuca = new JessibucaPro({
    videoRenderType:'video'
})

useCanvasRender(废弃)

  • 类型boolean
  • 默认值false
  • 用法:是否使用canvas标签进行渲染

方便一键式配置渲染元素。

目前这种方式会有个弊端,需要一次性设置两个参数,比如设置canvas渲染

则需要配置

{
    useVideoRender:false,
    useCanvasRender:true
}

推荐使用videoRenderType 参数

const jessibuca = new JessibucaPro({
    videoRenderType:'canvas'
})

videoRenderType

  • 类型string
  • 默认值video
  • 用法:视频渲染方式,支持videocanvas

该参数是用于替换useVideoRenderuseCanvasRender 参数的。

{
    videoRenderType:'video'|'canvas'
}
const jessibuca = new JessibucaPro({
    videoRenderType:'canvas'
})

useWebGPU

  • 类型boolean
  • 默认值false
  • 用法:canvas标签渲染下,是否使用web GPU引擎渲染

在canvas标签渲染下,默认的是使用webgl进行渲染。

useWebCanvas

  • 类型boolean
  • 默认值false
  • 用法:canvas标签渲染下,是否使用canvas引擎渲染

在canvas标签渲染下,默认的是使用webgl进行渲染。

使用的是context2D的方式进行渲染,可以突破掉浏览器上面的webgl的16个上下文的限制。

networkDelay

  • 类型number
  • 默认值10
  • 用法:单位秒(s), 根据本地时间戳和流播放的时间戳,检测网络播放延迟。

如果流的时间戳有问题,会导致networkDelay计算的有问题。

深入了解网络延迟的计算 关于网络延迟

networkDelayTimeoutReplay

  • 类型boolean
  • 默认值false
  • 用法:设置网络超时之后,是否重新播放。

如果设置为true,那么当网络超时之后,会重新播放。

因为这个参数的特殊性,如果配置 false 并不会暂停播放。 所以如果业务层需要自己做超时处理,则只需要自己监听

当配置了playFailedAndReplay:false的时候,触发超时的时候,不会自动重新播放。

// 监听一次(once)即可。
jessibucaPro.once('networkDelayTimeout', () => {
    // do something
})

syncAudioAndVideo

  • 类型boolean
  • 默认值false
  • 用法:是否根据时间戳来音视频同步。

播放器内部默认是根据流的顺序来进行音视频同步播放的。

如果设置为true,那么就是根据时间戳来进行音视频同步播放的。

如果流里面的音视频的时间戳本身就是不同步的,设置为true之后,会导致音频播放异常。

const jessibuca = new JessibucaPro({
    syncAudioAndVideo:true
})

syncAudioAndVideoDiff

  • 类型number
  • 默认值500 单位ms
  • 用法:配合syncAudioAndVideo参数,音视频同步。
const jessibuca = new JessibucaPro({
    syncAudioAndVideo:true,
    syncAudioAndVideoDiff:300 // 单位 ms
})

recordType

  • 类型string
  • 默认值mp4
  • 用法:视频录制默认的格式,支持webmmp4flv
{
    recordType:'mp4'|'webm'|'flv'
}

目前对于mp4格式的录制,只支持视频录制,不支持音频录制。如果需要音频和视频一起录制,可以选择webm或者flv格式。

或者可以考虑下 wasm mp4 录制扩展插件,可以咨询 微信:bosswancheng 购买

const jessibuca = new JessibucaPro({
    recordType:'webm'
})

ptzClickType

  • 类型string
  • 默认值click
  • 用法:ptz 操作指令点击事件类型,支持clickmouseDownAndUp

click 事件 会在点击之后,立即触发ptz arrow事件,300ms之后触发stop事件。

mouseDownAndUp 会在鼠标按下,立即触发ptz arrow事件,鼠标松开,触发stop事件。

当配置了 click 参数,可以通过设置ptzStopEmitDelay 参数来控制stop事件的触发时间。

{
    ptzClickType:'click'|'mouseDownAndUp'
}
const jessibuca = new JessibucaPro({
    ptzClickType:'mouseDownAndUp'
})

ptzShowType

  • 类型string
  • 默认值vertical
  • 用法:ptz 布局类型,支持vertical 垂直 和 level 水平

主要是ptz方向按键 和 扩展按键的布局,支持垂直 vertical水平 level 两种布局方式。

{
    ptzShowType:'vertical'|'level'
}
const jessibuca = new JessibucaPro({
    ptzShowType:'level'
})

ptzSupportDraggable

  • 类型boolean
  • 默认值false
  • 用法:ptz 是否支持拖拽
const jessibuca = new JessibucaPro({
    ptzSupportDraggable:true // 支持拖拽
})

ptzPositionConfig

  • 类型object
  • 默认值{}
  • 用法:ptz 初始化位置配置,支持left right top bottom 四个方向的配置。参考 css 配置
{
    ptzPositionConfig: {
        left: 10,
        right:10,
        top:10,
        bottom:10
    }
}
const jessibuca = new JessibucaPro({
    // 其他参数
    ptzPositionConfig: {
        left: 10,
        right:10,
        top:10,
        bottom:10
    }
})

ptzStopEmitDelay

  • 类型string
  • 默认值0.3 单位
  • 用法:ptz 操作指令点击事件类型为click的时候,当点击之后,多少秒之后触发stop事件。
const jessibuca = new JessibucaPro({
    ptzClickType:'click',
    ptzStopEmitDelay:0.5 // 0.5秒之后触发stop事件
})

ptzMoreArrowShow

  • 类型boolean
  • 默认值false
  • 用法:是否显示ptz 的左上,右上,左下,右下按钮
const jessibuca = new JessibucaPro({
    ptzMoreArrowShow:true
})

ptzZoomShow

  • 类型boolean
  • 默认值false
  • 用法:是否显示ptz zoom(镜头) 按钮
const jessibuca = new JessibucaPro({
    ptzZoomShow:true
})

ptzApertureShow

  • 类型boolean
  • 默认值false
  • 用法:是否显示ptz aperture(聚焦) 按钮
const jessibuca = new JessibucaPro({
    ptzApertureShow:true
})

ptzFocusShow

  • 类型boolean
  • 默认值false
  • 用法:是否显示ptz focus(光圈) 按钮
const jessibuca = new JessibucaPro({
    ptzFocusShow:true
})

ptzCruiseShow

  • 类型boolean
  • 默认值false
  • 用法:是否显示ptz cruise(巡航) 按钮
const jessibuca = new JessibucaPro({
    ptzCruiseShow:true
})

ptzFogShow

  • 类型boolean
  • 默认值false
  • 用法:是否显示ptz fog(透雾) 按钮
const jessibuca = new JessibucaPro({
    ptzFogShow:true
})

ptzWiperShow

  • 类型boolean
  • 默认值false
  • 用法:是否显示ptz wiper(雨刷) 按钮
const jessibuca = new JessibucaPro({
    ptzWiperShow:true
})

extendOperateBtns

  • 类型array
  • 默认值[]
  • 参数
    • {string} name 必填 类似uuid 用于区分按钮
    • {number} index 选填 排序字段,默认值 0
    • {string} icon 必填 按钮图标,支持base64 或者src,主要是设置background-url 属性
    • {string} iconHover 选填 按钮hover图标,等同于icon
    • {string} iconTitle 选填 按钮图标title
    • {string} activeIcon 选填 按钮active图标,等同于icon
    • {string} activeIconHover 选填 按钮active hover图标,等同于icon
    • {string} activeIconTitle 选填 按钮active图标title
    • {function} click 必填 按钮点击事件
    • {function} activeClick 选填 active 状态下按钮点击事件(需要配置activeIcon 才会生效)
    • {string} createdMoment 选填 按钮创建的时机, (支持:created,loading,playing 三个阶段配置),默认playing
  • 用法:添加自定义按钮

回调参数 (event)

多屏模式下会传递(event,index),index 是窗口的下标。

createdMoment 如果是createdloading阶段创建的,那在暂停的时候也会显示。

const jessibuca = new JessibucaPro({
    extendOperateBtns:[
        {
            name: 'testBtn',
            index: 2,
            icon: '/expand.png',
            iconHover: '/expand-hover.png',
            iconTitle: '测试hover',
            activeIcon: '/zoom-stop.png',
            activeIconHover: '/zoom-stop-hover.png',
            activeIconTitle: '测试active-hover',
            click: (event, index) => {
                // 当multi 多屏模式下,会传递窗口的下标
                console.log('test click')
            },
            activeClick: (event, index) => {
                // 当multi 多屏模式下,会传递窗口的下标
                console.log('test active click')
            },
        },
        {
            name: 'testBtn2',
            index: 5,
            icon: 'data:image/png;base64,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',
            iconHover: 'data:image/png;base64,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',
            iconTitle: '测试hover2',
            click: () => {
                console.log('test click2')
            },
        }
    ]
})

contextmenuBtns

  • 类型array
  • 默认值[]
  • 参数
    • {string} content 必填
    • {number} index 选填 排序字段,默认值 0
    • {function} click 必填 点击事件
  • 用法:添加自定义右键菜单按钮

如果配置了disableContextmenu:true ,则不会生效。

const jessibuca = new JessibucaPro({
    contextmenuBtns: [
        {
            content: '测试1',
            index: 0,
            click: () => {
                console.log('test click1')
            },
        },
        {
            content: '测试2',
            index: 1,
            click: () => {
                console.log('test click2')
            },
        }
    ]
})

checkFirstIFrame

  • 类型boolean
  • 默认值true
  • 用法:是否检测第一个iframe,如果为true,则会在播放的时候,首帧必须是i帧的时候,才会去解码,如果不是i帧,就会一直等待i帧的出现。

如果设置为false,则会不判断首帧是否是i帧,可能会出现绿屏或者花屏的情况。

const jessibuca = new JessibucaPro({
    checkFirstIFrame: false
})

audioEngine

  • 类型string
  • 默认值'null'
  • 用法:设置音频引擎,可选值有'worklet''script''active'、,默认值为'null',会自动选择最佳的音频引擎。

worklet:使用webworklet,需要浏览器支持(需要https环境),如果不支持,会自动降级到script引擎。

active:是为了兼容安卓的微信端播放的,一般情况下,在安卓的微信端,默认会使用active引擎。

script:使用script引擎,一般情况下,会自动选择这个引擎(兼容性最好的音频播放音频)。

{
    audioEngine: 'worklet'|'script'|'active'|null
}

const jessibuca = new JessibucaPro({
    audioEngine: 'worklet'
})

weiXinInAndroidAudioBufferSize(废弃)

  • 类型number
  • 默认值4800
  • 用法:安卓微信端的音频缓冲大小,单位是字节。

只会在安卓微信端生效(audioEngine参数设置为 null 或者 active),其他情况下,不会生效。

一般情况下,不需要设置这个参数,如果出现音频播放卡顿的情况,可以尝试设置这个参数。

属于高级参数,一般情况下,不需要设置。如有需要,可以联系作者。

isShowRecordingUI

  • 类型boolean
  • 默认值true
  • 用法:是否显示录制的UI(在没有配置底部的录制按钮的情况下),如果为true,则会显示录制的UI,如果为false,则不显示录制的UI。

方便通过直接调用js的录制方法的时候,可以显示录制的UI。

录制中的UI默认是根据底部按钮的配置来显示的,如果没有配置底部按钮,则会根据这个配置来显示。

const jessibuca = new JessibucaPro({
    isShowRecordingUI: false
})

isShowZoomingUI

  • 类型boolean
  • 默认值true
  • 用法:是否显示电子放大的UI(在没有配置底部的缩放按钮的情况下),如果为true,则会显示电子放大的UI,如果为false,则不显示缩放的UI。

方便通过直接调用js的缩放方法的时候,可以显示缩放的UI。

缩放中的UI默认是根据底部按钮的配置来显示的,如果没有配置底部按钮,则会根据这个配置来显示。

const jessibuca = new JessibucaPro({
    isShowZoomingUI: false
})

useFaceDetector

  • 类型boolean
  • 默认值false
  • 用法:是否使用人脸检测,如果为true,则会使用人脸检测,如果为false,则不使用人脸检测。

人脸检测的功能,需要额外的引入 jswasm 文件。

const jessibuca = new JessibucaPro({
    useFaceDetector: true
})

useWebFullScreen

  • 类型boolean
  • 默认值false
  • 用法:是否使用web全屏(旋转90度)(只会在移动端生效),IOS环境下默认设置为true。

web全屏使用的是css方式实现的伪全屏,实现的是横屏播放的。建议关闭手机的自动旋转,否则会跟着手机的旋转而旋转。

const jessibuca = new JessibucaPro({
    useWebFullScreen: true
})

fullscreenWatermarkConfig

  • 类型object
  • 默认值{}
  • 参数:全屏水印配置
  • 参数
    • {string} text 必填 水印内容
    • {number} opacity 选填 透明度 默认:0.15 参考css opacity
    • {number} angle 选填 倾斜角度 默认:15 参考css transform rotate
    • {string} color 选填 字体颜色 默认:black 参考 css color
    • {number} fontSize 选填 字体大小 默认:18px ,参考css的font-size
    • {string} fontFamily 选填 字体 默认:微软雅黑,参考css font-family
    • {number} xSpace 选填 水印横向间距 默认:100,参考css的margin
    • {number} ySpace 选填 水印纵向间距 默认:100,参考css的margin
const jessibuca = new JessibucaPro({
    fullscreenWatermarkConfig: {
        text: '测试水印',
        opacity: 0.15,
        angle: 15,
        color: 'black',
        fontSize: '18px',
        fontFamily: '微软雅黑'
    }
})

pageVisibilityHiddenTimeout

  • 类型number
  • 默认值5 * 60 5 分钟
  • 用法:监听窗口不可见的超时时间,单位秒。如果为0,则不会监听窗口不可见的事件。

需要监听visibilityHiddenTimeout 事件来监听事件

// 配置信息:
{
    pageVisibilityHiddenTimeout: 5 * 60
}
const jessibuca = new JessibucaPro({
    pageVisibilityHiddenTimeout: 5 * 60 // 单位秒
})


player.on('visibilityHiddenTimeout', function () {
    // 窗口不可见5分钟超时
});

heartTimeoutReplayUseLastFrameShow(废弃)

  • 类型boolean
  • 默认值true
  • 用法:播放过程中,超时重连时,是否使用最后一帧来显示。

推荐使用 replayUseLastFrameShow 参数

const jessibuca = new JessibucaPro({
    replayUseLastFrameShow: true
})

replayUseLastFrameShow

  • 类型boolean
  • 默认值true
  • 用法:触发重播的时候,是否使用最后一帧来显示。

heartTimeoutReplayUseLastFrameShow 是历史版本的遗留(不推荐使用了)。

replayUseLastFrameShow 配置优先级高于 heartTimeoutReplayUseLastFrameShow。

replayUseLastFrameShow 配置了之后,会覆盖 heartTimeoutReplayUseLastFrameShow 的配置。

const jessibuca = new JessibucaPro({
    replayUseLastFrameShow: true
})

replayShowLoadingIcon

  • 类型boolean
  • 默认值false
  • 用法:触发重播的时候,是否显示加载中icon。
const jessibuca = new JessibucaPro({
    replayShowLoadingIcon: true
})

controlHtml

  • 类型string | DOM
  • 默认值''
  • 用法:自定义控制栏的html,如果配置了这个参数,则会在底部控制栏渲染出来。
{
    controlHtml:'<div>自定义控制栏</div>'
}
const jessibuca = new JessibucaPro({
    controlHtml: '<div>自定义控制栏</div>'
})

supportLockScreenPlayAudio

  • 类型boolean
  • 默认值false
  • 用法:是否支持锁屏播放音频(移动端)

主要作用于移动端(手机、平板),在锁屏、后台运行的时候,是否支持播放音频。

const jessibuca = new JessibucaPro({
    supportLockScreenPlayAudio: true
})

isDecoderUseCDN

  • 类型boolean
  • 默认值false
  • 用法:decoder 是否使用cdn地址(绝对地址)

如果配置了true,且decoder 是 http(s)://cdn.com/deocder.js 绝对地址。

播放器内部会执行:

const blob = new Blob([`importScripts("${decoder}")`], {"type": 'application/javascript'});
decoder = window.URL.createObjectURL(blob);

另外需要修改 decoder-pro.js,decoder-pro-simd.js,decoder-pro-audio.js 里面引用 wasm 文件

decoder-pro.js 文件里面需要将decoder-pro.wasm 修改为http(s)://cdn.com/decoder-pro.wasm

decoder-pro-simd.js 文件里面需要将decoder-pro-simd.wasm 修改为http(s)://cdn.com/decoder-pro-simd.wasm

decoder-pro-audio.js 文件里面需要将decoder-pro-audio.wasm 修改为http(s)://cdn.com/decoder-pro-audio.wasm

需要修改 rollup.config.js 文件里面的

// wasm
// JESSIBUCA_PRO_WASM_URL:JSON.stringify('http://jessibuca.monibuca.com/pro/decoder-pro.wasm'),
// simd wasm
// JESSIBUCA_PRO_SIMD_WASM_URL:JSON.stringify('http://jessibuca.monibuca.com/pro/decoder-pro-simd.wasm'),
// audio wasm
// JESSIBUCA_PRO_AUDIO_WASM_URL:JSON.stringify('http://jessibuca.monibuca.com/pro/decoder-pro-audio.wasm'),
// wasm mt
// JESSIBUCA_PRO_MT_WORKER_WASM_URL:JSON.stringify('http://jessibuca.monibuca.com/pro/decoder-pro-mt-worker.wasm'),
// JESSIBUCA_PRO_MT_WORKER_JS_URL:JSON.stringify('http://jessibuca.monibuca.com/pro/decoder-pro-mt-worker.worker.js'),
// wasm simd mt
// JESSIBUCA_PRO_SIMD_MT_WORKER_WASM_URL:JSON.stringify('http://jessibuca.monibuca.com/pro/decoder-pro-simd-mt-worker.wasm'),
// JESSIBUCA_PRO_SIMD_MT_WORKER_JS_URL:JSON.stringify('http://jessibuca.monibuca.com/pro/decoder-pro-simd-mt-worker.worker.js'),
// wasm old wasm
// JESSIBUCA_PRO_OLD_WASM_URL:JSON.stringify('http://jessibuca.monibuca.com/pro/decoder-pro-old.wasm'),

配置放开,并修改成CDN的绝对地址。

然后运行 npm run build 重新打包。

supportHls265

  • 类型boolean
  • 默认值false
  • 用法:是否私用新的hls265解码器

新的解码器支持 m3u8+tsm3u8+mp4 格式,支持H264/H265 ,支持 硬解码+软解码

老的解码器只支持H264,硬解码。

稳定性不如老的解码器,如果只有H264的需求,不推荐开启位true。

const jessibuca = new JessibucaPro({
    supportHls265: true // 启动新的解码器
})

isEmitSEI

  • 类型boolean
  • 默认值false
  • 用法:是否需要抛出SEI数据(如果流数据里面有)
const jessibuca = new JessibucaPro({
    isEmitSEI: true
})

isEmitTsPrivateData

  • 类型boolean
  • 默认值false
  • 用法:是否需要抛出ts流里面的私有数据(如果流数据里面有)
const jessibuca = new JessibucaPro({
    isEmitTsPrivateData: true
})

pauseAndNextPlayUseLastFrameShow(废弃)

  • 类型boolean
  • 默认值false
  • 用法:调用pause()方法,再次调用play()方法的时候使用最后一帧来显示。

使用replayUseLastFrameShow参数代替

const jessibuca = new JessibucaPro({
    replayUseLastFrameShow: true
})

demuxUseWorker

  • 类型boolean
  • 默认值true
  • 用法:硬解码(MSE,WCS)是否在worker里面请求数据+解封装

多屏情况下,配置为true可以减少主线程的压力,提升性能,减少卡顿情况。 推荐如果页面有多屏需求,可以配置为true,可以提升页面性能。

const jessibuca = new JessibucaPro({
    demuxUseWorker: true
})

aspectRatio

  • 类型string
  • 默认值default
  • 用法:视频的宽高比例
  • 可选值default16:94:3

如果视频的宽高比例和配置的不一致,会导致视频变形。

{
    aspectRatio: '16:9'|'4:3'|'default'
}

const jessibuca = new JessibucaPro({
    aspectRatio: '16:9'
})

playFailedAndReplay

  • 类型boolean
  • 默认值true
  • 用法:播放失败后,是否自动重播

只需要设置这一个参数就行了,不需要像之前设置那么多原子化的参数了。

其中包含了降级到 wasm(simd) 逻辑。如果 playFailedAndReplay:false 则不会降级到 wasm

会统一触发playFailedAndPaused事件,可以监听这个事件来处理播放失败的情况。

const jessibuca = new JessibucaPro({
    playFailedAndReplay: true
})

ghostWatermarkConfig

  • 类型object

  • 默认值{}

  • 参数

    • {number} on 选填 幽灵模式开启时间 默认5 单位 秒
    • {number} off 选填 幽灵模式关闭时间 默认5 单位 秒
    • {string} content 必填 水印内容
    • {number} opacity 选填 透明度 默认:0.15 参考css opacity
    • {string} color 选填 字体颜色 默认:white 参考 css color
    • {number} fontSize 选填 字体大小 默认:12 ,参考css的font-size
    • {number} speed 选填 水印移动速度 默认:0.2, 0.1-1 之间
  • 用法:幽灵水印设置

const jessibuca = new JessibucaPro({
    ghostWatermarkConfig: {
        on: 5,
        off: 5,
        content: '幽灵水印',
        opacity: 0.15,
        color: 'white',
        fontSize: 12,
        speed: 0.2
    }
})

dynamicWatermarkConfig

  • 类型object

  • 默认值{}

  • 参数

    • {string} content 必填 水印内容
    • {number} opacity 选填 透明度 默认:0.15 参考css opacity
    • {string} color 选填 字体颜色 默认:white 参考 css color
    • {number} fontSize 选填 字体大小 默认:12 ,参考css的font-size
    • {number} speed 选填 水印移动速度 默认:0.2, 0.1-1 之间
  • 用法:动态水印设置

const jessibuca = new JessibucaPro({
    dynamicWatermarkConfig: {
        content: '动态水印',
        opacity: 0.15,
        color: 'white',
        fontSize: 12,
        speed: 0.2
    }
})

useMThreading

  • 类型boolean
  • 默认值false
  • 用法:是否使用多线程解码,支持wasm、wasm(simd)

配置开启多线程解码见:多线程解码

const jessibuca = new JessibucaPro({
    useMThreading: true
})

isDropSameTimestampGop(废弃)

  • 类型boolean
  • 默认值false
  • 用法:是否开启当遇到相同时间戳的gop的时候,丢弃这个gop

不推荐设置这个参数,会导致画面卡顿。

这个参数是为了解决一些特殊的流。

之前有遇到过当流里面有相同时间戳的帧,会导致解码器报错的情况(应该是流本身的问题导致的),为了兼容这种流,播放器支持配置这个参数。

playFailedAndPausedShowMessage

  • 类型boolean

  • 默认值false

  • 用法:当触发playFailedAndPaused事件的时候,显示错误提示信息。

const jessibuca = new JessibucaPro({
    playFailedAndPausedShowMessage: true
})

showMessageConfig

  • 类型object
  • 默认值{}
  • 用法: 配置playFailedAndPausedShowMessage显示的错误信息。

如果有国际化的需求,也是需要全部配置成对应的i18n信息。

目前的错误信息有:

const showMessageConfig = {
    playIsNotPauseOrUrlIsNull: '播放地址不能为空',
    webglAlignmentError: 'Webgl 渲染失败',
    webglContextLostError: 'webgl 上下文丢失',
    mediaSourceH265NotSupport: '不支持硬解码H265',
    mseSourceBufferFull: '缓冲区已满',
    mediaSourceAppendBufferError: '初始化解码器失败',
    mseSourceBufferError: '解码失败',
    mseAddSourceBufferError: '初始化解码器失败',
    mseWorkerAddSourceBufferError: '初始化解码器失败',
    mediaSourceDecoderConfigurationError: '初始化解码器失败',
    mediaSourceTsIsMaxDiff: '流异常',
    mseWidthOrHeightChange: '流异常',
    mediaSourceAudioG711NotSupport: '硬解码不支持G711a/u音频格式',
    mediaSourceAudioInitTimeout: '初始化音频解码器失败',
    mediaSourceAudioNoDataTimeout: '等待音频数据超时',
    mediaSourceUseCanvasRenderPlayFailed: 'MediaSource解码使用canvas渲染失败',
    mediaSourceBufferedIsZeroError: "流异常",
    webcodecsH265NotSupport: '不支持硬解码H265',
    webcodecsUnsupportedConfigurationError: '初始化解码器失败',
    webcodecsDecodeConfigureError: '初始化解码器失败',
    webcodecsDecodeError: '解码失败',
    webcodecsAudioInitTimeout: '初始化音频解码器失败',
    webcodecsAudioNoDataTimeout: '等待音频数据超时',
    wcsWidthOrHeightChange: '解码失败',
    wasmDecodeError: '解码失败',
    simdDecodeError: '解码失败',
    simdDecodeDelayTimeout: '首帧解码超时',
    wasmWidthOrHeightChange: '流异常',
    wasmUseVideoRenderError: 'video自动渲染失败',
    videoElementPlayingFailed: 'video自动渲染失败',
    simdH264DecodeVideoWidthIsTooLarge: '不支持该分辨率的视频',
    networkDelayTimeout: '网络超时重播失败',
    fetchError: '请求失败',
    streamEnd: '请求结束',
    websocket1006Error: '流异常结束',
    websocketError: '请求失败',
    webrtcError: '请求失败',
    hlsError: '请求失败',
    decoderWorkerInitError: '初始化worker失败',
    decoderWorkerWasmError: 'wasm解码失败',
    videoElementPlayingFailedForWebrtc: 'video自动渲染失败',
    videoInfoError: '解析视频分辨率失败',
    webrtcStreamH265: 'webrtc不支持H265',
    delayTimeout: '播放超时重播失败',
    loadingTimeout: '加载超时重播失败',
    loadingTimeoutRetryEnd: '加载超时重播失败',
    delayTimeoutRetryEnd: '播放超时重播失败',
    flvDemuxBufferSizeTooLarge: 'FLV待解封装buffer过大',
    audioChannelError: '音频通道错误',
    aliyunRtcError: '请求失败',
    mseWaitVideoCanplayTimeout: '流异常',
    initDecoderWorkerTimeout: '初始化解码worker超时',
}

const jessibuca = new JessibucaPro({
    showMessageConfig: showMessageConfig
})

如果需要重新配置显示错误信息可以

const jessibuca = new JessibucaPro({

    //其他参数

    // 重置参数信息
    showMessageConfig: {
        delayTimeout: '重置:播放超时重播失败',
        loadingTimeout: '重置:加载超时重播失败',
        loadingTimeoutRetryEnd: '重置:加载超时重播失败',
        delayTimeoutRetryEnd: '重置:播放超时重播失败',
    }
})

nakedFlowH265DemuxUseNew

  • 类型boolean
  • 默认值true
  • 用法:是否使用新的H265解封装器

如果遇到265裸流播放不出来的时候,可以尝试把这个参数设置为false,切换到老的解封装器。

const jessibuca = new JessibucaPro({
    nakedFlowH265DemuxUseNew: false
})

playFailedUseLastFrameShow

  • 类型boolean
  • 默认值true
  • 用法:当播放过程中出现异常导致的播放器暂停播放,是否显示最后一帧画面。
const jessibuca = new JessibucaPro({
    playFailedUseLastFrameShow: false
})

disableContextmenu

  • 类型boolean
  • 默认值false
  • 用法: 是否禁用右键,默认不禁用。

如果设置为 true ,contextmenuBtns将不会生效。

const jessibuca = new JessibucaPro({
    disableContextmenu: true // 禁用右键
})

extendDomConfig

  • 类型Object
  • 默认值{}
  • 参数
    • {string} html 必填 扩展DOM的html
    • {boolean} showBeforePlay 选填 是否在播放前显示 默认:false
    • {boolean} showAfterLoading 选填 是否在加载后显示 默认:true
  • 用法:配置扩展DOM的html
const jessibuca = new JessibucaPro({
    extendDomConfig: {
        html: '<div>扩展DOM</div>',
        showBeforePlay: true,
        showAfterLoading: true
    }
})

widthOrHeightChangeReplay

  • 类型boolean
  • 默认值true
  • 用法:是否在播放器宽高变化的时候,重播
const jessibuca = new JessibucaPro({
    widthOrHeightChangeReplay: true
})

widthOrHeightChangeReplayDelayTime

  • 类型number
  • 默认值0 单位秒

支持在播放器宽高变化的时候,延迟重播时间。

主要是为了解决在推流端切换分辨率的时候,还会继续推流一些脏数据到服务器端,播放器端接受到了之后,会出现花屏的情况。

const jessibuca = new JessibucaPro({
    widthOrHeightChangeReplay: true,
    widthOrHeightChangeReplayDelayTime: 2 // 单位秒
})

websocket1006ErrorReplay

  • 类型boolean
  • 默认值false

当播放器发生 websocket1006 错误的时候,支持播放器内部发起重连。

const jessibuca = new JessibucaPro({
    websocket1006ErrorReplay: true
})

websocket1006ErrorReplayDelayTime

  • 类型number
  • 默认值0 单位秒

当触发 websocket1006ErrorReplay 的时候,支持延迟 websocket1006ErrorReplayDelayTime 秒触发重播机制。

const jessibuca = new JessibucaPro({
    websocket1006ErrorReplay: true,
    websocket1006ErrorReplayDelayTime: 2 // 单位秒
})

streamErrorReplay

  • 类型boolean
  • 默认值false
  • 用法:当http请求失败(404,500等状态码),或者ws请求失败(websocket error), 支持播放器内部发起重连。
const jessibuca = new JessibucaPro({
    streamErrorReplay: true
})

streamErrorReplayDelayTime

  • 类型number
  • 默认值1 单位秒
  • 用法:当触发 streamErrorReplay 的时候,支持延迟 streamErrorReplayDelayTime 秒触发重播机制。
const jessibuca = new JessibucaPro({
    streamErrorReplay: true,
    streamErrorReplayDelayTime: 2 // 单位秒
})

streamEndReplay

  • 类型boolean
  • 默认值false
  • 用法:当http请求结束(fetch end)事件,或者ws请求结束(ws close)事件, 支持播放器内部发起重连。
const jessibuca = new JessibucaPro({
    streamEndReplay: true
})

streamEndReplayDelayTime

  • 类型number
  • 默认值1 单位秒
  • 用法:当触发 streamEndReplay 的时候,支持延迟 streamEndReplayDelayTime 秒触发重播机制。
const jessibuca = new JessibucaPro({
    streamEndReplay: true,
    streamEndReplayDelayTime: 2 // 单位秒
})

mseDecoderUseWorker

  • 类型boolean
  • 默认值false

配置是否在worker线程里面解码MSE。

可以减少主线程压力。 chrome 108+,edge 108+ ,Android 121+ 支持。

const jessibuca = new JessibucaPro({
    mseDecoderUseWorker: true
})

mainThreadFetchUseWorker

  • 类型boolean
  • 默认值true

主线程请求fetch支持另起一个worker 线程发起http请求。

const jessibuca = new JessibucaPro({
    mainThreadFetchUseWorker: true
})

这样就做到不占用主线程http并发资源。

flvDemuxBufferSizeTooLargeReplay

  • 类型boolean
  • 默认值false

当触发 flvDemuxBufferSizeTooLarge 的时候,支持播放器内部发起重连。

const jessibuca = new JessibucaPro({
    flvDemuxBufferSizeTooLargeReplay: true
})

flvDemuxBufferSizeMaxLarge

  • 类型number
  • 默认值1024 * 1024 1M

flv解封装器的缓冲区大小,如果超过这个大小,会触发flvDemuxBufferSizeTooLarge事件。

const jessibuca = new JessibucaPro({
    flvDemuxBufferSizeTooLargeReplay: true,
    flvDemuxBufferSizeMaxLarge: 1024 * 1024 // 1M
})

flvDemuxBufferSizeTooLargeEmitFailed

  • 类型boolean
  • 默认值true

当触发 flvDemuxBufferSizeTooLargetrue 的时候,支持播放器直接暂停播放,并抛出playFailedAndPaused事件。

如果同时配置了flvDemuxBufferSizeTooLargeReplaytrue,则会优先触发flvDemuxBufferSizeTooLargeReplay

const jessibuca = new JessibucaPro({
    flvDemuxBufferSizeTooLargeReplay: true,
    flvDemuxBufferSizeTooLargeEmitFailed: true
})

isCheckInView

  • 类型boolean
  • 默认值false
  • 用法:是否检测播放器是否在可视区域内

如果开启了这个参数为true,则会触发 inView 事件

const jessibuca = new JessibucaPro({
    isCheckInView: true
})

hiddenControl

  • 类型boolean
  • 默认值false
  • 用法:是否隐藏底部控制栏

如果开启了这个参数为true,则会隐藏底部控制栏,

  1. 把配置的operateBtns下面的按钮都设置false
  2. showBandwidth设置false
  3. extendOperateBtns设置为 []
  4. controlHtml设置为""

如果本身就没有配置底部可显示的东西,那底部控制栏也会自动隐藏掉的。这个参数只是快捷键帮助去配置以上的参数设置为空的。

const jessibuca = new JessibucaPro({
    hiddenControl: true
})

networkDisconnectReplay

  • 类型boolean
  • 默认值false
  • 用法:网络断开重播

播放过程中,网络断开,导致播放失败,等待网络恢复后,自动重播。

const jessibuca = new JessibucaPro({
    networkDisconnectReplay: true
})

initDecoderWorkerTimeout

  • 类型number
  • 默认值10 单位秒
  • 用法:初始化解码器worker超时时间

如果初始化解码器worker超时,会触发playFailedAndPaused事件,错误类型是 initDecoderWorkerTimeout

const jessibuca = new JessibucaPro({
    initDecoderWorkerTimeout: 10 // 单位秒
})

zoomMaxScale

  • 类型number
  • 默认值5
  • 用法:缩放的最大倍数,支持1-100倍
const jessibuca = new JessibucaPro({
    zoomMaxScale: 10 // 最大放大10倍
})

mseDecodeAudio

  • 类型boolean
  • 默认值false
  • 用法:是否使用MSE解码音频

使用mse解码音频,支持 aac/mp3 格式,如果是其他格式,会自动降级到wasm解码。

const jessibuca = new JessibucaPro({
    mseDecodeAudio: true
})

wcsDecodeAudio

  • 类型boolean
  • 默认值false
  • 用法:是否使用WCS解码音频

使用wcs解码音频,支持 aac/mp3/g711a/g711u 格式。

const jessibuca = new JessibucaPro({
    wcsDecodeAudio: true
})

initShowPlayBtn

  • 类型boolean
  • 默认值false
  • 用法:初始化是否显示播放按钮

当配置为true的时候,初始化的时候,会显示播放按钮。当点击播放按钮的时候,会触发clickInitPlayer事件。

const jessibuca = new JessibucaPro({
    initShowPlayBtn: true
})

i18n

  • 类型object
  • 默认值{}
  • 用法:配置国际化参数

目前支持的国际化配置参数有:

还需要额外配置 showMessageConfig 参数。

{
    // icon 模块
    play: '播放',
    pause: '暂停',
    screenshot: '截图',
    fullscreen: '全屏',
    fullscreenExit: '退出全屏',
    record: '录制',
    recordStop: '停止录制',
    narrow: '缩小',
    expand: '放大',
    ptz: '操作盘',
    ptzActive: '操作盘激活',
    zoom: '电子放大',
    zoomStop: '关闭电子放大',
    close: '关闭',
    performance: '性能面板',
    performanceActive: '性能面板激活',
    // ai 模块
    face: '人脸识别',
    faceActive: '人脸识别激活',
    object: '物品识别',
    objectActive: '物品识别激活',
    occlusion: '遮挡物检查',
    occlusionActive: '遮挡物检查激活',
    // ptz 模块
    expandPlus: '缩放+',
    expandMinus: '缩放-',
    apertureFar:'光圈+',
    apertureNear:'光圈-',
    focusFar:'聚焦+',
    focusNear:'聚焦-',
    cruisePlay:'巡航开',
    cruisePause:'巡航关',
    fogOpen:'透雾开',
    fogClose:'透雾关',
    wiperOpen:'雨刷开',
    wiperClose:'雨刷关',
    // 其他文案
    zoomTips:'电子放大'
}

// demo
const jessibucaPro = new JessibucaPro({
    i18n: {
        play: 'Play',
        pause: 'Pause',

    }
})

androidMobileFullscreenRotate

  • 类型boolean
  • 默认值false
  • 用法:安卓手机全屏是否旋转90度

如果开启了,安卓手机全屏的时候,会旋转90度。


const jessibucaPro = new JessibucaPro({
    androidMobileFullscreenRotate: true
})

videoSEISyncPtsDiff

  • 类型number
  • 默认值0.2 单位秒
  • 用法:视频SEI数据和视频时间戳的差值
const jessibucaPro = new JessibucaPro({
    videoSEISyncPtsDiff: 0.2
})

配置抛出sei数据的精度差,比如设置了0.2s,那么播放器内部会把sei数据的时间戳和视频时间戳做一个差值,如果差值在正负0.2s以内,会抛出sei数据。

适合那些ai业务会延迟抛出的sei数据。这个时候就需要通过配置这个参数来调整sei数据的抛出精度,来调整视频和sei数据的时间戳的差值。

zoomSupportWheelInPc

  • 类型boolean
  • 默认值false
  • 用法:在pc端,是否支持鼠标滚轮缩放
const jessibucaPro = new JessibucaPro({
    zoomSupportWheelInPc: true
})

correctionConfigurationProfileIndication

  • 类型boolean
  • 默认值false
  • 用法:是否纠正流数据的configuration profile字段

针对于某些有问题的流,可以通过播放器内部的纠正来解决。

correctionConfigurationVersion

  • 类型boolean
  • 默认值false
  • 用法:是否纠正流数据的configuration version字段

针对于某些有问题的流,可以通过播放器内部的纠正来解决。

checkWebrtcLowFps

  • 类型boolean
  • 默认值false
  • 用法:是否检测WebRTC流的低帧率

checkWebrtcLowFpsDuration

  • 类型number
  • 默认值5 单位秒
  • 用法:检测WebRTC流的低帧率的持续时间

webrtcLowFps

  • 类型number
  • 默认值3
  • 用法:WebRTC流的低帧率阈值

checkWebrtcLowFpsCalcType

  • 类型'average' | 'all'
  • 默认值'all'
  • 用法:检测WebRTC流的低帧率计算方式

all表示检测帧率在checkWebrtcLowFpsDuration期间内,都得小于等于webrtcLowFps

average表示检测帧率在checkWebrtcLowFpsDuration期间内,统计出来的平均值小于等于webrtcLowFps

静态变量

ERROR

播放器对外的错误

jessibucaPro.on(JessibucaPro.EVENTS.error, (error) => {
    if (error === JessibucaPro.ERROR.playError) {
        // 播放错误
    }
})

ERROR详细的参数见 d.ts

export const EVENTS_ERROR = {
    playError: 'playIsNotPauseOrUrlIsNull',
    fetchError: "fetchError",
    fetchErrorWorker: "fetchErrorWorker",

    //  websocket
    websocketError: 'websocketError',
    websocketOpenTimeout: 'websocketOpenTimeout',
    //  webcodec
    webcodecsH265NotSupport: 'webcodecsH265NotSupport',
    webcodecsDecodeError: 'webcodecsDecodeError',
    webcodecsUnsupportedConfigurationError: 'webcodecsUnsupportedConfigurationError',
    webcodecsDecodeConfigureError: 'webcodecsDecodeConfigureError',
    webcodecsAudioInitTimeout: 'webcodecsAudioInitTimeout',
    webcodecsAudioNoDataTimeout: 'webcodecsAudioNoDataTimeout',
    // mse
    mediaSourceH265NotSupport: 'mediaSourceH265NotSupport',
    mediaSourceAudioG711NotSupport: 'mediaSourceAudioG711NotSupport',
    mediaSourceAudioInitTimeout: 'mediaSourceAudioInitTimeout',
    mediaSourceAudioNoDataTimeout: 'mediaSourceAudioNoDataTimeout',
    mediaSourceDecoderConfigurationError: 'mediaSourceDecoderConfigurationError',
    mediaSourceFull: EVENTS.mseSourceBufferFull,
    mseSourceBufferError: EVENTS.mseSourceBufferError,
    mseAddSourceBufferError: EVENTS.mseAddSourceBufferError,
    mseWorkerAddSourceBufferError: EVENTS.mseWorkerAddSourceBufferError,
    mediaSourceAppendBufferError: 'mediaSourceAppendBufferError',
    mediaSourceTsIsMaxDiff: 'mediaSourceTsIsMaxDiff',
    mediaSourceUseCanvasRenderPlayFailed: 'mediaSourceUseCanvasRenderPlayFailed',
    mediaSourceBufferedIsZeroError: 'mediaSourceBufferedIsZeroError',
    // wasm
    wasmDecodeError: 'wasmDecodeError',
    wasmUseVideoRenderError: 'wasmUseVideoRenderError',
    simdH264DecodeVideoWidthIsTooLarge: 'simdH264DecodeVideoWidthIsTooLarge',
    simdDecodeError: 'simdDecodeError',
    simdDecodeDelayTimeout: 'simdDecodeDelayTimeout',

    hlsError: 'hlsError',
    // webrtc
    webrtcError: 'webrtcError',
    webrtcClosed: EVENTS.webrtcClosed,
    webrtcIceCandidateError: 'webrtcIceCandidateError',
    //
    webglAlignmentError: 'webglAlignmentError',
    wasmWidthOrHeightChange: 'wasmWidthOrHeightChange',
    mseWidthOrHeightChange: 'mseWidthOrHeightChange',
    wcsWidthOrHeightChange: 'wcsWidthOrHeightChange',
    widthOrHeightChange: 'widthOrHeightChange',

    tallWebsocketClosedByError: 'tallWebsocketClosedByError',
    flvDemuxBufferSizeTooLarge: EVENTS.flvDemuxBufferSizeTooLarge,
    audioChannelError: 'audioChannelError',
    webglContextLostError: 'webglContextLostError',

    videoElementPlayingFailed: 'videoElementPlayingFailed',
    videoElementPlayingFailedForWebrtc: 'videoElementPlayingFailedForWebrtc',

    decoderWorkerInitError: 'decoderWorkerInitError',
    decoderWorkerWasmError: 'decoderWorkerWasmError',
    videoInfoError: 'videoInfoError',
    streamEnd: EVENTS.streamEnd,
    websocket1006Error: 'websocket1006Error',
    delayTimeout: EVENTS.delayTimeout,
    loadingTimeout: EVENTS.loadingTimeout,
    networkDelayTimeout: EVENTS.networkDelayTimeout,
    fullscreenError: 'fullscreenError',
    aliyunRtcError: 'aliyunRtcError',
    mseWaitVideoCanplayTimeout: 'mseWaitVideoCanplayTimeout',
    initDecoderWorkerTimeout: 'initDecoderWorkerTimeout',

    // wasm
    notSupportNewWasm: 'notSupportNewWasm',

    failedToAsynchronouslyPrepareWasm: 'failedToAsynchronouslyPrepareWasm',

    //
    playVodMp4Error: 'playVodMp4Error',

    playVodFlvError: 'playVodFlvError',
    mp4Error: 'mp4Error',
}

EVENTS

播放器对外的事件

事件里面的key

jessibucaPro.on(JessibucaPro.EVENTS.blur, () => {
    // 窗口不可见
})

EVENTS详细的参数见 d.ts

// jessibuca events
export const JESSIBUCA_EVENTS = {
    load: EVENTS.load,
    timeUpdate: EVENTS.timeUpdate,
    videoInfo: EVENTS.videoInfo,
    audioInfo: EVENTS.audioInfo,
    error: EVENTS.error,
    kBps: EVENTS.kBps,
    start: EVENTS.start,
    timeout: EVENTS.timeout,
    loadingTimeout: EVENTS.loadingTimeout,
    loadingTimeoutRetryEnd: EVENTS.loadingTimeoutRetryEnd,
    delayTimeout: EVENTS.delayTimeout,
    delayTimeoutRetryEnd: EVENTS.delayTimeoutRetryEnd,
    fullscreen: 'fullscreen',
    webFullscreen: EVENTS.webFullscreen,
    play: EVENTS.play,
    pause: EVENTS.pause,
    mute: EVENTS.mute,
    stats: EVENTS.stats,
    performance: EVENTS.performance,
    //  record
    recordingTimestamp: EVENTS.recordingTimestamp,
    recordStart: EVENTS.recordStart,
    recordCreateError: EVENTS.recordCreateError,
    recordEnd: EVENTS.recordEnd,
    recordBlob: EVENTS.recordBlob,
    recordCancel: EVENTS.recordCancel,

    playToRenderTimes: EVENTS.playToRenderTimes,

    // playback
    playbackSeek: EVENTS.playbackSeek,
    playbackStats: EVENTS.playbackStats,
    playbackTimestamp: EVENTS.playbackTimestamp,
    playbackPauseOrResume: EVENTS.playbackPauseOrResume,
    playbackPreRateChange: EVENTS.playbackPreRateChange,
    playbackRateChange: EVENTS.playbackRateChange,
    playbackShowPrecisionChange: EVENTS.playbackShowPrecisionChange,
    playbackEnd: EVENTS.playbackEnd,

    // playVod
    playVodEnded: EVENTS.playVodEnded,
    playVodPauseOrResume: EVENTS.playVodPauseOrResume,
    playVodRateChange: EVENTS.playVodRateChange,
    playVodTime: EVENTS.playVodTime,
    playVodBufferedTime: EVENTS.playVodBufferedTime,
    playVodSeek: EVENTS.playVodSeek,
    playVodSeekEnd: EVENTS.playVodSeekEnd,

    ptz: EVENTS.ptz,
    streamQualityChange: EVENTS.streamQualityChange,
    zooming: EVENTS.zooming,
    crashLog: EVENTS.crashLog,

    focus: EVENTS.focus,
    blur: EVENTS.blur,
    visibilityHiddenTimeout: EVENTS.visibilityHiddenTimeout,
    visibilityChange: EVENTS.visibilityChange,

    // websocket
    websocketOpen: EVENTS.websocketOpen,
    websocketClose: EVENTS.websocketClose,
    websocketStringMsg: EVENTS.websocketStringMsg,
    //
    networkDelayTimeout: EVENTS.networkDelayTimeout,
    //
    aiObjectDetectorInfo: EVENTS.aiObjectDetectorInfo,
    aiFaceDetectorInfo: EVENTS.aiFaceDetectorInfo,
    aiOcclusionDetectResult: EVENTS.aiOcclusionDetectResult,
    aiImageDetectResult: EVENTS.aiImageDetectResult,

    playFailedAndPaused: EVENTS.playFailedAndPaused,

    streamEnd: EVENTS.streamEnd,

    // audio
    audioResumeState: EVENTS.audioResumeState,

    // video
    videoSEI: EVENTS.videoSEI,
    videoSEISyncPts: EVENTS.videoSEISyncPts,

    //  flv
    flvMetaData: EVENTS.flvMetaData,

    // webrtc
    webrtcOnConnectionStateChange: EVENTS.webrtcOnConnectionStateChange,
    webrtcOnIceConnectionStateChange: EVENTS.webrtcOnIceConnectionStateChange,

    currentPts: EVENTS.currentPts,

    videoSmooth: EVENTS.videoSmooth,

    networkState: EVENTS.networkState,

    volume: EVENTS.volume,

    drawingRectInfo: EVENTS.drawingRectInfo,
    //
    clickInitPlayer: EVENTS.clickInitPlayer,
}

方法

setDebug(flag)(废弃)

  • 参数
    • {boolean} flag
  • 返回值void
  • 用法: 是否开启控制台调试打印
// 开启
jessibucaPro.setDebug(true)
// 关闭
jessibucaPro.setDebug(false)

播放器会在初始化的时候,会根据debug:true 初始化一些监听事件,如果初始化的时候没有配置debug:true, 在播放器初始化之后,再调用setDebug(true) 打开日志的话,会导致有些日志没有打印出来的。

如果初始化的时候,监听全部事件的话,会有性能浪费的情况,所以不推荐使用。

推荐做法:

根据业务需求,需要看日志的时候,重新播放(初始化的时候把 debug:true, debugLevel:'debug' 配置起来)。

可以是url 上面添加一个 debug=true 参数,播放器在初始化的时候,检测下url 是否有这个参数,如果有就带上参数。 或者也可以有其他更好的方式。

getOption()

  • 用法: 获取配置参数信息
  • 返回值{object}
jessibucaPro.getOption()

mute()

  • 用法: 静音
  • 返回值void
jessibucaPro.mute()

cancelMute()

  • 用法: 取消静音
  • 返回值void

取消静音,会恢复之前的音量大小,默认 0.5。

jessibucaPro.cancelMute()

audioResume()(废弃)

  • 用法: 留给上层用户操作来触发音频恢复的方法。
  • 返回值void

废弃,推荐使用mute(false)方法

iPhone,chrome等要求自动播放时,音频必须静音,需要由一个真实的用户交互操作来恢复,不能使用代码。

https://developers.google.com/web/updates/2017/09/autoplay-policy-changes

jestibucaPro.audioResume()

setTimeout(time)

  • 参数
    • {number} time
  • 返回值void
  • 用法

设置超时时长, 单位秒 在连接成功之前和播放中途,如果超过设定时长无数据返回,则回调timeout事件

会同步设置loadingTimeoutheartTimeout的值

支持播放过程中设置,heartTimeout会被重置。

jessibucaPro.setTimeout(10)

jessibucaPro.on('timeout', function () {
    //
});

setScaleMode(mode)

  • 参数
    • {number} mode
  • 返回值void
  • 用法
  1. 0 视频画面完全填充canvas区域,画面会被拉伸 等同于参数 isResize 为false
  2. 1 视频画面做等比缩放后,高或宽对齐canvas区域,画面不被拉伸,但有黑边 等同于参数 isResize 为true
  3. 2 视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全 等同于参数 isFullResize 为true
jessibucaPro.setScaleMode(0)

jessibucaPro.setScaleMode(1)

jessibucaPro.setScaleMode(2)

在IOS端上,如果是通过video标签渲染的时候,因为css在控制video样式的时候,尤其是拉伸的时候,会有部分画面被遮挡看不到,所以在这种环境下会禁用这个设置。

pause(isClear)

  • 参数
    • {boolean} isClear 是否清除画面,默认 false
  • 返回
    • {Promise}
  • 用法: 暂停播放

会断开流请求

jessibucaPro.pause().then(() => {
    console.log('pause success')

    jessibucaPro.play().then(() => {

    }).catch((e) => {

    })

}).catch((e) => {
    console.log('pause error', e);
})

jessibucaPro.pause(true).then(() => {
    console.log('pause success')

    jessibucaPro.play().then(() => {

    }).catch((e) => {

    })

}).catch((e) => {
    console.log('pause error', e);
})

可以在pause 之后,再调用 play()方法就会发起流请求,继续播放之前的流。

close()(废弃)

  • 用法: 关闭视频,不释放底层资源
  • 返回
    • {Promise}

废弃,推荐使用destroy()方法

内部就是调用的destroy()方法

jessibucaPro.close().then(() => {
    console.log('close success')
}).catch((e) => {
    console.log('close error', e);
})

destroy()

  • 用法: 关闭视频,释放底层资源
  • 返回Promise
//
jessibucaPro.destroy().then(() => {
    console.log('destroy success')
}).catch((e) => {
    console.log('destroy error', e);
})


// 或者
const result = await jessibucaPro.destroy();

clearView()

  • 用法: 清理画布为黑色背景
  • 返回void
jessibucaPro.clearView()

play([url],[options])

  • 参数

    • {string} url 播放url,支持 http(s):,ws(s):, webrtc://, wt://,artc://
    • {object} options 扩展参数
      • {object} headers fetch 请求头数据
      • {Array} protocols ws请求的 一个协议字符串或者一个包含协议字符串的数组
      • {string} websocketFirstMessage ws请求的首个消息(open事件之后发送),播放器内部触发重播逻辑的时候也会发送此参数。
      • {boolean} useLastFrameShow 加载过程中是否使用前一个播放的最后一帧画面显示。(非初次播放)
      • {boolean} replay 强制重新播放(非初次播放)
      • {boolean} loadingIcon 是否显示loading图标(非初次播放)
  • 返回

    • {Promise}
  • 用法: 播放视频

options.headers 主要是为了支持在播放的时候,可以自定义请求头,比如在播放的时候,需要带上cookie等信息,用于身份认证。

catch方法里面的错误处理,主要是为了处理加载失败的情况(直接影响初始化),播放异常的情况需要通过监听playFailedAndPaused事件来处理。

当播放失败的时候,也会触发playFailedAndPaused事件。所以如果要处理重播逻辑,只需要统一在playFailedAndPaused事件里面处理就可以了,不需要在catch里面处理。


jessibucaPro.play('url').then(() => {
    // 这里只是初始化成功,并不代表流已经开始播放成功。因为请求地址是个异步响应,同时也有重播的逻辑,所以这里统一是表示加载成功。
    // 如果需要检查播放失败,可以查看`playVodFailedAndPaused`事件。
    // 如果想要监听播放成功,可以监听`start`事件。
    console.log('initialized and ready to play');
}).catch((e) => {
    console.log('play error', e)
})
//
jessibucaPro.play()

http 授权认证

jessibucaPro.play('url',{
    headers:{
        Authorization:'test' // 身份认证
    }
}).then(() => {
    console.log('play success')
}).catch((e) => {
    console.log('play error', e)
})

ws请求的首个消息

jessibucaPro.play('url',{
    websocketFirstMessage: JSON.stringify({
        type: 'login',
        data: {
            username: 'test',
        }
    })
}).then(() => {
    console.log('play success')
}).catch((e) => {
    console.log('play error', e)
})

使用前一个播放的最后一帧画面显示

jessibucaPro.play('url',{
    useLastFrameShow: true
}).then(() => {
    console.log('play success')
}).catch((e) => {
    console.log('play error', e)
})

resize()

  • 用法: 重新调整视图大小
  • 返回void
jessibucaPro.resize()

setBufferTime(time)

  • 参数

    • {number} time
  • 返回void

  • 用法: 设置最大缓冲时长,单位秒,播放器会自动消除延迟,如果设置为0 则不进行任何缓冲,直接进行解码渲染。 等同于 videoBuffer 参数。

// 设置 200ms 缓冲
jessibucaPro.setBufferTime(0.2)

setBufferDelayTime(time)

  • 参数

    • {number} time
  • 返回void

  • 用法: 设置最大延迟时间,单位秒,播放器当延迟超过这个时间之后就会丢帧,消除延迟。

等同于 videoBufferDelay 参数。

// 设置 1000ms 最大延迟时间
jessibucaPro.setBufferTimeDelay(1)

setRotate(deg)

  • 参数
    • {number} deg
  • 返回void
  • 用法: 设置旋转角度,支持,0(默认) ,90,180,270 三个值。

可用于实现监控画面小窗和全屏效果,由于iOS没有全屏API,此方法可以模拟页面内全屏效果而且多端效果一致。

注意,当旋转90度后,用户也会旋转手机,这时如果手机未锁定方向,画面又可能因为浏览器旋转导致画面又旋转了。可以监听页面旋转事件,将角度又旋转回0

jessibucaPro.setRotate(0)

jessibucaPro.setRotate(90)

jessibucaPro.setRotate(180)

jessibucaPro.setRotate(270)

setVolume(volume)

  • 参数

    • {number} volume
  • 用法

  1. 设置音量大小,取值0 — 1
  2. 当为0时,完全无声
  3. 当为1时,最大音量,默认值

区别于 mute 和 cancelMute 方法,虽然设置setVolume(0) 也能达到 mute方法,但是mute 方法是不调用底层播放音频的,能提高性能。而setVolume(0)只是把声音设置为0 ,以达到效果。

jessibucaPro.setVolume(0.2)

jessibucaPro.setVolume(0)

jessibucaPro.setVolume(1)

getVolume()

  • 返回值number
  • 用法:返回音量大小,取值0 — 1,两位小数
const volume = jessibucaPro.getVolume();

hasLoaded()(废弃)

  • 返回值boolean
  • 用法: 返回是否加载完毕
var result = jessibucaPro.hasLoaded()
console.log(result) // true

永久返回 true

pro播放器不需要用户去判断hasLoaded()是否加载完毕 然后再执行 play() 方法了,播放器内部会自行判断。

setKeepScreenOn()

  • 用法: 开启屏幕常亮,在手机浏览器上, canvas标签渲染视频并不会像video标签那样保持屏幕常亮。 H5目前在chrome\edge 84, android chrome 84及以上有原生亮屏API, 需要是https页面 其余平台为模拟实现,此时为兼容实现,并不保证所有浏览器都支持
  • 返回值void
jessibucaPro.setKeepScreenOn()

setFullscreen(flag)

  • 参数

    • {boolean} flag
  • 用法: 全屏(取消全屏)播放视频

iOS不支持,iPadOS13后支持

推荐iOS端配置上 useWebFullScreen 这个参数(最新版本如果是IOS环境,默认会变成true)。

由于浏览器安全机制,触发窗口全屏前,页面必须先存在交互(例如用户点击过页面)


jessibucaPro.setFullscreen(true)
//
jessibucaPro.setFullscreen(false)

screenshot([filename]|[options], [format], [quality],[type])

  • 参数
    • {string|object} filename | options
    • {string} format
    • {number} quality
    • {string} type
  • 用法

截图,调用后弹出下载框保存截图

当传入的是options对象时,参数如下:

  • {string} filename
  • {string} format
  • {number} quality
  • {string} type

参数解析

  1. filename: 可选参数, 保存的文件名, 默认 时间戳
  2. format : 可选参数, 截图的格式,可选pngjpeg或者webp ,默认 png
  3. quality: 可选参数, 当格式是jpeg或者webp时,压缩质量,取值0 ~ 1 ,默认 0.92
  4. type: 可选参数, 可选download或者base64或者blob,默认download

手机浏览器不一定能保存下来。 建议手机端通过base64形式。让用户自主保存。


jessibucaPro.screenshot("test", "png", 0.5)

// 返回base64
const base64 = jessibucaPro.screenshot("test", "png", 0.5, 'base64')

// 返回blob
const fileBlob = jessibucaPro.screenshot("test", 'blob')

// 对象
jessibucaPro.screenshot({
    filename: 'test',
    format: 'png',
    quality: 0.5,
})
// 返回base64
const base64 = jessibucaPro.screenshot({
    filename: 'test',
    format: 'png',
    quality: 0.5,
    type: 'base64'
})

// 返回blob
const fileBlob = jessibucaPro.screenshot({
    filename: 'test',
    type: 'blob'
})

screenshotWatermark(options)

  • 返回值Promise
  • options 参数
    • {string} filename
    • {string} format
    • {number} quality
    • {string} type
  • 用法

截图(支持水印参数) ,调用后弹出下载框保存截图

  1. filename: 可选参数, 保存的文件名, 默认 时间戳
  2. format : 可选参数, 截图的格式,可选pngjpeg或者webp ,默认 png
  3. quality: 可选参数, 当格式是jpeg或者webp时,压缩质量,取值0 ~ 1 ,默认 0.92
  4. type: 可选参数, 可选download或者base64或者blob,默认download

仅支持 text以及图片配置,仅支持单个水印配置,不支持数组。

手机浏览器不一定能保存下来。 建议手机端通过base64形式。让用户自主保存。


jessibucaPro.screenshotWatermark({
    filename: 'test',
    text: {
        content: 'jessibuca-pro',
        fontSize: '40',
        color: 'red'
    },
    right: 20,
    top: 40
})


jessibucaPro.screenshotWatermark({
    filename: 'test',
    text: {
        content: 'jessibuca-pro',
        fontSize: '40',
        color: 'red'
    },
    right: 20,
    top: 40,
    type: 'base64'
}).then((base64) => {

})


jessibucaPro.screenshotWatermark({
    image: {
        src: 'data:image/png;base64,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',
        width: 60,
        height: 60
    },
    right: 20,
    top: 20,
    type: `blob`,
}).then((fileBlob) => {

})

screenshotCopyrightWatermark(options)

  • 返回值Promise
  • options 参数
    • {string} filename
    • {string} format
    • {number} quality
    • {string} type
    • {string} copyright 暗水印内容
  • 用法

截图(支持暗水印参数),调用后弹出下载框保存截图

  1. filename: 可选参数, 保存的文件名, 默认 时间戳
  2. format : 可选参数, 截图的格式,可选pngjpeg或者webp ,默认 png
  3. quality: 可选参数, 当格式是jpeg或者webp时,压缩质量,取值0 ~ 1 ,默认 0.92
  4. type: 可选参数, 可选download或者base64或者blob,默认download
  5. copyright:可选,暗水内容
jessibucaPro.screenshotCopyrightWatermark({
    filename: 'xxx',
    format: 'png',
    quality: 0.92,
    type: 'download',
    copyright: 'xxx',
}).then((fileBlob) => {
    // fileBlob
})


// 或者
const fileBlob = await jessibucaPro.screenshotCopyrightWatermark({
    filename: 'xxx',
    format: 'png',
    quality: 0.92,
    type: 'download',
    copyright: 'xxx',
})

startRecord(fileName,fileType)

  • 参数
    • {string} filename
    • {string} fileType(废弃)
  • 返回值{Promise}
  • 用法: 开始录制。
  1. fileName: 可选,默认时间戳 2. fileType: 可选,支持webm 和mp4 格式 默认webm
jessibucaPro.startRecord('xxx').then(()=>{
    console.log('开始录制')
})

// 或者
await jessibucaPro.startRecord('xxx')

文件类型根据 recordType 参数走。需要在初始化播放器的时候指定。

safari 浏览器(Pc + Mobile)不支持webm格式的录制功能。

stopRecordAndSave(type,fileName)

  • 用法: 暂停录制并下载。
  • 参数
    • {string} type
    • {string} fileName
  • 返回值{Promise}
  1. type: 可选,默认download,支持downloadblob
  2. fileName: 可选,默认时间戳

手机浏览器不一定能保存下来。 建议手机端通过blob形式。让用户自主保存。

jessibucaPro.stopRecordAndSave()
jessibucaPro.stopRecordAndSave('', 'fileName')
jessibucaPro.stopRecordAndSave('blob')
jessibucaPro.once('recordBlob', (fileBlob) => {
    console.log(fileBlob)
})
jessibucaPro.stopRecordAndSave('blob').then((fileBlob) => {
    console.log(fileBlob)
})

// 或者
const fileBlob = await jessibucaPro.stopRecordAndSave('blob')

cancelRecord()

  • 用法: 暂停录制并下载。
  • 返回值{Promise}
jessibucaPro.cancelRecord().then(()=>{
    console.log('取消录制')
})

// 或者
await jessibucaPro.cancelRecord()

isPlaying()

  • 返回值boolean
  • 用法: 返回是否正在播放中状态。
var result = jessibucaPro.isPlaying()
console.log(result) // true

isLoading()

  • 返回值boolean
  • 用法: 返回是否正在加载中状态。
var result = jessibucaPro.isLoading()
console.log(result) // true

isPause()

  • 返回值boolean
  • 用法: 返回是否正在暂停中状态。
var result = jessibucaPro.isPause()
console.log(result) // true

isMute()

  • 返回值boolean
  • 用法: 返回是否静音。
var result = jessibucaPro.isMute()
console.log(result) // true

isRecording()

  • 返回值boolean
  • 用法: 返回是否正在录制。
var result = jessibucaPro.isRecording()
console.log(result) // true

clearBufferDelay()

  • 返回值void
  • 用法: 手动消除缓冲区数据。
jessibucaPro.clearBufferDelay()

setNetworkDelayTime(timestamp)

  • 参数
    • {number} timestamp 单位秒s
  • 返回
    • {void}

设置网络延迟时间,用于播放器计算播放时间,单位秒s


// 设置网络延迟时间为10秒
jessibucaPro.setNetworkDelayTime(10)

setStreamQuality(quality)

  • 参数

    • {string} quality
  • 返回

    • {void}
  • 用法: 设置分辨率 quality 必须是qualityConfig里面的数据

例如:qualityConfig 配置的是 ["高清","超清"]

jessibucaPro.setStreamQuality('高清')

// 或者
jessibucaPro.setStreamQuality('超清')

setMirrorRotate(mirrorRotate)

  • 参数

    • {string} mirrorRotate
  • 返回

    • {void}
  • 用法: 设置镜像翻转 mirrorRotate ,可选参数有 默认none,水平 level,垂直 vertical

jessibucaPro.setMirrorRotate('level')

// 或者
jessibucaPro.setMirrorRotate('vertical')

// 或者
jessibucaPro.setMirrorRotate('none')

togglePerformancePanel(flag)

  • 参数

    • {boolean} flag 隐藏/显示 性能面板,如果不写参数,则当做toggle切换
  • 返回

    • {void}
  • 用法: 隐藏/显示 性能面板


// 隐藏/展示 性能面板
jessibucaPro.togglePerformancePanel()

// 显示性能面板
jessibucaPro.togglePerformancePanel(true)

// 隐藏性能面板
jessibucaPro.togglePerformancePanel(false)

openZoom()

  • 返回

    • {void}
  • 用法: 打开电子放大

jessibucaPro.openZoom()

closeZoom()

  • 返回

    • {void}
  • 用法: 关闭电子放大


jessibucaPro.closeZoom()

toggleZoom(flag)

  • 参数
    • {boolean} flag 是否开启电子放大,如果不写参数,则当做toggle切换
  • 返回
    • {void}

jessibucaPro.toggleZoom(true)

// 或者
jessibucaPro.toggleZoom(false)

// 或者
jessibucaPro.toggleZoom()

isZoomOpen()

  • 返回

    • {boolean}
  • 用法: 当前是否处于电子放大模式下

const isZoomOpen = jessibucaPro.isZoomOpen()

expandZoom()

  • 返回

    • {void}
  • 用法: 电子放大-放大

需要开启电子放大才能生效

jessibucaPro.expandZoom()

narrowZoom()

  • 返回

    • {void}
  • 用法: 电子放大-缩小

需要开启电子放大才能生效

jessibucaPro.narrowZoom()

updateCurrentZoom(index)

  • 参数
    • {number} index 电子放大档位 1 ~ zoomMaxScale
  • 返回
    • {void}
  • 用法: 电子放大-切换档位

zoomMaxScale 为配置项中的 见zoomMaxScale 参数

需要开启电子放大才能生效

jessibucaPro.updateCurrentZoom(3)

getCurrentZoomIndex()

  • 返回

    • {number} currentZoom 当前放大的档位
  • 用法: 获取当前电子放大档位 范围 1~ zoomMaxScale

zoomMaxScale 为配置项中的 zoomMaxScale 参数

const currentIndex = jessibucaPro.getCurrentZoomIndex()

getDecodeType()

  • 返回
    • {string} decodeType 当前解码类型

返回一个字符串 告知当前解码类型。如果是组合型的话,会用空格分隔。

可能得结果有:msewcsoffscreenwasmsimdwebrtchls

const decodeType = jessibucaPro.getDecodeType()

getDemuxType()

  • 返回
    • {string} demuxType 当前解复用类型

返回一个字符串 告知当前解复用类型。

可能得结果有:flvm7shlswebrtcwebTransportnakedFlow

const demuxType = jessibucaPro.getDemuxType()

getRenderType()

  • 返回
    • {string} renderType 当前渲染组件 包含 video,canvas

返回一个字符串 告知当前渲染组件。

const renderType = jessibucaPro.getRenderType()

getPlayingTimestamp()

  • 返回
    • {number} pTs 播放时间戳 单位 秒

返回一个数字,告知当前播放时间戳。

单次播放的时长,触发重播逻辑的时候,会重新计时。

播放器本地的播放时间时长,从0开始的,区别于ts(流里面的时间戳)。

等同于 stats 事件中的 pTs 字段

const pTs = jessibucaPro.getPlayingTimestamp()

getStatus()

  • 返回
    • {string} status 当前播放器状态 包含状态有 playing paused loading

返回一个字符串,告知当前播放器状态。

const status = jessibucaPro.getStatus()

getPlayType()

  • 返回
    • {string} playType 当前播放器类型 包含类型有 player playbackTF, playVod

返回一个字符串,告知当前播放器类型。


const playType = jessibucaPro.getPlayType()

getAudioEngineType()

  • 返回{string} 返回当前音频引擎类型

返回的结果有 audioworkletscriptactive

const audioEngineType = jessibucaPro.getAudioEngineType()

setNakedFlowFps(fps)

  • 用法: 设置裸流播放的fps
  • 参数{number} fps fps值 1~100
  • 返回{promise}
// 设置fps 为25
jessibucaPro.setNakedFlowFps(25)

updateDebugLevel(level)

  • 用法: 设置调试等级
  • 参数{number} level debugwarn
  • 返回{void}
// 设置调试等级为debug
jessibucaPro.updateDebugLevel('debug')

faceDetectOpen()

  • 用法: 打开人脸检测
  • 返回{void}
  • 注意: 人脸检测功能需要额外加载js和wasm文件

需要提前在html中引入js文件。

jessibucaPro.faceDetectOpen();

faceDetectClose()

  • 用法: 关闭人脸检测
  • 返回{void}
  • 注意: 人脸检测功能需要额外加载js和wasm文件
jessibucaPro.faceDetectClose();

updateFullscreenWatermark(config)

  • 用法: 更新全屏水印
  • 返回{void}
  • 注意: config 等同于 fullscreenWatermarkConfig 配置
jessibucaPro.updateFullscreenWatermark({
    text: 'jessibucaPro 体验',
})

removeFullscreenWatermark()

  • 用法: 移除全屏水印
  • 返回{void}
jessibucaPro.removeFullscreenWatermark();

sendWebsocketMessage(message)

  • 用法: 发送websocket消息
  • 参数{*} message 消息内容
  • 返回{void}

请求地址是ws(s) 才会有效。

jessibucaPro.sendWebsocketMessage('hello world');

addContentToCanvas(contentList)

  • 用法: 给canvas(video) 添加内容
  • 返回{void}
  • 参数{Array} contentList 内容列表
    • {string} type 内容类型 支持 text,line,rect,polygon
    • {string} text 文本内容(type 为 text 有效)
    • {number} fontSize 字体大小(type 为 text 有效) 默认值 14
    • {number} width 宽度(type 为 rect 有效)
    • {number} height 高度(type 为 rect 有效)
    • {number} lineWidth 边框宽度(type 为 line/rect/polygon 有效) 默认值2
    • {string} color 颜色 默认值 green (都有效)
    • {string} fill 填充颜色(type 为 rect/polygon 有效)
    • {string} fillOpacity 填充颜色透明度(type 为 rect/polygon 有效)
    • [array] list 多边形坐标(type 为 polygon 有效)
      • {number} x x坐标
      • {number} y y坐标
      • {number} index 坐标索引
    • {number} x x坐标 (type 为 text/rect 有效)
    • {number} y y坐标 (type 为 text/rect 有效)
    • {number} x1 x1坐标 (type 为 line 有效)
    • {number} y1 y1坐标 (type 为 line 有效)
    • {number} x2 x2坐标 (type 为 line 有效)
    • {number} y2 y2坐标 (type 为 line 有效)
    • {number} angle 旋转角度(以中心点旋转) (type 为 text/rect 有效,等同于css 的 transform: rotate(45deg),angle为45时候

目前仅支持 在硬解码模式下,在使用 canvas 渲染。

现在 软解码硬解码, canvas渲染video渲染 都支持。

注意:是画内容到 video/canvas 上面,不是画到container上面。所以是基于视频的坐标系,而不是container的坐标系。

demo 文字

const position1 = getPosition();
const position2 = getPosition();
jessibuca.addContentToCanvas([
    {
        type: 'text',
        text: 'hello world 你好',
        x: position1.x,
        y: position1.y,
        color: 'red',
        fontSize: 20,
        angle:45 // 旋转45度
    },
    {
        type: 'text',
        text: 'hello world2 你好2',
        x: position2.x,
        y: position2.y,
        color: 'blue',
        fontSize: 20,
        angle:90 // 旋转90度
    }
])

demo 矩形

const position1 = getPosition();
const position2 = getPosition();
jessibuca.addContentToCanvas([
    {
        type: 'rect',
        x: position1.x,
        y: position1.y,
        width: 100,
        height: 100,
        color: '#FF0000',
        fill: fill ? fill : '',
        fillOpacity: fill ? 0.1 : '',
        angle:45 // 旋转45度
    },
    {
        type: 'rect',
        x: position2.x,
        y: position2.y,
        width: 100,
        height: 100,
        color: '#0000FF',
        fill: fill ? fill : '',
        fillOpacity: fill ? 0.1 : '',
        angle:45 // 旋转45度
    }
])

demo 文字+矩形

const {x, y} = getPosition();
jessibuca.addContentToCanvas([
    {
        type: 'rect',
        x,
        y,
        width: 100,
        height: 100,
        color: '#0000FF',
        fill: fill ? fill : '',
        fillOpacity: fill ? 0.3 : '',
    },
    {
        type: 'text',
        text: 'hello world 你好',
        x,
        y: y - 25,
        width: 100,
        height: 100,
        color: '#0000FF',
    }
])

demo 多边形


const points = [
    {x: 100, y: 100, index: 0},
    {x: 200, y: 50, index: 1},
    {x: 300, y: 100, index: 2},
    {x: 250, y: 200, index: 3},
    {x: 150, y: 200, index: 4},
]

jessibuca.addContentToCanvas([
    {
        type: 'polygon',
        color: 'red',
        lineWidth: 2,
        list: points
    }
])

clearContentToCanvas()

  • 用法: 清空canvas 额外添加的内容
  • 返回{void}
jessibuca.clearContentToCanvas()

setControlHtml(html)

  • 用法: 设置控制面板的html
  • 返回{void}
jessibucaPro.setControlHtml('<div>自定义控制面板</div>')

clearControlHtml()

  • 用法: 清空控制面板的html
  • 返回{void}
jessibucaPro.clearControlHtml()

toggleControlHtml(isShow)

  • 用法: 隐藏/展示控制面板的html
  • 参数{boolean} isShow 是否显示控制面板
  • 返回{void}
jessibucaPro.toggleControlHtml()

jessibucaPro.toggleControlHtml(true)

jessibucaPro.toggleControlHtml(false)

getControlHtml()

  • 用法: 获取控制面板的html
  • 返回{DOM | null}

播放器会在传入的html外面包裹一个div,返回的就是这个div


<div class="jb-pro-controls-item-html">
    // your extend html
</div>

demo

const controlHtml = jessibucaPro.getControlHtml()

updateWatermark(config)

  • 用法: 更新水印
  • 参数{object | array} config 水印配置
  • 返回{void}

水印参数支持 objectarray 支持配置多个水印数据。 配置参数等同于watermarkConfig

// 单个水印
jessibucaPro.updateWatermark({
    image: {
        src: 'data:image/png;base64,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',
        width: 150,
        height: 48
    },
    right: 10,
    top: 10
})
// 多个水印
jessibucaPro.updateWatermark([
    {
        image: {
            src: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAS4AAABgCAYAAACjZZ/rAAAK4mlDQ1BJQ0MgUHJvZmlsZQAASImVlwdUU1kagO976SEhkIQISAm9SW8BpIQeivQqKiEJJJQQE4KCDZXBERwVRESwDOCoiIKjIyBjQSxYUWzYB2RQUNbBgg2VfcASZmbP7p7937nvfufPf/9yz705/wOAHMKVSDJhFQCyxDnSyABvZnxCIhP3DOAAA9CBA7Dm8mQSdnh4CEBkev6rvL8LoIn5luWEr3///b8KlS+Q8QCAkhBO4ct4WQi3I2OEJ5HmAIA6jOgNluRIJvg2wnQpkiDCgxOcNsVfJjhlktEqkzbRkT4IGwKAJ3G50jQASDaInpnLS0P8kMIRthHzRWKECxD24Am5fISRuGBOVlb2BA8jbIrYSwAg0xFmpfzJZ9pf/Kco/HO5aQqeqmtS8L4imSSTm/d/bs3/lqxM+XQMY2SQhNLASGRWR/bvXkZ2sILFKfPCplnEn7SfZKE8MGaaeTKfxGnmc32DFWsz54VMc6rIn6Pwk8OJnmaBzC9qmqXZkYpYqVIf9jRzpTNx5RkxCr1QwFH4zxdGx01zrih23jTLMqKCZ2x8FHqpPFKRv0Ac4D0T119Re5bsT/WKOIq1OcLoQEXt3Jn8BWL2jE9ZvCI3vsDXb8YmRmEvyfFWxJJkhivsBZkBCr0sN0qxNgc5nDNrwxV7mM4NCp9m4Av8QAjyMEEMsAPOwBawQAQIzREszZkoxidbkicVpQlzmGzkxgmYHDHPag7TzsbODoCJ+zt1JN5GTt5LiHFqRpe9BznK75E7UzqjSykHoKUICf1gRme4CwBKIQDNHTy5NHdKh554YQARUJB/Bg2gAwyAKbBE8nMCbsALyTgIhIFokAAWAh4QgiwgBUvAcrAaFIESsBlsBVVgN6gD+8EhcAS0gBPgDLgAroAb4A54CHrBAHgJRsB7MAZBEA4iQzRIA9KFjCALyA5iQR6QHxQCRUIJUDKUBokhObQcWguVQGVQFVQD1UM/Q8ehM9AlqBu6D/VBQ9Ab6DOMgkkwHdaGjWFrmAWz4WA4Gl4Ap8GL4Xy4EN4IV8K18EG4GT4DX4HvwL3wS3gUBVBKKAZKD2WJYqF8UGGoRFQqSopaiSpGVaBqUY2oNlQn6haqFzWM+oTGomloJtoS7YYORMegeejF6JXoDegq9H50M/oc+ha6Dz2C/oYhY7QwFhhXDAcTj0nDLMEUYSowezHHMOcxdzADmPdYLJaBNcE6YwOxCdh07DLsBuxObBO2HduN7ceO4nA4DZwFzh0XhuPicnBFuO24g7jTuJu4AdxHvBJeF2+H98cn4sX4NfgK/AH8KfxN/HP8GEGFYERwJYQR+IQ8wibCHkIb4TphgDBGVCWaEN2J0cR04mpiJbGReJ74iPhWSUlJX8lFKUJJpFSgVKl0WOmiUp/SJxKVZE7yISWR5KSNpH2kdtJ90lsymWxM9iInknPIG8n15LPkJ+SPyjRlK2WOMl95lXK1crPyTeVXFALFiMKmLKTkUyooRynXKcMqBBVjFR8VrspKlWqV4yo9KqOqNFVb1TDVLNUNqgdUL6kOUnFUY6oflU8tpNZRz1L7aSiaAc2HxqOtpe2hnacN0LF0EzqHnk4voR+id9FH1KhqDmqxakvVqtVOqvUyUAxjBoeRydjEOMK4y/g8S3sWe5Zg1vpZjbNuzvqgPlvdS12gXqzepH5H/bMGU8NPI0OjVKNF47EmWtNcM0JzieYuzfOaw7Pps91m82YXzz4y+4EWrGWuFam1TKtO66rWqLaOdoC2RHu79lntYR2GjpdOuk65zimdIV2aroeuSLdc97TuC6Yak83MZFYyzzFH9LT0AvXkejV6XXpj+ib6Mfpr9Jv0HxsQDVgGqQblBh0GI4a6hqGGyw0bDB8YEYxYRkKjbUadRh+MTYzjjNcZtxgPmqibcEzyTRpMHpmSTT1NF5vWmt42w5qxzDLMdprdMIfNHc2F5tXm1y1gCycLkcVOi+45mDkuc8Rzauf0WJIs2Za5lg2WfVYMqxCrNVYtVq+sDa0TrUutO62/2TjaZNrssXloS7UNsl1j22b7xs7cjmdXbXfbnmzvb7/KvtX+tYOFg8Bhl8M9R5pjqOM6xw7Hr07OTlKnRqchZ0PnZOcdzj0sOiuctYF10QXj4u2yyuWEyydXJ9cc1yOuf7hZumW4HXAbnGsyVzB3z9x+d313rnuNe68H0yPZ40ePXk89T65nredTLwMvvtder+dsM3Y6+yD7lbeNt9T7mPcHH1efFT7tvijfAN9i3y4/ql+MX5XfE399/zT/Bv+RAMeAZQHtgZjA4MDSwB6ONofHqeeMBDkHrQg6F0wKjgquCn4aYh4iDWkLhUODQreEPppnNE88ryUMhHHCtoQ9DjcJXxz+awQ2IjyiOuJZpG3k8sjOKFrUoqgDUe+jvaM3RT+MMY2Rx3TEUmKTYutjP8T5xpXF9cZbx6+Iv5KgmSBKaE3EJcYm7k0cne83f+v8gSTHpKKkuwtMFixdcGmh5sLMhScXURZxFx1NxiTHJR9I/sIN49ZyR1M4KTtSRng+vG28l3wvfjl/SOAuKBM8T3VPLUsdTHNP25I2JPQUVgiHRT6iKtHr9MD03ekfMsIy9mWMZ8ZlNmXhs5Kzjoup4gzxuWyd7KXZ3RILSZGkd7Hr4q2LR6TB0r0ySLZA1ppDRxqlq3JT+XfyvlyP3Orcj0tilxxdqrpUvPRqnnne+rzn+f75Py1DL+Mt61iut3z18r4V7BU1K6GVKSs7VhmsKlw1UBBQsH81cXXG6mtrbNaUrXm3Nm5tW6F2YUFh/3cB3zUUKRdJi3rWua3b/T36e9H3Xevt129f/62YX3y5xKakouTLBt6Gyz/Y/lD5w/jG1I1dm5w27dqM3SzefLfUs3R/mWpZfln/ltAtzeXM8uLyd1sXbb1U4VCxextxm3xbb2VIZet2w+2bt3+pElbdqfaubtqhtWP9jg87+Ttv7vLa1bhbe3fJ7s8/in68VxNQ01xrXFtRh63LrXu2J3ZP50+sn+r3au4t2ft1n3hf7/7I/efqnevrD2gd2NQAN8gbhg4mHbxxyPdQa6NlY00To6nkMDgsP/zi5+Sf7x4JPtJxlHW08RejX3Ycox0rboaa85pHWoQtva0Jrd3Hg453tLm1HfvV6td9J/ROVJ9UO7npFPFU4anx0/mnR9sl7cNn0s70dyzqeHg2/uztcxHnus4Hn794wf/C2U525+mL7hdPXHK9dPwy63LLFacrzVcdrx675njtWJdTV/N15+utN1xutHXP7T510/PmmVu+ty7c5ty+cmfene67MXfv9ST19N7j3xu8n3n/9YPcB2MPCx5hHhU/Vnlc8UTrSe1vZr819Tr1nuzz7bv6NOrpw35e/8vfZb9/GSh8Rn5W8Vz3ef2g3eCJIf+hGy/mvxh4KXk5Nlz0D9V/7Hhl+uqXP7z+uDoSPzLwWvp6/M2Gtxpv971zeNcxGj765H3W+7EPxR81Pu7/xPrU+Tnu8/OxJV9wXyq/mn1t+xb87dF41vi4hCvlTrYCKGTAqakAvNmH9McJANBuAECcP9VfTwo09U0wSeA/8VQPPilOANT1ABC9DICQawBsr0JaWsQ/BfkuCKcgejcA29srxr9ElmpvN+WL5Im0Jo/Hx9+aAoArBeBr6fj4WN34+Nc6JNmHALTnTfX1E6JyEIAacxtH+5D7VPMC8DeZ6vn/VOPfZzCRgQP4+/xPeFgcU9phDh8AAABsZVhJZk1NACoAAAAIAAQBGgAFAAAAAQAAAD4BGwAFAAAAAQAAAEYBKAADAAAAAQACAACHaQAEAAAAAQAAAE4AAAAAAAAAkAAAAAEAAACQAAAAAQACoAIABAAAAAEAAAEuoAMABAAAAAEAAABgAAAAADApncsAAAAJcEhZcwAAFiUAABYlAUlSJPAAAB1BSURBVHgB7V0HeBTVFj6b3fRCAgSQ3qSKIuoDRESx8OzloaIIiqhYUIEHiIJIU6QpVkRRwMaTp4INBBsoRZQiIFhACL1DQtpusuWdf8IsM7Ozu0nYDQzvnO/bzMyd2+a/N/+ce+65d2w+FhIRBAQBQcBCCMRYqK5SVUFAEBAEFASEuKQjCAKCgOUQEOKyXJNJhQUBQUCIS/qAICAIWA4BIS7LNZlUWBAQBIS4pA8IAoKA5RAQ4rJck0mFBQFBQIhL+oAgIAhYDgEhLss1mVRYEBAEhLikDwgCgoDlEBDislyTSYUFAUFAiEv6gCAgCFgOASEuyzWZVFgQEASEuKQPCAKCgOUQEOKyXJNJhQUBQUCIS/qAICAIWA4BIS7LNZlUWBAQBIS4pA8IAoKA5RAQ4rJck0mFBQFBQIhL+oAgIAhYDgEhLss1mVRYEBAEhLikDwgCgoDlEBDislyTSYUFAUFAiEv6gCAgCFgOASEuyzWZVFgQEASEuKQPCAKCgOUQEOKyXJNJhQUBQcBxqkDgK8gmT+5+Ik8RuTYvJtefC6l430YiO9fQxj+mWHvluhTX4GJKaNKFYhLSKSaRf8nV+L7w76nSjlIPQaAiELD5WCqioGBlFGetJOfGb8nNJFW07RciX3EJUamEpR7BTfgdIzGcO6o1pbja7Siu1gUU37BLsCIkXBAQBE4zBE4qcR2adDV5cnYxVxWUkJKWnFTCUo/ae+r5saMtLoHsabUordMzFFvjvNOsieRxBAFBwIhAhROXz5VPBd+/SfmLppHP42LC8lGMzcOjPS/5mIhsdi+H8bmdL2LwYyUsxkY+W2yJtqXRuBQNjO9rNbHElt0piX+O9DONzyrX/0cIbNuxm5yuImrcoA7Z7Xj7iZxOCFQocRVvX0f5C14h18bvFdtVrLeQSctNNlsx2RwgK4bWwSNXPvrY+uaz8zkfvUxiIC6fL5a8nqQSolIJSz1qCM2eXo/SLhxJcTU7nE5tJc9SCgQKCp3Ub9hztHzlWiV2g7q16OWxQ6le7TN0qQ8dyaZNW7bpwtIrpVGzxg10YXJxaiJQYcTlWruQjr4/mLxF+WRnO1a8O5e1K59CVipBBSMukBgnUjQyctjI40xnEovTE5iGuFRNLLXdcEpqdicnxk1ryr4Dh2jjn3/rKp+YGE/tzjtHFyYXJQhMmjKTZvxnrg6O885pSTNeGqMLm//tEho8apIu7KK2bWjK+Kd0YXJxaiIASoi6OFfNY9J6nMhdSHFuF8V62KYFzapc4iN78mHyulOYBJM5h+CklLvqObaf5VByy/uZ5JjoLCi/rPmNnnhmsq7mdWrWoHmzpujC5KIEgdXreCbaIGs3/MEvOh9r9sH7iiGJXJ7iCGCgFVVxrf2ajr43hMhVQPGF+RTHx0iILSGPbMk5nFUIAmTXivyNb5Nrz5JIFCl5WACB2mdUD6hlzerVhLQCULF2QFSJy5t7iPK/eZt8RYUU73KSw10UHi28FRPSKCa1JtmrNKH4s3tRUscxFN+sO9krNWK/rZqsrSUq+djinGRLyg2Zp68ol7IX9yFPwb6Q8eTm6YHAQ/fcThlsq1IlNtZBg/r2Ui/leJogENWhYt6ciVS8eSVrWYUUW+xSDO6hcLMlVaa49veQo3FnctRtx1FNVHufh1xbPqaiXQvIuX022RLz2XDP1nwnho3B5ch3d1LGJdPInlIveCS5Y3kEYISfM/NFgg3LxbOKl3S4gBrVr2P555IH0CMQNeJy78uiwmUfM2k5FW1L8YDXl627sjfqRAk3jCM7O5WGFCap+Ea3Uly9aym+8W2Us+QORevyFUELC65AevK2k2vvckpqLMQVEt/T4GaVjHS6s+u1p8GTyCMEQyD4f3qwFKUI97F2dWRsV7J5veQoYk/4MGKvfS4l3zc3PGlp8rE5ktjd4UpKa/8G2eIqkS0t21RB8yfxeSl39Qj2HSv0B8mJICAIWBOBqGhczhWfk4+N8Ha3mxzF7pBDxNhzb6aEnm+WG734OjdTWoydcpb3YNsX29A8IWYPeZiZt34SpbYeVu7yrJgwNy+fdu7ZR3v2HqD8wkKqnlmFzqieSbVqVGMf3/K/u5xOF/35dxYdPpJD2UdzKSU5iapkVKKGPDRLT0stF1TRyLNcFTmWyOv10a69+2jrtl38fIlUu2Z1yqxS+ZQ29hcVF9PuPftp74GDtO/AYUpMiKeqVTKobq0zqGrl9HLDgZnZv7N2cL6H6Eh2DhtybFSZ27ta1crKcLwiZ20jTlw+1mzcO34nn7uY7EXukCDFZDaiuC7sJmFmywqZUn8zvtYNlNZ2KuUsGsTEpb9nvCrY9M7/BXGhky395Vea9cmXtGTFasI/oFHQ4bped6Xyy+SOXVpZ+vMaev/jL+nn1evIZaJRx/BKh3NaNqV/XXMFXdflUiZHE1ulobBI5Tn70wU04bXputxv/GdnGtqfXWLKIAcPZ9Pz7BO2cPEyxVamTVqtahXqeet1Cm7JSSUTRdr76vnAERNp8fKV6qVyHDnoIbr68ot1YcaLT7/6nsa8MFUXfPnF7Wjs0H66MOPF739toY++WEhffv0D5RcEjixALGiXa6/sRF2vvaLUKwqwCmHa+5/QDz+tVF5SxnJxDUK8pMM/6L4eXakmvxSjLREnLu/BXeRa841S74RCNsiHWG1hb345xVSPzNIcR/q55Khcm9x7DoXBzEcuNuzH1zp9F2VDw8I/zTImrlCy/+Bhem36f2j6rLk0dthjdFlHTIgEF/wzPDFmMn2/9OfgkfgOSHLN+j+U3wdz5tGLY4ZQjWpVTdNEOk+3x03Q2rQCDaQsMu+bH2j081MpL9/cdWf/wUM08bUZCnm/OWkE1avDM90mgnKNdXF7wrxZOR83j1SM6YpMXhBqkR7OE/V576Mv1CDTI15mv/72h/L7+POv6ZknH6UzGwa3+SL+5Knv0szZnxHKCCUg+o8+X0hffL2YBjxwF91+01Whop/wvfKPE4IU7XPmk+fwbnavCnzDG5PEXTvUGFTua0dqM3LUaFmq9M6d80oVz4qRdu87QN0ffDwsaWmfrdDppP5PjVcITBuuPcc/0oODR4UlLW0anMPrv9djwwgd2yjRyNNYRlmvUd+nnnslKGlp89vDWPfo+wRt3rpdG1yh52i7ewc8HZa0jJX6fdMWuvvRYbRl207jLf/10GdfordnzQlLWv4EfII2fXbyGzRn3rfa4IifR5y4irPWK5W0u0MztK1SDbIlpET0gRJq3liq/HxerhsPaU83gaYzZPTztHX7roBHgy0Lw4TrrrzEVJVX3q5vvENmnufIDENDaFFGObdVM+rT8xYa9XhfuvWGLooNyBhn5+59/OZ+xxgclTwDCilDAJZXDXh6Amk1NIfDTkmJCUFzOZJ9lIaPe0XxzA8aKYo3oGmt/HWDaQkYsrVt04qan9nQ9BmO5ubRg4NGBWh3yOyr75bQ5wsXmeabkZ5Gl/KwsGO786iWicMvEo1hjRW2z2hJxIeKzqVzlLrGeEITQ8Jdr0f8meKqdipVnl7nAfK6DvFmhNEfi5eqQhGK9P7HX5iSC1T3rtddQakpx33dtu3cw8O+F2j975v8pYP4ho19mT6ZPpkS2KCrlZkffqq9VM773d+Dene/2R9+09WXKeewVz02dKzO/oV/gn59euqMw9HI01+ZcpxoF11f0am9Yq9p2qi+MoFx4NAR+viLr9nW83GAzQsYQsO4+ZrLy1Fq+ZMAZ9j0jAIj/MjBD9P5rY+PQGCLfO+/n9Or02dRMU+YqQINfdac+dTrdv1Lf8qMD9Uo/iPyGzHwId3QGC+8+Uxyw8a+pMsX5D/7swX0wF23+tNH8iTiGlfR5jVK/Xj1dsh62ng300iLLfa4x3SovD1528hbwMPZ00jcrOFOfWd2wBPdc/tNSqfUkhYiwVHzpWefVGYXtYl27N5L3/64QhtEsIUdyTmqC8Nb9+5uN+jC1IsO/ziXut10tXqpHEGK6zb86Q+LRp7+zE/wpHPHtvT8qMGKpqLOumLyAv+ETw14wDR3aKQVLW+xwdwo8XGxSt21pIU4CMdL5ul/P2hMEjDMhA3POITETPSkEYN0pIWMYPC/+rKOdH+PWwLyXbP+94CwSAVEXOMiNo7C2dQTbg8kdmE4WQJty+M6gh1zThv5iWf4co7m6Z4HuyL069NDF6a9wEzQ+OEDqMfDT2iDlWHCNVccn/mCsd8oCfHxIWelHul9R4ATaFrqcdNANPI01rE81yD0Z554NGjSG/55KWu1vyvalzbSX+wWsnf/waCTENq4kTiHzXDVug0BWQ3u25uaNq4fEK4G3HBVZ8KEiXbHERDVLnaXUYd9aSkpitatpsERbg/4BRO8rF59e5bu9q69+3XXkbyI2v+u1xFGmeMF0CKRQ2DBd0sDMmt//jlh/Y3ObsHrQfltrHVrWPrLGmU4FB9f4hPXoG5tZZipJRsYpqfOnE19ggwFkDbYTCIqGo08AwAoR0D/B3oq/mihkg55pDfNnf9dgNH6x59W0S3XV8xs9XesFUOL1QrWaMLOGE7688sMu45oRTt8hJkg1GyjNp16Dtcao+Tlmc/KGuOV5zpqxOUL49joO/A3UbVG5amzpDFBQGufUW9XYY0KQ7JwUomdRbXx0In38VsYthII/LBghP9h+SpdVq/wG/YLdh3AUAFvXBiBsai5NBKNPEtTbrg4zZuE75P4x67PLhBwxtQK7IYVJVk7Aidg4PhbGsFebpHaz83Lq2NymaCgsVWklK6XlaFGtvgEdj51Kim8TF687Z9p6sKZD1PK+OOGYdNIUQq0J9XkLwRVj1LuJydbGI+NMnLCa8agUl8f5PxU4kKi3nfczG/pDYTpd61k8QwmfMHwi4uNpeZNGlLrs5oRtL3zW5+laHPa+NrzaOSpzb+s5/D8L63zZOMGdQOICzOMFSUHDwe2d+NSEldZ64jZ1kXLfqE/N2cpBIVrkFVePm/DzjvOngyJOHHFt76MnCtLDJXO5ARKLAi0jygPmn+IvHk8s5dSpcKf255Sl0Bep4tgyICtiCMpRr+rNme3oNcnPMW+XKODdlbMJK1lAzx+mDGEVzlm2u7t/i9T+0g08jwRDJqEcMY05ouh1ILv9cPzwxFuA2OZ2muzF1Wkd8GAFj/+len006q12qJPifMwhqiy1zGxY1d/IuwVD60rmLhm3hfsVlTDbXEZvCFqcENjVAuPSua8rXWE/dLMPLxBNLOmTqDu/7pGt+dVsEeCV/y7PAUP4z+m3c0kGnmalVOaMFuIvmpMb7YuT29xMqaI7HWMybdEuRdErBD4cXXtPeCUJC08ZMQ1rpi0qn7wPA4HudlIG1tsrk569/5F3m0rKabe+f40FXFi1ukqotxolYEp+8rplQK808fxjKF2U72ylB/MONuwXm0a8ui9NPChXgRjNNbiQcPasm1HgLFYLW/7rj10V98n6d1Xx5oa7KORp1p2WY5mdsJg6Tdv3RZwC21QUWK2WNpocytvXTb8uVnZLhz2K63AGfcCHv5Ds8N6zdTUZEpj30C42hTw4v1+w8Zpo0f1POLEZUvJ4E0AW/BC641KxV1syAxGXL4c/oTU7AGUNHARO4QE18zCIVC46UNKPPO2cNFO+n34WsFhTyvhjNlGmxLSqrN92nyqVs4IIC6QFmxN0RB04ksv+ofyQ/5Y17du419swF9J8775McDvC64CXy9eTj1uuS5odaKRZ9DCTG7AkxyuAfinDCebtmwPiBLKXUCNXGhYR6mGa4+wL4YT7PZglL+zdhqDynX9xrsf8XpJvW0as88TRwwM8PtTC4DdqyKl/GwRpJb2jOq8zXJ7/13MLuamp8NTzR+mPfHs/o2ODqrC2zuXferUx9vU5K8ZzYurW2mzLMW5eV1KkfCEolx9x4PU5vJbdD/1M1rBMsZyGaOY7eRQnz/DZRSsR6sogWH7wgtaK9rYlx+8xt8zDHQwXrW25GVW2jpFI89wZf+xKStcFMV1xGxWTzuZgUxiecRhFLiRhJOsneGdo/HZNaNsMcxyGu+r1/DhwioA7U9br+W/BNq04O+HrZCCSUWv14w4ceHB4pq3I1usZn0Xk1ZBcjJvsRy8uIIpXaj41w+D4RIQ7snfRQVrx1LeL7wdcxmX7sSwjetkSKvmZwYUiy1nQskqk6/WmPnMYImKUcw6oDEOrjGVjc6MIcJvf2xWlgFp/XqghYBAtT/tej5jnhg6GJeQIM4fm7f6o0YjT3/mJ3DyAq+pNNNytVlOfHV6gEaC+x3btdFGU/Ym0wXwBfANJfCVW/JT6D6B9J0vaqssRdLmhdUNHzEhhRI822P83ckRPOOs/akjAcyMGp8fLxDVOTVY3kZXmWDxIhUe+EqIQM5xZ3WimPRM8hw67uficcRSoT2VkgpzTEvw7PmNCub2I8eqt3nf+YcotsX1HC9QM/J53VS4bhK5smZT0W72UcL3Fcso3uLcMqaITHQscl64aJkus8947yWs8TPTUDC0gv3IKDBoG+ViXvCamJCg63SYDXp52vv0yL3djdH91/A9uvXeAbqZQnTSeR9M8ceZ8OoMxZveH8AnqDMWVgcTh4m2gWUjqkQjTzXvEzlCcxgx/jWCfdBM5n37I/1n7vyAW/BWN2okZkPOFavWKS8Gs5cYMkV7YVPGcIJh6QW8dnDF6vW6qM+9NI1acz8z60+I+PqM2YqHvzYRXEBq8qaSELMF5TADYCiobT9tetgG5zMuFSnBVaATqQVrWFXGLOQPWRxf4oHsvLwMKD8lnWca7ea5sxHfvX0FFXx0F2U/m0HZL9Sm/C96UQFvEJg793o6PK0m/ypTwc/jqWgH2wE85eRd/iDtyZDzeQmOUdBJ7+3/NH224HtF84FrA4zZr7NXuvGDpUgLL/crL7nQmI2yKNpsn3XYK/CBVLO9pRYvW0n38ZYoRl+cbjf+U3E6VQvBDgNGwaJi7FtlJujkM3iPL6PATqJKNPJU8z7RI8gJ37KEsVvVRNBO2OIFpGYmd9x8TUBw+wvM7YsPsUsJXmCq1oo2x44ejzzxrLLgOSCjIAH3sG+dUfCBkP7Dx+sWzyMO9tPC0PCd/35mTEK333x8XSnsp2YE9eQzL5rODGPPt5488WJcyxpQSIQDovol6/yveDO2TyeWfMMCFIkflCibj2J9Lr4sIrutmDcbZIM1c1C4L1l7KY47Ujx/DDaR8+KMjuWZefcy/mxZyfh73zQejqllqeWBJ1HusfCEuldTpbYvckDFC9RzdKBgYmdyD7VpG1wRMKtnJhjedesziLBuziiYeWzBzqFnt2hKBw4dpr/4LYmdLY2CGb73p4zTLXvBP8P1PfqadlzEx0zTua2a01Ee5sDOgs3kjEQJb/P5s1737w4RjTzxLB/wjq9jX5ymeyz4kmG3BK2YfckadsI8fgatDxv+kRP4Z1wHqs0L2hMwM5utvur2B5Qhtja+eo42qVkjkw4dztFpylgvafTCx8tq0shBalL/ceTEKcoGfv4AzQnapk6tGtwWhUyMO023mYGW+Pl7r+ochaH14YVnJphRbNvmbEUDw6aEqv8gNDXjCxAfLVk0d7pZNiccVk6VpXTlJl12FxX9vZKKNi7SJ2CNrNjONjBbPE8m8pepyUUOG4zz+hk3JPL52Pe+OJGN9/yDjQxGfhCQRpxbF1DSWXcqITZHPG+15dLcPbVOBz3ci31j1gVdIhGKtJo0qk/9eYuaYIIZShhR+wwcqXQsbTxMbcO+EsrGgjft1IlP60gLeeCfd9SQR+jhIWMCtnTBLgL4ffjpV9ridOf4B8WWxdop/GjkqSu0HBf4mOw9d9ykaMCqKwAIFr9ggplbDJnNSAtphva7X3HaNUuPMoyTLxfx0qnL2F5Z2lUP6E94Waw22YlBbRuzshEGW+Rr44bpSAvhPW69XlnepbVJIhwCLdTodoF8Xhj9OOM2vCRSBfw1UEBkS4SBPr33CxRbu3mQjG1MVTHkjkkkZ0wV/lUlJ2WS05tJLk8mq9LVeI+fTNawUpjAVLUpMKvcJaPBcMqNytfPCYxgCPHk7yRvYeBsnSFaVC7hTY6tjEOt4DcrGPaxV58bGtDJjHHxRvzwzYnUhjWgsgjWrr31wihTPyvkg6Hd1AnDlQ8jlCVf2GKeHzXIdJ/1aORZlrqZxYX2CI02nJsK0oLoZ77ybFB7EuJc1LYN9eWdMoIRG+KoglnJ0bwzBQYHpRVoOm9NHl2qxdXaPNFP0N5mtjB86GTGy89Q2/PO1iYxPUf5aF+s3axIsY9giWaBNkccxbfqTO79W8hzMKtkyIaWCfcDpSKOegwZn7W2lBoUm9mS1yBWJnf2ZvLk8OyNmsaQh6/oIMVV73DSPg4LzQMfqUjntzXUbdXWwU8bIDCcwpaBoY52W5iAiJoAdKbru1xC0NDgm7SLv/hiJvCbAiGOYW3qwV63cX1SzaL5w2DA7XbjVcpSHgynDmebT7QgAYYp3XjfcWiAzRo38OdhPIl0ntjUzzhTi/WT2LFTKzDCY/JDK3V5iHbtFZ0IQ7+reOH4Tt6bDPuTGVzveLYwnfef6kpjmGTM7EHaPHEO22bLpo2V/Mz8nbDGEx+ZGDf834pDJz56gbWBWgHRdLm0gzbIfw6NtlP78xV3FGhxWWwCCKa544V592030Ghu8+rVjk+W+DM7doI6XdW5IzlZ29zOEzhOl34Ug76DPjyZX8JNGtZXPs7xDu9NrxX0w7u73agNith5VG1c2lrCT+vIy3dS8Q6eBQGRqGSinmuPIBxVwVKP6n3cU881x7ha7Sjj2rf5XizPNi6hnMX9yFvM/1javNT4HJbSaiAlN+2jreJJOcce3TDMlqj1O9gB8oiyrg++Wi2aNqJzecFyad7WoSoPOwSGJHACzWYjM8gQH3jA58lgUyuvYEcJzChl5+QqBJnMn++C9zhIS52lKmve0cizrHXQxsd2P7APwR4It4DaNWsouOEftzyCfLbyzg77+bNhldJSFKzQFiCKSAlsTdvYFwztDTwT4uKUz5PVq13TdGvtcOWCBGETRZ29vLSsfp1aVIdxKC8G4corzf0KIy61MtnT+1LRX0vJV5x3XKNSCUU9asmmlMQFgko6525KbT9UKSp/w9uU9+vzPJXJb4ogeWRes5xi4o8vUVLrKEdBQBA4tRGocOLyuYuoOGsN5cz6N3mPsp1JJSvtsZzEFZOUQZk9f/Yj7tr5PeWtnUzunI16kkT+XF5c9Qspo8NMf3w5EQQEAWsgUOHEpYXFufozyp03lrzObDauu4+TWFmIi4c6MUmVKK5+Z6rUaTQTVOBEac6ygeTau5iLYMc+G6/BOkZccKlIOrMXpbYYzGHlU/21zyPngoAgUDEInFTiUh6RPxVWsGIWf4sxi4p3r6finatLiEUd3qlHVSM7Rjr2Kg0pvkEnsqeeQYln3c58pVliZIKdj73lC7d+wiS5l5z8QVhP4Q6FKG3xaZTS7BFKanC3SSoJEgQEgVMRgZNPXCoqbPTz5rPxL++gEuIpOMhLhrbwcHKXsqNqTEZtcmQ24ZnAkp1LbfGpZE/DFCyYrGwCdwifO4/c/LWfgi1v8Ycz9lHm5YvLlonEFgQEgZOGwKlDXCcNAilYEBAErIYABmAigoAgIAhYCgEhLks1l1RWEBAEgIAQl/QDQUAQsBwCQlyWazKpsCAgCAhxSR8QBAQByyEgxGW5JpMKCwKCgBCX9AFBQBCwHAJCXJZrMqmwICAICHFJHxAEBAHLISDEZbkmkwoLAoKAEJf0AUFAELAcAkJclmsyqbAgIAgIcUkfEAQEAcshIMRluSaTCgsCgoAQl/QBQUAQsBwCQlyWazKpsCAgCAhxSR8QBAQByyEgxGW5JpMKCwKCgBCX9AFBQBCwHAJCXJZrMqmwICAICHFJHxAEBAHLISDEZbkmkwoLAoKAEJf0AUFAELAcAkJclmsyqbAgIAgIcUkfEAQEAcshIMRluSaTCgsCgsD/AFt/MVAlcetCAAAAAElFTkSuQmCC',
            width: 150,
            height: 48
        },
        right: 10,
        top: 10
    },
    {
        image: {
            src: 'data:image/png;base64,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',
            width: 150,
            height: 48
        },
        left: 10,
        top: 10
    }
])

removeWatermark()

  • 用法: 移除水印
  • 返回{void}
jessibucaPro.removeWatermark()

getVideoInfo()

  • 用法: 获取视频信息
  • 返回{object}

返回一个对象,包含以下字段:

  • width:视频宽
  • height:视频高
  • encType:编码类型,包含:H264(AVC)H265(HEVC)

需要在触发videoInfo事件之后才能获取到

const videoInfo = jessibucaPro.getVideoInfo()

getAudioInfo()

  • 用法: 获取音频信息
  • 返回{object}

返回一个对象,包含以下字段:

  • sampleRate:采样率
  • channels:声道数
  • encType:编码类型,包含:AACALAWMULAW

需要在触发audioInfo事件之后才能获取到

const audioInfo = jessibucaPro.getAudioInfo()

updateLoadingText(text)

  • 用法: 更新loading文案
  • 参数{string} text 文案
  • 返回{void}
  • 注意: 该方法只在 loading 状态下有效
  • 示例
jessibucaPro.updateLoadingText('加载中...')

暂不支持dom。更新的是innerText

updateIsEmitSEI(isEmitSEI)

  • 用法: 更新是否发送SEI
  • 参数{boolean} isEmitSEI 是否发送SEI
  • 返回{void}
  • 示例
jessibucaPro.updateIsEmitSEI(true)

setAspectRatio(aspectRate)

  • 用法: 设置视频宽高比
  • 参数{string} aspectRate 宽高比
  • 返回{void}
  • 示例
jessibucaPro.setAspectRatio()

// 16:9
jessibucaPro.setAspectRatio('16:9')
// 4:3
jessibucaPro.setAspectRatio('4:3')

getPTZCmd(cmd,speed)

  • 用法: 获取 gb28281 ptz指令
  • 参数
    • {string} cmd cmd 命令
    • {number} speed 默认值 4 速度 0-9
  • 返回{void}
  • 示例

jessibucaPro.on('ptz', (cmd) => {

    const ptzCmd = jessibucaPro.getPTZCmd(cmd)

    // ajax 发送指令到服务器端。
})


关于gb28281前端设备控制协议(GBT-28181-2016.pdf):见:

getExtendBtnList()

  • 用法: 获取 自定义按钮列表
  • 参数
  • 返回{array}
    • {string} name 按钮name
    • {DOM} $container 按钮容器DOM
    • {DOM} $btn 按钮DOM
    • {DOM} $activeBtn 按钮DOM
  • 示例
const extendBtnList = jessibuca.getExtendBtnList();

支持对自定义dom按钮进行自定义操作。$container是按钮的容器,$btn是按钮,$activeBtn是激活状态下按钮。

getFlvMetaData()

  • 用法: 获取flv流的metaData数据
  • 参数
  • 返回{object}
const metaData = jessibuca.getFlvMetaData();

只有flv流才会有数据。

如果想要第一时间获取,可以通过监听flvMetaData事件获得。

flvMetaData事件触发之前,返回的是null。

showErrorMessageTips(content)

  • 用法 显示错误信息提示
  • 参数
    • {string} content 错误信息提示内容
  • 返回{object}
jessibuca.showErrorMessageTips('错误提示内容');

在触发播放器加载的时候提示信息会消失掉。

hideErrorMessageTips()

  • 用法: 隐藏错误信息提示
  • 参数
  • 返回{void}
jessibuca.hideErrorMessageTips();

setPtzPosition(position)

  • 用法: 设置云台位置
  • 参数
    • {object} position 云台位置
      • {string} position.left 参考 css left 属性
      • {string} position.right 参考css right 属性
      • {string} position.top 参考css top 属性
      • {string} position.bottom 参考css bottom 属性
  • 用法: 设置云台位置
jessibuca.setPtzPosition({
    left: '100px',
    top: '100px'
});

// 或者
jessibuca.setPtzPosition({
    right: '100px',
    bottom: '100px'
});

getContainerRect()

  • 用法: 获取播放器的尺寸和坐标信息

尺寸和坐标信息是通过 getBoundingClientRect() 获取的

const containerRect = jessibuca.getContainerRect();

proxy(target, name, callback, option)

  • 用法: DOM 事件的代理函数。
  • 参数
    • {DOM} target 代理的DOM
    • {string} name 事件名称
    • {function} callback 回调函数
    • {object} option 事件配置

实质上代理了 addEventListenerremoveEventListener, 当使用 proxy 来处理事件,播放器销毁时也会自动销毁该事件

等同于 target.addEventListener(name, callback, option);

假如你需要一些 DOM 事件只存在于播放器的生命周期上时,强烈建议使用该函数,以避免造成内存泄漏

jessibuca.proxy(document, 'click', function (e) {
    console.log(e)
})

getUrl()

  • 用法: 获取当前的播放地址
const url = jessibuca.getUrl();

toggleControlExtendBtn(name, isActive)

  • 用法: 设置扩展按钮的激活状态
  • 参数
    • {string} name 按钮的name
    • {boolean} isActive 是否激活状态(如果不设置,则根据当前的状态做切换)
// 激活
jessibuca.toggleControlExtendBtn('extendBtn', true);

// 取消激活
jessibuca.toggleControlExtendBtn('extendBtn', false);

// 切换状态
jessibuca.toggleControlExtendBtn('extendBtn');

getControlExtendBtnActive(name)

  • 用法: 获取扩展按钮的激活状态
  • 参数
    • {string} name 按钮的name
const isActive = jessibuca.getControlExtendBtnActive('extendBtn');

toggleControlBar(isShow)

  • 用法: 切换底部控制条 隐藏/显示
  • 参数
    • {boolean} isShow 是否显示

// 显示
jessibuca.toggleControlBar(true)
// 隐藏
jessibuca.toggleControlBar(false)

// 切换 隐藏/显示
jessibuca.toggleControlBar()


getControlBarShow()

  • 用法: 获取底部控制条是否显示
  • 返回{boolean}
const isShow = jessibuca.getControlBarShow()

getRenderElement()

  • 用法: 获取渲染的元素
  • 返回{DOM}
const renderElement = jessibuca.getRenderElement()

setExtendHtml(html)

  • 用法: 设置扩展html
  • 返回{void}
jessibucaPro.setExtendHtml('<div>扩展html</div>')

clearExtendHtml()

  • 用法: 清除扩展html
  • 返回{void}
jessibucaPro.clearExtendHtml()

toggleExtendHtml(isShow)

  • 用法: 清除扩展html
  • 参数
    • {boolean} isShow 是否显示
  • 返回{void}
jessibucaPro.toggleExtendHtml(true) // 显示

jessibucaPro.toggleExtendHtml(false) // 隐藏

jessibucaPro.toggleExtendHtml() // 切换显示/隐藏

getExtendHtmlIsShow()

  • 用法: 获取扩展html是否显示
  • 返回{boolean}
const isShow = jessibucaPro.getExtendHtmlIsShow()

getExtendHtml()

  • 用法: 获取扩展面板的html
  • 返回{DOM | null} 返回扩展面板的html

播放器会在传入的html 外层包裹一个 div ,返回的是这个div

<div class="jb-pro-extend-dom">
    // your extend html
</div>

demo

const html = jessibucaPro.getExtendHtml();
// html 是一个 <div class='jb-pro-extend-dom'></div> dom对象

resetPlayer()

  • 用法: 重置播放器
  • 返回{Promise}

播放器内部重置了所有的状态,包括播放状态,清空了所有的缓存,重置了所有的状态。

会沿用之前的配置。

主要是方便了业务层在重播的时候,不需要再次销毁播放器,再次初始化播放器。

jessibucaPro.resetPlayer().then(() => {
    console.log('重置成功')

    jessibucaPro.play('new url');
}).catch((e) => {
    console.log('重置失败', e)
})

或者

try {
    await jessibucaPro.resetPlayer();
    jessibucaPro.play('new url');
}
catch (e) {
    // 重置失败
}

updateDynamicWatermark(config)

jessibucaPro.updateDynamicWatermark({
    content: '动态水印',
    opacity: 0.15,
    color: 'white',
    fontSize: 12,
    speed: 0.2
})

removeDynamicWatermark()

  • 用法: 删除动态水印
jessibucaPro.removeDynamicWatermark()

updateGhostWatermark(config)

jessibucaPro.updateGhostWatermark({
    on: 5,
    off: 5,
    content: '幽灵水印',
    opacity: 0.15,
    color: 'white',
    fontSize: 12,
    speed: 0.2
})

removeGhostWatermark()

  • 用法: 删除幽灵水印
jessibucaPro.removeGhostWatermark()

getI18nConfig()

  • 用法: 获取国际化配置
  • 返回{object}
const i18nConfig = jessibucaPro.getI18nConfig()

kbps2Speed(kbps)

  • 用法: kbps 转换为速度(KB/s)
  • 参数
    • {number} kbps kbps
  • 返回{number}
// 或者
jessibucaPro.on(JessibucaPro.EVENTS.kBps, function (data) {
    const speed = jessibucaPro.kbps2Speed(data) // KB/s
})

updateZoomMaxScale(scale)

  • 用法: 更新最大缩放比例
  • 参数
    • {number} scale 缩放比例
  • 返回{void}
jessibucaPro.updateZoomMaxScale(10) //

isWebFullscreen()

  • 用法: 判断是否全屏(H5)
  • 返回{boolean}

主要是给IOS设备使用的,ios设备不支持DOM的全屏API

const isWebFullscreen = jessibucaPro.isWebFullscreen()

isInView()

  • 用法: 判断播放器是否在视口内
  • 返回{boolean}

isCheckInView 为true时生效

const isInView = jessibucaPro.isInView();
console.log('isInView:', isInView);

isFocus()

  • 用法: 判断播放器是否获得焦点
  • 返回{boolean}

pc 端使用,移动端不支持

const isFocus = jessibucaPro.isFocus();
console.log('isFocus:', isFocus);

on(event, callback)

  • 参数
    • {string} event
    • {function} callback
  • 用法: 监听方法

jessibucaPro.on("load", function () {
    console.log('load')
})

事件

load(废弃)

监听 jessibucaPro 初始化事件。


jessibucaPro.on("load", function () {
    console.log('load')
})

优先判断 hasLoaded() 方法, 因为hasLoaded()方法现在只会返回true,所以这个方法已经废弃。

timeUpdate(废弃)

  • 回调参数
    • {number} ts 是否显示

等同于 stats里面的ts字段

如果需要监听当前帧的时间戳,推荐监听currentPts事件。

jessibucaPro.on('timeUpdate', function (ts) {
    console.log('timeUpdate', ts);
})

//  或者
jessibucaPro.on(JessibucaPro.EVENTS.timeUpdate, function (ts) {
    console.log('timeUpdate', ts);
})

等同于 statsts字段

videoInfo

  • 回调参数
    • {number} width 视频宽
    • {number} height 视频高
    • {string} encType 视频格式 ,包含:H264(AVC)H265(HEVC), MPEG4
    • {number} encTypeCode 视频格式编码 712, 99

当解析出视频信息时回调

encTypeCode 是视频编码类型,7H264(AVC)12H265(HEVC), 99MPEG4


jessibucaPro.on("videoInfo", function (data) {
    console.log('width:', data.width, 'height:', data.width, 'encType', data.encType)
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.videoInfo, function (data) {
    console.log('width:', data.width, 'height:', data.width, 'encType', data.encType)
})

audioInfo

  • 回调参数
    • {number} channels 声频通道
    • {number} sampleRate 采样率
    • {string} encType 编码类型 支持 : AAC,ALAW,MULAW,MP3
    • {number} encTypeCode 编码类型编码 10, 7, 8, 2

当解析出音频信息时回调

ALAW 是 G.711 A-law 编码,MULAW 是 G.711 u-law 编码,

encTypeCode 是音频编码类型,10AAC7ALAW, 8MULAW, 2MP3


jessibucaPro.on("audioInfo", function (data) {
    console.log('channels:', data.channels, 'sampleRate', data.sampleRate, 'encType', data.encType)
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.audioInfo, function (data) {
    console.log('channels:', data.channels, 'sampleRate', data.sampleRate, 'encType', data.encType)
})

error

错误信息

目前已有的错误信息:

完整的错误信息见:JessibucaPro.ERROR

  • JessibucaPro.ERROR.playError ;播放错误,url 为空的时候,调用play方法
  • JessibucaPro.ERROR.fetchError ;http 请求失败
  • JessibucaPro.ERROR.websocketError; websocket 请求失败
  • JessibucaPro.ERROR.webcodecsUnsupportedConfigurationError; webcodecs 解码类型不支持
  • JessibucaPro.ERROR.webcodecsH265NotSupport; webcodecs 解码 h265 失败
  • JessibucaPro.ERROR.webcodecsDecodeError; webcodecs 解码失败
  • JessibucaPro.ERROR.mediaSourceH265NotSupport; mediaSource 解码 h265 失败
  • JessibucaPro.ERROR.wasmDecodeError ; wasm 解码失败
  • JessibucaPro.ERROR.hlsError ; hls 播放失败
  • JessibucaPro.ERROR.wasmDecodeVideoNoResponseError ; wasm 解码视频没有响应
  • JessibucaPro.ERROR.mediaSourceUseCanvasRenderPlayFailed ; mediaSource 使用 canvas 渲染播放失败
  • JessibucaPro.ERROR.mseWidthOrHeightChange ;流分辨率发生变化(可以无视,播放器内部已经处理了)
  • JessibucaPro.ERROR.wcsWidthOrHeightChange ;流分辨率发生变化(可以无视,播放器内部已经处理了)
  • JessibucaPro.ERROR.mediaSourceFull ;mse 缓存已满
  • JessibucaPro.ERROR.mediaSourceAppendBufferError ;mse 解码错误
  • JessibucaPro.ERROR.mediaSourceBufferListLarge ;mse 缓存列表过大
  • JessibucaPro.ERROR.mediaSourceAppendBufferEndTimeout ;mse 缓存超时
  • JessibucaPro.ERROR.mediaSourceDecoderConfigurationError ;mse 解码器配置错误
  • JessibucaPro.ERROR.mediaSourceTsIsMaxDiff ;mse 解码ts 时间戳差值过大(时间戳被重置了)
  • JessibucaPro.ERROR.webrtcError ;webrtc 播放失败
  • JessibucaPro.ERROR.webrtcClosed ; webrtc 连接关闭
  • JessibucaPro.ERROR.webrtcIceCandidateError; webrtc ice 候选失败
  • JessibucaPro.ERROR.audioChannelError ;音频通道错误
  • JessibucaPro.ERROR.simdH264DecodeVideoWidthIsTooLarge ;simd 解码H264视频宽度过大
  • JessibucaPro.ERROR.wasmWidthOrHeightChange ;流分辨率发生变化(可以无视,播放器内部已经处理了)
  • JessibucaPro.ERROR.flvDemuxBufferSizeTooLarge ;flv 解码缓存过大
  • JessibucaPro.ERROR.webglContextLostError ; webgl上下文丢失
  • JessibucaPro.ERROR.simdDecodeError ; simd 解码报错
  • JessibucaPro.ERROR.simdDecodeDelayTimeout ; simd 首帧解码超时
  • JessibucaPro.ERROR.tallWebsocketClosedByError ; 语音通讯websocket连接失败
  • JessibucaPro.ERROR.webglAlignmentError ; webgl 对齐错误
  • JessibucaPro.ERROR.wasmUseVideoRenderError ; wasm 使用 video 渲染失败(有些移动端浏览器不支持)
  • JessibucaPro.ERROR.mseAddSourceBufferError ; mse 添加缓存失败
  • JessibucaPro.ERROR.mseSourceBufferError ; mse 添加缓存失败
  • 还有更多错误信息,详见:JessibucaPro.ERROR

jessibucaPro.on("error", function (error, data) {
    if (error === JessibucaPro.ERROR.fetchError) {
        //
    } else if (error === JessibucaPro.ERROR.webcodecsH265NotSupport) {
        //
    }
    console.log('error:', error)
})

//或者
jessibucaPro.on(JessibucaPro.EVENTS.error, function (error, data) {
    if (error === JessibucaPro.ERROR.fetchError) {
        //
    } else if (error === JessibucaPro.ERROR.webcodecsH265NotSupport) {
        //
    }
    console.log('error:', error)
})

如配置了重播逻辑,播放器内部触发重播的同时,同样会触发error异常。

不推荐在error事件里面触发重播机制,推荐通过监听 playFailedAndPaused 事件

见:playFailedAndPaused

jessibucaPro.on("playFailedAndPaused", function (errorType, lastFrameInfo, msg) {
    console.log('playFailedAndPaused', errorType, msg);

    if(errorType === JessibucaPro.ERROR.fetchError) {
        console.log('fetchError')
    }
    else if(errorType === JessibucaPro.ERROR.websocketError) {
        console.log('websocketError')
    }
})

fetchError(废弃)

播放器播放的时候,http(s) 协议请求失败

  • 回调参数
    • {string} msg 错误信息

msg 是 Error.prototype.toString() 的返回值


jessibucaPro.on("fetchError", function (msg) {
    console.log('fetchError:', msg)
})

// 或者
jessibucaPro.on(JessibucaPro.ERROR.fetchError, function (msg) {
    console.log('fetchError:', msg)
})

如配置了重播逻辑(网络异常重连),播放器内部触发重播的同时,同样会触发fetchError异常。

不推荐在fetchError事件里面触发重播机制,推荐通过监听 playFailedAndPaused 事件

见:playFailedAndPaused

jessibucaPro.on("playFailedAndPaused", function (errorType, lastFrameInfo, msg) {
    console.log('playFailedAndPaused', errorType, msg);

    if(errorType === JessibucaPro.ERROR.fetchError) {
        console.log('fetchError')
    }
})

websocketError(废弃)

播放器播放的时候,websocket 请求失败

  • 回调参数
    • {string} msg 错误信息
jessibucaPro.on("websocketError", function (msg) {
    console.log('websocketError:', msg)
})

// 或者
jessibucaPro.on(JessibucaPro.ERROR.websocketError, function (msg) {
    console.log('websocketError:', msg)
})

如配置了重播逻辑,播放器内部触发重播的同时,同样会触发websocketError异常。

不推荐在websocketError事件里面触发重播机制,推荐通过监听 playFailedAndPaused 事件

见:playFailedAndPaused

jessibucaPro.on("playFailedAndPaused", function (errorType, lastFrameInfo, msg) {
    console.log('playFailedAndPaused', errorType, msg);

    if(errorType === JessibucaPro.ERROR.websocketError) {
        console.log('websocketError')
    }
})

kBps

当前码率

  • 回调参数
    • {number} data 当前码率

码率(kbps)与网速(KB/s)的区别

因为 1 Byte(字节)= 8 bits(比特)


jessibucaPro.on("kBps", function (data) {
    console.log('kBps:', data)
    // 如果想要转换成网速(KB/s)
    const speed = jessibucaPro.kbps2Speed(data)
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.kBps, function (data) {
    console.log('kBps:', data)
    // 如果想要转换成网速(KB/s)
    const speed = jessibucaPro.kbps2Speed(data)
})

start

渲染开始

暂停后再次播放,也会触发这个事件。

如果触发重播机制,也会触发这个方法。

start 事件会优先于 play 事件触发。

如果需要在 start 之后调用截图方法,需要写一个延迟方法去执行。因为代码中无法感应到画面被渲染出来了。

start 事件的效果等同于 play 事件


jessibucaPro.on("start", function () {
    console.log('start render')

    // 如果有截图需求。需要延迟一下,因为代码中无法感应到画面被渲染出来了。
    // 1s 之后截图
    setTimeout(function () {
        jessibuca.screenshot('xxx')
    }, 1 * 1000)
})

// 只想监听一次
jessibucaPro.once("start", function () {
    console.log('start render')
})

// 或者

jessibucaPro.on(JessibucaPro.EVENTS.start, function () {
    console.log('start render')
})

timeout

当设定的超时时间内无数据返回

  • 回调参数
    • {string} type timeout 类型,有:loadingTimeout,delayTimeout

jessibucaPro.on("timeout", function (type) {
    console.log('timeout:', type)
    if(type === 'loadingTimeout'){
        // loading timeout
    }
    else if(type === 'delayTimeout'){
        // delay timeout
    }
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.timeout, function (type) {
    console.log('timeout:', type)
    if(type === 'loadingTimeout'){
        // loading timeout
    }
    else if(type === 'delayTimeout'){
        // delay timeout
    }
})

loadingTimeout

当play()的时候,如果没有数据返回,则回调


jessibucaPro.on("loadingTimeout", function () {
    console.log('loadingTimeout')
})

// 或者

jessibucaPro.on(JessibucaPro.EVENTS.loadingTimeout, function () {
    console.log('loadingTimeout')
})

如配置了重播逻辑,播放器内部触发重播的同时,同样会触发loadingTimeout异常。

推荐playFailedAndPaused事件也可以监听到loadingTimeout事件。

当重试次数超过配置的loadingTimeoutReplayTimes,任然会触发loadingTimeout事件

jessibucaPro.on("playFailedAndPaused", function (errorType, lastFrameInfo, msg) {
    console.log('playFailedAndPaused', errorType, msg);

    if(errorType === JessibucaPro.ERROR.loadingTimeout) {
        console.log('loadingTimeout')
    }
})

loadingTimeoutRetryEnd

当loadingTimeout事件触发后,如果超过重试次数loadingTimeoutReplayTimes,则回调


jessibucaPro.on("loadingTimeoutRetryEnd", function () {
    console.log('loadingTimeoutRetryEnd')
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.loadingTimeoutRetryEnd, function () {
    console.log('loadingTimeoutRetryEnd')
})

推荐playFailedAndPaused事件也可以监听到loadingTimeoutRetryEnd事件。

jessibucaPro.on("playFailedAndPaused", function (errorType, lastFrameInfo, msg) {
    console.log('playFailedAndPaused', errorType, msg);

    if(errorType === JessibucaPro.EVENTS.loadingTimeoutRetryEnd) {
        console.log('loadingTimeoutRetryEnd')
    }
})

delayTimeout

当播放过程中,如果超过timeout之后没有数据渲染,则抛出异常。


jessibucaPro.on("delayTimeout", function () {
    console.log('delayTimeout')
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.delayTimeout, function () {
    console.log('delayTimeout')
})

如配置了重播逻辑,播放器内部触发重播的同时,同样会触发delayTimeout异常。

推荐playFailedAndPaused事件也可以监听到delayTimeout事件。

jessibucaPro.on("playFailedAndPaused", function (errorType, lastFrameInfo, msg) {
    console.log('playFailedAndPaused', errorType, msg);

    if(errorType === JessibucaPro.ERROR.delayTimeout) {
        console.log('delayTimeout')
    }
})

delayTimeoutRetryEnd

当delayTimeout事件触发后,如果超过重试次数,则回调

jessibucaPro.on("delayTimeoutRetryEnd", function () {
    console.log('delayTimeoutRetryEnd')
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.delayTimeoutRetryEnd, function () {
    console.log('delayTimeoutRetryEnd')
})

推荐playFailedAndPaused事件也可以监听到delayTimeoutRetryEnd事件。

jessibucaPro.on("playFailedAndPaused", function (errorType, lastFrameInfo, msg) {
    console.log('playFailedAndPaused', errorType, msg);

    if(errorType === JessibucaPro.ERROR.delayTimeoutRetryEnd) {
        console.log('delayTimeoutRetryEnd')
    }
})

playFailedAndPaused

当播放失败后,没有触发任何的重播机制,就会触发这个事件。

  • 回调参数
    • {string} errorType 错误类型,既变量EVENTS,ERROR里面的值
    • {Object} lastFrameInfo 最后一帧的画面
      • {string} loadingBackground 最后一帧的画面的base64内容
      • {number} loadingBackgroundWidth 最后一帧的画面的宽
      • {number} loadingBackgroundHeight 最后一帧的画面的高
    • {string} msg 详细的错误信息

playFailedAndPaused 事件只会触发一次。表示播放器真正的暂停播放了。

如果配置了播放器重播机制,触发重播的时候,不会触发playFailedAndPaused 事件。当重播次数用完了,就会触发playFailedAndPaused 事件。

对于websocket报错,fetch 报错,webrtc报错这种,都会走到playFailedAndPaused 事件里面。

jessibucaPro.on("playFailedAndPaused", function (errorType, lastFrameInfo, msg) {
    console.log('playFailedAndPaused', errorType, msg);

    if(errorType === JessibucaPro.ERROR.fetchError) {
        console.log('fetchError')
    }
    else if(errorType === JessibucaPro.ERROR.websocketError) {
        console.log('websocketError')
    }
    else if(errorType === JessibucaPro.EVENTS.loadingTimeoutRetryEnd) {
        console.log('loadingTimeoutRetryEnd')
    }


    // lastFrameInfo 是最后一帧的画面,可以用来重播的时候,显示最后一帧画面。

    // msg 具体的错误信息。
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.playFailedAndPaused, function (errorType, lastFrameInfo, msg) {
    console.log('playFailedAndPaused', errorType, msg);

    // lastFrameInfo 是最后一帧的画面,可以用来重播的时候,显示最后一帧画面。

    // msg 具体的错误信息。
})

对于reason 字段看 错误信息

fullscreen

当前是否全屏

  • 回调参数
    • {Boolean} flag 是否全屏

触发 webFullscreen 事件的时候,也会同时触发fullscreen 事件。

jessibucaPro.on("fullscreen", function (flag) {
    console.log('is fullscreen', flag)
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.fullscreen, function (flag) {
    console.log('is fullscreen', flag)
})

webFullscreen(废弃)

当前是否全屏(H5)

  • 回调参数
    • {Boolean} flag 是否全屏(H5)

推荐使用fullscreen事件

jessibucaPro.on("webFullscreen", function (flag) {
    console.log('is webFullscreen', flag)
})

//或者
jessibucaPro.on(JessibucaPro.EVENTS.webFullscreen, function (flag) {
    console.log('is webFullscreen', flag)
})

fullscreenError(废弃)

全屏失败

  • 回调参数
    • {string} error 错误内容

推荐通过监听error事件来监听

当没有触发任何交互的时候,调用全屏api,会触发这个事件。报错内容“Failed to execute 'requestfullscreen' on 'Element': APl can only be initiated by a user gesture. ”

jessibucaPro.on("fullscreenError", function (error) {
    console.log('fullscreenError', error)
})

play

触发播放事件

jessibucaPro.on("play", function () {
    console.log('play')
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.play, function () {
    console.log('play')
})

pause

触发暂停事件

jessibucaPro.on("pause", function () {
    console.log('pause')
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.pause, function () {
    console.log('pause')
})

mute

触发声音事件,返回boolean值

  • 回调参数
    • {boolean} flag 是否静音
jessibucaPro.on("mute", function (flag) {
    console.log('is mute', flag)
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.mute, function (flag) {
    console.log('is mute', flag)
})

stats

流状态统计,流开始播放后回调,每秒1次。

  • 回调参数
    • {Object} stats 统计数据

统计数据stats的字段

  • fps: 视频帧率(fps),
  • maxFps:视频峰值帧率(fps),
  • dfps:解码帧率(fps)
  • abps: 音频码率(bit)
  • vbps: 视频码率(bit)
  • audioBuffer:音频缓冲帧,
  • audioBufferDelayTs: 音频缓冲时长(audioBuffer * oneFrameDuration)
  • demuxBuffer: 视频待解码帧(直播流)
  • flvBuffer: 待解封装数据(byte)
  • isDropping: 是否丢帧
  • playbackVideoBuffer:视频待渲染(录像流)
  • playbackCacheDataDuration:缓存时长(ms)(录像流)
  • audioDemuxBuffer:音频待解码帧(直播流)
  • mseDelay:MSE缓冲时长(ms)
  • mseDecodeDiffTimes:MSE解码间隔(ms)
  • mseTs:MSE解码时间(ms)
  • mseDecodePlaybackRate:MSE播放模式(1:正常;>1 加速)
  • wcsDecodeDiffTimes:WCS解码间隔(ms)
  • hlsDelay:HLS缓冲时长(ms)
  • hlsDecodePlaybackRate:HLS播放模式(1:正常;>1 加速)
  • netBuf:网络延迟(ms)
  • buf: 缓存时长(ms) ,
  • pushLatestDelay:最新缓冲时长(ms)
  • ts:视频显示时间(ms)
  • currentPts:最新显示时间戳(ms)(最新渲染画面)
  • audioTs:音频显示时间(ms)
  • dts:视频解码时间(ms)
  • delayTs:解码前-解码后延迟(ms)
  • totalDelayTs:总延迟(网络+解码)(ms)
  • videoSmooth:视频是否播放流畅
  • performance:视频流畅度统计
  • pTs:当前播放器的播放时间(播放器自己计算的时间),每次从0开始,单位秒

在音频有的情况下: 可以通过 ts - audioTs 来计算出:音视频同步时间戳(ms)

performance 数据统计不如 videoSmooth 来的准确性高

jessibucaPro.on("stats", function (s) {
    console.log("stats is", s)
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.stats, function (s) {
    console.log("stats is", s)
})

如果是TF卡流(录像流),建议使用ts字段,这个字段是数据流里面的

performance

渲染性能统计,流开始播放后回调,每秒1次。

  • 回调参数
    • {number} performance 渲染性能统计结果,结果:0到3

只在直播流里面支持,录像(回放流)流不支持。

以25fps为标准,

// 四舍五入

25 * 0.33 = 8.25 -> 8
25*0.5 = 12.5 -> 13
25*0.83 = 20.75 -> 21
  • 0: 表示严重卡顿 ; 当 fps 小于 25*0.33 = 8.25 的时候。
  • 1: 表示明显卡顿 ;当 fps8.25-12.5 之间。
  • 2: 表示轻微卡顿 ; 当 fps12.5-20.75 之间。
  • 3: 表示流畅播放 ; 当 fps 大于 20.75 的时候。
jessibucaPro.on("performance", function (performance) {
    console.log("performance is", performance)
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.performance, function (performance) {
    console.log("performance is", performance)
})

这种检测方式只是作为参考,如果需要更精准的检测,可以使用 videoSmooth 事件。

recordStart

录制开始的事件

jessibucaPro.on("recordStart", function () {
    console.log("record start")
})

// 或
jessibucaPro.on(JessibucaPro.EVENTS.recordStart, function () {
    console.log("record start")
})

recordEnd

录制结束的事件

jessibucaPro.on("recordEnd", function () {
    console.log("record end")
})

// or
jessibucaPro.on(JessibucaPro.EVENTS.recordEnd, function () {
    console.log("record end")
})

recordBlob

调用录制结束,接收的二进制内容。

  • 回调参数
    • {blob} fileBlob 录制的二进制数据
jessibucaPro.stopRecordAndSave('blob')
jessibucaPro.once('recordBlob', (fileBlob) => {
    console.log(fileBlob)
})

// or
jessibucaPro.once(JessibucaPro.EVENTS.recordBlob, (fileBlob) => {
    console.log(fileBlob)
})

等同于:

jessibucaPro.stopRecordAndSave('blob').then((fileBlob) => {
    console.log(fileBlob)
})

recordCancel

录制取消的事件

jessibucaPro.on("recordCancel", function () {
    console.log("record cancel")
})

// or
jessibucaPro.on(JessibucaPro.EVENTS.recordCancel, function () {
    console.log("record end")
})

recordingTimestamp

录制的时候,返回的录制时长,1s一次

  • 回调参数
    • {number} timestamp 录制的时长,单位秒
jessibucaPro.on("recordingTimestamp", function (timestamp) {
    console.log("recordingTimestamp is", timestamp)
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.recordingTimestamp, function (timestamp) {
    console.log("recordingTimestamp is", timestamp)
})

recordCreateError

录制创建失败的事件

  • 回调参数
    • {string} error 错误信息
jessibucaPro.on("recordCreateError", function (error) {
    console.log("record create error")
})

// or
jessibucaPro.on(JessibucaPro.EVENTS.recordCreateError, function (error) {
    console.log("record create error")
})

playToRenderTimes

监听调用play方法 经过 初始化-> 网络请求-> 解封装 -> 解码 -> 渲染 一系列过程的时间消耗

  • 回调参数
    • {object} times 一系列阶段的时间戳

数据结构如下。

{
    playInitStart: '', //1 初始化时间戳
    playStart: '', // 2 开始请求流时间戳
    streamStart: '', //3 请求流时间戳
    streamResponse: '', // 4 请求流返回时间戳
    demuxStart: '', // 5 解封装时间戳
    decodeStart: '', // 6 解码时间戳
    videoStart: '', // 7 渲染时间戳
    playTimestamp: '',// playStart- playInitStart 从初始化到流开始请求的时间,(主要看decoder解码器的加载耗时)
    streamTimestamp: '',// streamStart - playStart 从开始请求流到真正的流请求的时间(主要看初始化播放器的)
    streamResponseTimestamp: '',// streamResponse - streamStart 从流请求开始到流响应的时间,(主要看流的请求响应耗时)
    demuxTimestamp: '', // demuxStart - streamResponse 从流响应到开始解封装开始的时间(主要看处理流数据的耗时)
    decodeTimestamp: '', // decodeStart - demuxStart 解封装开始到解码开始的时间,(主要看解封装耗时)
    videoTimestamp: '',// videoStart - decodeStart 从解码开始到首帧渲染的时间 (主要看解码耗时)
    allTimestamp: '' // videoStart - playInitStart 从初始化到首帧渲染的时间(看初始化到首帧渲染的总共耗时)
}

jessibucaPro.on("playToRenderTimes", function (times) {
    console.log("playToRenderTimes is", times)
})

// or
jessibucaPro.on(JessibucaPro.EVENTS.playToRenderTimes, function (times) {
    console.log("playToRenderTimes is", times)
})

videoSmooth

  • 回调参数
    • {boolean} videoSmooth 是否播放丝滑
    • {string} reasonvideoSmooth为false的时候的原因

原因有:

  1. vbpsIsZero,
  2. isDroppingIsTrue,
  3. fpsIsLow,
  4. videoCurrentTimeDiffIsNotNormal

对于解释

  • vbpsIsZero:这一秒的流数据为空
  • isDroppingIsTrue:这一秒有触发丢帧
  • fpsIsLow:这一秒的渲染fps低于正常fps的0.83倍 即:currentFps < fps *0.85
  • videoCurrentTimeDiffIsNotNormal:这一秒,video标签的渲染数据时长不是1s(可能和当前的机器性能有关系)。

视频流畅度统计(结合多个参数,vbps,是否丢帧、延迟、渲染的fps等),流开始播放后回调,每秒1次。

只在直播流里面支持,录像(回放流)流不支持。

jessibucaPro.on("videoSmooth", function (videoSmooth, reason) {
    console.log("is video smooth", videoSmooth, reason)
})

// 或者
jessibucaPro.on(JessibucaPro.EVENTS.videoSmooth, function (videoSmooth, reason) {
    console.log("is video smooth", videoSmooth, reason)
})

ptz

回调ptz 操作的方向

  • 回调参数
    • {string} ptz ptz 操作

ptz 类型有

  • up 方向上
  • right 方向右
  • down 方向下
  • left 方向左
  • leftUp 方向左上
  • leftDown 方向左下
  • rightUp 方向右上
  • rightDown 方向右下
  • stop 暂停
  • zoomExpand 镜头 +
  • zoomNarrow 镜头 -
  • apertureFar 聚焦 +
  • apertureNear 聚焦 -
  • focusFar 光圈 +
  • focusNear 光圈 -
  • fiStop 暂停(聚焦,光圈)

示例


jessibucaPro.on('ptz', (ptz) => {
    console.log(ptz)
})
//
jessibucaPro.on(JessibucaPro.EVENTS.ptz, (ptz) => {
    console.log(ptz)
})

streamQualityChange

切换分辨率的事件回调

  • 回调参数
    • {string} value 回调值,值是qualityConfig里面配置的值

示例

jessibucaPro.on('streamQualityChange', (value) => {
    // 这里的value就是qualityConfig里面配置的值。
    console.log(value)
})
//
jessibucaPro.on(JessibucaPro.EVENTS.streamQualityChange, (value) => {
    console.log(value)
})

close

在点击底部UI上面的x按钮,会触发播放器close事件 ,内部会销毁播放器。

由于 close 事件必须先抛出,然后执行的内部的destroy 方法(不然内部执行执行接触事件绑定,外部on方法就会失效掉的)

,所以需要在监听事件内部通过 setTimeout 方法之后(让destroy执行成功)再执行后续的业务代码,例如关闭流连接啥的等等

如果不在setTimeout之后执行,会出现意想不到的事情

jessibucaPro.on('close', () => {
    setTimeout(() => {
        // do some things
    }, 10)
})

// or
jessibucaPro.on(JessibucaPro.EVENTS.close, () => {
    setTimeout(() => {
        // do some things
    }, 10)
})

zooming

电子放大是否开启状态

  • 回调参数
    • {string} flag 是否开启电子放大
jessibucaPro.on('zooming', (flag) => {
    console.log('zooming status is', flag);
})

// or
jessibucaPro.on(JessibucaPro.EVENTS.zooming, (flag) => {
    console.log('zooming status is', flag);
})

crashLog

触发播放器重播的时候,会抛出错误信息,方便业务层做错误上报

  • 回调参数
    • {object} data 错误信息内容

主要收集的数据有

  • url: 播放地址
  • type: 错误的类型
  • error: 错误信息
  • playType : 播放类型
  • demuxType:解封装类型
  • decodeType:解码类型
  • renderType: 渲染类型
  • videoInfo : 视频信息 {width,height,encType}
  • audioInfo : 音频信息 {encType,channels,sampleRate}
  • audioEngine :音频引擎
  • allTimes :播放时长,单位秒
jessibucaPro.on('crashLog', (data) => {
    console.log('crashLog is', data);
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.crashLog, (data) => {
    console.log('crashLog is', data);
})

focus

播放器实例获取焦点(点击和右键)的时候触发的事件。

jessibucaPro.on('focus', () => {
    // do something
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.focus, () => {
    // do something
})

blur

播放器实例失去焦点的时候触发的事件。

jessibucaPro.on('blur', () => {
    // do something
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.blur, () => {
    // do something
})

visibilityHiddenTimeout

监听窗口不可见超时时间

jessibucaPro.on('visibilityHiddenTimeout', () => {
    // do something
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.visibilityHiddenTimeout, () => {
    // do something
})

visibilityChange

窗口可见性(隐藏/显示)变化的时候触发

  • 回调参数
    • {boolean} flag 错误信息内容

jessibucaPro.on('visibilityChange', (flag) => {
    if (flag === true) {
        // 窗口显示
    } else {
        // 窗口隐藏
    }
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.visibilityChange, (flag) => {
    if (flag === true) {
        // 窗口显示
    } else {
        // 窗口隐藏
    }
})

websocketOpen

该事件只有在使用websocket协议的时候才会触发

监听websocket连接成功(open)事件

jessibucaPro.on('websocketOpen', () => {
    // do something

    // 例如发送ws消息
    jessibucaPro.sendWebsocketMessage('hello world');
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.websocketOpen, () => {
    // do something

    // 例如发送ws消息
    jessibucaPro.sendWebsocketMessage('hello world');
})

websocketClose

该事件只有在使用websocket协议的时候才会触发

监听websocket关闭(close)事件

等同于 streamEnd 事件

jessibucaPro.on('websocketClose', () => {
    // do something
})

// or
jessibucaPro.on(JessibucaPro.EVENTS.websocketClose, () => {
    // do something
})

websocketStringMsg

该事件只有在使用websocket协议的时候才会触发

监听websocket接收到的string消息

  • 回调参数
    • {string} msg 接收到的消息内容
jessibucaPro.on('websocketStringMsg', (msg) => {
    console.log('websocketStringMsg is', msg);
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.websocketStringMsg, (msg) => {
    console.log('websocketStringMsg is', msg);
})

audioResumeState

当尝试做声音恢复的时候,会触发该事件,方便业务层做相关的处理

  • 回调参数
    • {string} state 当前的音频状态,值有:runningsuspended
    • {boolean} isRunning 是否 running 状态

isRunningtrue 或者检查 state 的值为running的时候,说明声音恢复成功了

jessibucaPro.on('audioResumeState', (value) => {
    if (value.isRunning === true || value.state === 'running') {
        // do something
    }
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.audioResumeState, (value) => {
    if (value.isRunning === true || value.state === 'running') {
        // do something
    }
})

networkDelayTimeout

当网络延迟超过networkDelay的时候,会触发该事件,方便业务层做相关的处理。

如果配置了networkDelayTimeoutReplay,则会自动重播。 事件也会抛出。

只要网络延迟超过networkDelay,就会触发该事件(频繁),所以建议使用once方法监听一次即可。

// 推荐once 监听一次即可。
jessibucaPro.once('networkDelayTimeout', () => {
    // do some things
})

// OR
jessibucaPro.once(JessibucaPro.EVENTS.networkDelayTimeout, () => {
    // do some things
})

webrtcOnConnectionStateChange

当使用webrtc协议的时候,监听webrtc连接状态变化的事件

  • 回调参数
    • {object} data 事件
jessibucaPro.on('webrtcOnConnectionStateChange', (data) => {
    console.log('webrtcOnConnectionStateChange is', data);
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.webrtcOnConnectionStateChange, (data) => {
    console.log('webrtcOnConnectionStateChange is', data);
})

webrtcOnIceConnectionStateChange

当使用webrtc协议的时候,监听webrtc ice连接状态变化的事件

  • 回调参数
    • {object} data 事件
jessibucaPro.on('webrtcOnIceConnectionStateChange', (data) => {
    console.log('webrtcOnIceConnectionStateChange is', data);
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.webrtcOnIceConnectionStateChange, (data) => {
    console.log('webrtcOnIceConnectionStateChange is', data);
})

videoSEI

监听 SEI 数据

  • 回调参数
    • {object} data sei 数据
      • {number} ts 流里面的时间戳
      • {Uint8Array} data sei 数据(实际负载数据Payload)
      • {Uint8Array} originData 原始sei数据(没有经过sei格式化过的数据)
      • {number} type 类型
      • {string} uuid uuid,当type为5的时候,会有uuid
      • {number} size sei数据的大小

type类型有

  • 1: pic_timing 时间同步
  • 5:user_data_unregistered 未注册的用户数据(带UUID)

SEI 的数据结构 [Header][Type][Size][UUID(可选)][实际负载数据(Payload)] 其中,Header是固定的,Type是SEI的类型,Size是SEI的大小,UUID是可选的,Payload是实际的数据。

如果Type是5的情况下,后面会跟着UUID,UUID是一个16字节的字符串,表示SEI的唯一标识符。

解封装器解析到 SEI 数据的时候,会触发该事件。和当前渲染的帧时间是不一一致的。 如果需要同步时间戳的,可以使用 videoSEISyncPts 事件。


jessibucaPro.on('videoSEI', (data) => {
    console.log(`videoSEI ts is ${data.ts}, type is ${data.type}, uuid is ${data.uuid}, data is ${data.data},originData is ${data.originData}`);
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.videoSEI, (data) => {
    console.log(`videoSEI ts is ${data.ts}, type is ${data.type}, uuid is ${data.uuid}, data is ${data.data},originData is ${data.originData}`);
})

videoSEISyncPts

监听 SEI 数据,同步 currentPts 时间戳 抛出的。

如果使用mse硬解码,并且流里面有大量的帧时间戳相同的情况,播放器在封装fmp4的时候,会纠正时间戳,这样就会导致误差会越来越大。最终会导致匹配不上。

可以配合videoSEISyncPtsDiff参数,来调整时间戳的差值。

  • 回调参数
    • {object} data sei 数据
      • {number} ts 流里面的时间戳
      • {Uint8Array} data sei 数据(实际负载数据Payload)
      • {Uint8Array} originData 原始sei数据(没有经过sei格式化过的数据)
      • {number} type 类型
      • {string} uuid uuid,当type为5的时候,会有uuid
      • {number} size sei数据的大小

等同于 videoSEI 事件,这个事件是同步pts的,会多个pts时间戳,表示当前正在渲染的帧时间戳。


jessibucaPro.on('videoSEISyncPts', (data) => {
    console.log(`videoSEISyncPts ts is ${data.ts}, pts is ${data.pts}, type is ${data.type}, uuid is ${data.uuid}, data is ${data.data},originData is ${data.originData}`);
    // 可以直接调用播放器的画框的功能,进行人脸或者物品的识别等操作。
    // 通过addContentToCanvas()方法来实现给视频添加人脸或者物品打框子。
    jessibucaPro.addContentToCanvas({
        //
    });
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.videoSEISyncPts, (data) => {
    console.log(`videoSEISyncPts ts is ${data.ts}, pts is ${data.pts}, type is ${data.type}, uuid is ${data.uuid}, data is ${data.data}`);
    // 可以直接调用播放器的画框的功能,进行人脸或者物品的识别等操作。
    // 通过addContentToCanvas()方法来实现给视频添加人脸或者物品打框子。
    jessibucaPro.addContentToCanvas({
        //
    });
})

decoderWorkerInitError(废弃)

监听解码器worker初始化失败的事件

  • 回调参数
    • {string} error 错误内容

例如配置的decoder参数不正确或者地址404,导致解码器worker初始化失败

该事件也会会触发playFailedAndPaused事件,推荐使用playFailedAndPaused事件来监听。

jessibucaPro.on('decoderWorkerInitError', (error) => {
    console.log('decoderWorkerInitError is', error);
})

// OR
jessibucaPro.on(JessibucaPro.ERROR.decoderWorkerInitError, (error) => {
    console.log('decoderWorkerInitError is', error);
})

推荐使用playFailedAndPaused事件来监听decoderWorkerInitError事件

jessibucaPro.on('playFailedAndPaused', (reason, lastFrameInfo, msg) => {
    console.log('playFailedAndPaused', reason, msg);

    if(reason === JessibucaPro.ERROR.decoderWorkerInitError) {
        console.log('decoderWorkerInitError')
    }
})

streamEnd

监听流结束(fetch 和 websocket )的事件

如果是 websocke 协议,会在 websocketClose 事件之后触发

如果是 fetch 协议,会在 fetch down事件之后触发

该事件也会会触发playFailedAndPaused事件


jessibucaPro.on('streamEnd', () => {
    console.log('streamEnd');
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.streamEnd, () => {
    console.log('streamEnd');
})

如配置了重播逻辑,播放器内部触发重播的同时,同样会触发streamEnd异常。

推荐使用playFailedAndPaused事件来监听streamEnd事件

jessibucaPro.on('playFailedAndPaused', (reason, lastFrameInfo, msg) => {
    console.log('playFailedAndPaused', reason, msg);

    if(reason === JessibucaPro.ERROR.streamEnd) {
        console.log('streamEnd')
    }
})

videoElementPlayingFailed(废弃)

监听video元素播放失败的事件

推荐监听playFailedAndPaused 事件来处理video元素播放失败的情况。

该事件只有在使用video元素渲染的时候才会触发

jessibucaPro.on('videoElementPlayingFailed', () => {
    console.log('videoElementPlayingFailed');
})

// OR
jessibucaPro.on(JessibucaPro.ERROR.videoElementPlayingFailed, () => {
    console.log('videoElementPlayingFailed');
})

如配置了重播逻辑,播放器内部触发重播的同时,同样会触发videoElementPlayingFailed异常。

推荐使用playFailedAndPaused事件来监听videoElementPlayingFailed事件

jessibucaPro.on('playFailedAndPaused', (reason, lastFrameInfo, msg) => {
    console.log('playFailedAndPaused', reason, msg);

    if(reason === JessibucaPro.ERROR.videoElementPlayingFailed) {
        console.log('videoElementPlayingFailed')
    }
})

videoElementPlayingFailedForWebrtc(废弃)

监听video元素播放失败的事件 (webrtc)

推荐监听playFailedAndPaused 事件来处理video元素播放失败的情况。

一般会在

jessibucaPro.on('videoElementPlayingFailedForWebrtc', () => {
    console.log('videoElementPlayingFailedForWebrtc');
})

// OR
jessibucaPro.on(JessibucaPro.ERROR.videoElementPlayingFailedForWebrtc, () => {
    console.log('videoElementPlayingFailedForWebrtc');
})

如配置了重播逻辑,播放器内部触发重播的同时,同样会触发videoElementPlayingFailedForWebrtc异常。

推荐使用playFailedAndPaused事件来监听videoElementPlayingFailedForWebrtc事件

jessibucaPro.on('playFailedAndPaused', (reason, lastFrameInfo, msg) => {
    console.log('playFailedAndPaused', reason, msg);

    if(reason === JessibucaPro.ERROR.videoElementPlayingFailedForWebrtc) {
        console.log('videoElementPlayingFailedForWebrtc')
    }
})

flvMetaData

监听flv元数据的事件.

  • 回调参数
    • {object} data flv元数据

当flv流中包含metadata数据的时候,会触发该事件、 播放器已经内部解析了metadata数据,所以业务层可以直接使用。

只针对flv流有效


jessibucaPro.on('flvMetaData', (data) => {
    console.log('flvMetaData', data);
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.flvMetaData, (data) => {
    console.log('flvMetaData', data);
})

currentPts

监听当前渲染帧的时间戳(流里面的)

  • 回调参数
    • {number} pts 时间戳

wasm(simd) 软解码、wcs硬解码能够严格的返回流里面的时间戳。

mse硬解码返回的时间戳是根据渲染的时间戳来计算的,所以会有一定的误差。

如果使用mse硬解码,并且流里面有大量的帧时间戳相同的情况,播放器在封装fmp4的时候,会纠正时间戳,这样就会导致误差会越来越大。


jessibucaPro.on('currentPts', (pts) => {
    console.log('currentPts', pts);
})

// OR
jessibucaPro.on(JessibucaPro.EVENTS.currentPts, (pts) => {
    console.log('currentPts', pts);
})

inView

当播放器出现在视口时触发

  • 回调参数
    • {boolean} flag 是否在视口
jessibucaPro.on('inView', (flag) => {
    console.log('inView', flag);
})

networkState

当前网络状态

  • 回调参数
    • {string} state 当前网络状态,值有:online,offline
jessibucaPro.on('networkState', (state) => {
    console.log('networkState', state);
})

volume

当前音量变化

  • 回调参数
    • {number} volume 当前音量,值从0-1
jessibucaPro.on('volume', (volume) => {
    console.log('volume change:', volume);
})

clickInitPlayer

点击初始化的时候play播放按钮


jessibucaPro.on('clickInitPlayer', () => {
    console.log('clickInitPlayer');
    // 可以调用play 方法进而播放
    jessibucaPro.play('your url');
})

tsPrivateData

监听ts流里面的私有数据

  • 回调参数
    • {Uint8Array} data 私有数据
jessibuca.on('tsPrivateData',(data)=>{

})