体验版的内置配置参数
体验版为了最大的提升体验,配置的参数会比较激进,所以会和正式版的默认配置参数会有一些差异。
业务可以根据自己实际情况,来调整配置参数。
{
decoderErrorAutoWasm: false, // 解码失败自动降级到 wasm 模式,设置为false,表示会继续尝试使用硬解码。正式版默认是true,会自动降级到wasm解码
supportHls265: true, // 强制走hls 自研265解码器。正式版如果是hls地址,默认走的是hls.js解码器,如果业务上面有软解码265需求,可以配置为true
mseDecodeAudio:true, // 强制使用mse解码音频。正式版默认是false,走的是wasm解码音频
wcsDecodeAudio:true, // 强制使用wcs解码音频。正式版默认是false,走的是wasm解码音频
nakedFlowDemuxUseNew: true, // 裸流解封装使用新的解封装逻辑。正式版默认是false,使用老的解封装逻辑
androidMobileFullscreenRotate: true, // 安卓手机全屏旋转屏幕。 正式版默认是false,不旋转屏幕(会出现安卓全屏的时候,画面不选择90度)
correctionConfigurationProfileIndication: true, // 修正hevc profile level。正式版默认是false,不会主动修正流数据异常情况。(业务上面如果有这种异常情况,可以配置true,但也有可能出现解码异常的情况)
correctionConfigurationVersion:true // 修正hevc version。正式版默认是false,不会主动修正流数据异常情况。(业务上面如果有这种异常情况,可以配置true,但也有可能出现解码异常的情况)
checkWebrtcLowFps: true, // 检测webrtc低fps。正式版默认是false,不检测低fps情况
playVodMp4UseSrc: true, // 播放vod mp4使用src方式播放。正式版默认是false,使用media source方式播放
waitingCheckFirstIframeTimeoutAutoWasmAndNoCheck: true, // 等待检查首帧超时自动降级到wasm并且不检查首帧。正式版默认是false,等待检查首帧超时,不会自动降级到wasm解码
playFailedAndPausedShowMessage: true, // 播放失败显示错误信息。正式版默认是false,不显示错误信息
isUseNewFullscreenWatermark: true, // 使用新的全屏水印逻辑。正式版默认是false,使用老的全屏水印逻辑
websocket1006ErrorReplay: true, // websocket 1006错误自动重试。正式版默认是false,不会自动重试,会走到playFailedAndPaused事件
networkDisconnectReplay: true, // 网络断开自动重试。正式版默认是false,不会自动重试,会走到playFailedAndPaused事件
loadingTimeoutRetryEndShowPlayBtn: true, // 加载超时重试结束显示播放按钮。正式版默认是false,不显示播放按钮
}
💡推荐配置方案建议💡
由于mse的兼容性比wcs要强,所以在http 或者https 环境下,都可以优先使用mse进行解码。
优先使用mse/wcs硬解码,如果不支持,降级到simd wasm解码,兜底使用wasm解码。
优先级 mse> wcs> simd wasm > wasm
{
// ---------- 硬解码参数-----------
useMSE: true,
useWCS: true, // 依赖https环境
// 音频参数
mseDecodeAudio:true, // 支持 aac/mp3
wcsDecodeAudio:true, // 依赖https环境 支持 aac/mp3/pcma/pcmu
// ---------- 硬解码参数-----------
// ---------- 软解码--------------
useSIMD:true,
autoWasm:true,// 自动降级到 wasm 模式
// ---------- 软解码--------------
isResize:false,// 拉伸全屏
videoBuffer:1, // 缓冲时长
videoBufferDelay:1, // 延迟时长(超过延迟会触发丢帧机制)
// 优化参数
demuxUseWorker:true, // worker进程解封装数据
mseDecoderUseWorker:true, // worker进程解码数据
}
如果希望硬解码报错的时候不降级到软解码,并且不黑屏,不出现loading效果
可能会播放过程中,存在流本身就会存在缺帧的情况(推流端没推完整),会导致mse或者wcs 解码报错。
{
replayUseLastFrameShow: true, // 重播使用上一帧显示
replayShowLoadingIcon: false,// 重播显示loading
decoderErrorAutoWasm: false, // 解码失败自动降级到 wasm 模式
}
可以配置使用硬解码来解音频数据,这样可以不加载wasm 来解码音频数据。
{
mseDecodeAudio:true, // 支持 aac/mp3
wcsDecodeAudio:true, // 支持 aac/mp3/pcma/pcmu
}
小结
function create(options, isReplay = false){
var jessibuca = new JessibucaPro({
container: 'player-container',// 必传
videoBuffer: 1,// 单位秒,如果是内网环境,可以设置更低些,比如0.3
videoBufferDelay: 1,// 单位秒 , 当累计延迟超过这个,会触发丢帧。如果网络不稳定的情况,可以设置高些,比如2,增大延迟,减少丢帧。
decoder:'', // 解码器地址,默认是请求根目录下面的 decoder-pro.js 文件。具体配置信息看api.html 下面的 decoder 参数配置。
isResize: false, // 画面会拉伸铺满整个container容器
// 当需要调试代码的时候,测试和生产环境不推荐配置为true,会影响性能和增加内存。
debug: true,
debugLevel: "debug",
// 硬解码 视频
useMSE: true,
useWCS: true, // 依赖https环境
// 硬解码 音频
mseDecodeAudio:true, // 支持 aac/mp3
wcsDecodeAudio:true, // 支持 aac/mp3/pcma/pcmu
// 硬解码不支持的时候降级到软解码,比如265解码不支持。
autoWasm:true,
useSIMD: true,// 优先使用simd wasm 解码,不支持会降级到wasm 解码
// 硬解码报错的时候,不降级到软解码,而是重置解码器,继续用硬解码播放。
decoderErrorAutoWasm: false,
demuxUseWorker: true, // 解封装数据使用worker进程,这样可以提升性能。
// 优先video标签渲染,多屏下性能要强于canvas(播放器默认配置的就是优先video渲染的)
useVideoRender:true,
useCanvasRender:false,
// 如果想在触发手动重播的时候(比如http 和ws 地址发生 错误或者断开,触发playFailedAndPaused事件,手动重置播放器的时候),不出现黑屏和loading的icon
loadingIcon: isReplay === true ? false : true,
//当播放器·内部发生重置·播放的时候,不希望出现黑屏和loading的icon
replayUseLastFrameShow: true, // 重播使用上一帧显示
replayShowLoadingIcon: false,// 重播显示loading
// 加载地址超时
loadingTimeout: 10, // 单位秒
loadingTimeoutReplay:true, // 超时重试
loadingTimeoutReplayTimes:3, // 重试次数 ,如果想无限次重试,可以设置-1
// 播放过程中没有流数据触发的超时(流地址没有断开)
heartTimeout: 10, // 单位秒
heartTimeoutReplay:true, // 超时重试
heartTimeoutReplayTimes:3, // 重试次数 ,如果想无限次重试,可以设置-1
// 解除静音
isNotMute: true, // 自动播放的情况下,是不会生效的,需要有交互的情况(浏览器认为的交互)下才会生效。
// 如果播放的地址是hls,且有265的情况下,推荐配置下这个参数
// supportHls265: true, // 支持hls265解码
// 如果贵公司的播放地址只能使用一次,因为播放器内部也会触发重播机制的,这个时候需要业务自己手动触发播放器的重播机制。
// playFailedAndReplay:true ,// 配置了这个参数,当播放器内部发生重播的时候,都会触发playFailedAndPaused事件,需要业务自己去做重播。
// 其他参数
...options,
})
}
mse(wcs) 在播放过程中解码报错的时候,不降级到wasm解码(仍然使用mse或者wcs解码)
可能会播放过程中,存在流本身就会存在缺帧的情况(推流端没推完整),会导致mse或者wcs 解码报错。
这边我们希望解码报错的时候,仍然使用mse或者wcs解码,而不是降级到wasm解码。
{
decoderErrorAutoWasm:false,
}
希望重置解码器的时候,不黑屏,不出现loading情况
{
replayUseLastFrameShow: true, // 重播使用上一帧显示
replayShowLoadingIcon: false,// 重播显示loading
}
监听请求流的失效(404、403等)或者500报错
监听playFailedAndPaused事件,来统一处理业务。
见 dist/demo-retry.html demo 页面实现
jessibucaPro.on('playFailedAndPaused',(reason, lastFrameInfo,error)=>{
// 业务可以重置播放器,然后重新播放 可以看下 demo-retry.html demo
})
关于移动端(H5)切换网络的时候(断网重连),播放器会触发什么事件。
见 dist/demo-retry.html demo 页面实现
关于播放器延迟(超过延迟触发丢帧)设置
目前播放器提供videoBuffer和videoBufferDelay两个参数来控制延迟。
对于videoBuffer参数(单位秒),是用来设置缓存的时长,啥意思呢?
就是播放器在接收流数据之后,并没有立马解码播放,还是等待缓存了
videoBuffer时长的数据之后才去按照一定的频率去解码->播放
在播放过程中,会根据新来流的时间戳结合本地的时间戳,实时计算当前的延迟时长,当延迟小于videoBufferDelay + videoBuffer ,则不做任何处理,继续 解码->播放。
当最新过来的流数据的时间戳,计算最新的延迟时长大于
videoBufferDelay + videoBuffer的时候,就会触发,丢帧机制。
关于网络延迟
对于网络延迟,是如何计算而来的呢?
当流过来的时候,本地也会同步的起一个时间线,因为是直播流,所以理论上如果没有网络延迟的情况下,1s的时间里面,流里面的数据也应该是1s的。
所以根据这个依据,当本地过了1s之后,如果计算的流的数据只有0.9s的话,那这1 - 0.9 = 0.1 的就是网络延迟。
播放器支持配置networkDelay参数(单位秒s),当播放器计算的网络延迟超过了预定设置的networkDelay 参数之后,当设置了networkDelayTimeoutReplay为true的时候,就会触发networkDelayTimeout事件。
业务可以通过监听
jessbucaPro.on(JessibucaPro.EVENTS.networkDelayTimeout, (ts) => {
// ts 就是网络超时的时间,单位ms(毫秒)
})
也有一种可能,就是在用软解码的时候,机器性能支持不了当前流的分辨率,会导致解码慢,因为单线程的缘故(堵塞响应),导致网络层接收流数据变慢,从而在解封装的时候,计算网络延迟的就会变大。
会出现本身延迟很低,但是网络延迟数据却很大
一般这种情况,会出现在机器是4g网络,然后机器向上推流的时候会存在丢帧的逻辑,但是时间戳的逻辑是不会变的,所以会出现这种情况。
比如机器的FPS是25,正常情况下,每秒会有25帧,然后每秒40ms的增加,这样一秒下来,25帧的时间戳就是1000ms。
但是如果存在丢帧的情况,比如丢帧了5帧,那么一秒就只会上传20帧的数据,但是还是每秒40ms的增加,这样一秒下来,20帧的时间戳就是800ms。这样就会少了200ms的数据。
然后结合播放器本地1s的时间,结合流里面的时间戳的时间,就会计算出200ms的网络延迟。
基于这种情况,网络延迟的数据,只是一个参考值,不是绝对的。
配置低延迟(300ms)解决方案建议【直播流】
看 dist/demo-low-delay.html 实现
因为超低延迟,对于mse 和wcs并不能做到这么低的延迟方案,所以推荐使用wasm simd来实现。
推荐的配置方案:
{
useMSE:false,
useWCS:false,
videoBuffer:0.1,
videoBufferDelay:0.2,
useSIMD: true,
}
如果需要更低的延迟,可以使用videoBufferDelay来配置延迟时间,单位是秒。
崩溃日志上报
当播放器播放失败,或者崩溃重新播放的时候,会触发crashLog事件,可以监听这个事件,来上报崩溃日志。
可以监听crashLog事件
jessibuca.on('crashLog', (data) => {
})
返回的数据有:
- url: 播放地址
- error: 错误信息
- playType : 播放类型
- demuxType:解封装类型
- decodeType:解码类型
- renderType: 渲染类型
- videoInfo : 视频信息 {width,height,encType}
- audioInfo : 音频信息 {encType,channels,sampleRate}
- audioEngine :音频引擎
- allTimes :播放时长,单位秒
方便业务拿到数据进行数据上报。
页面最小化(切换tab)超时检测建议
一般业务有需要监听页面最小化,或者切换tab的事件,来关闭播放器播放,并提示用户。
可以通过设置pageVisibilityHiddenTimeout 参数,单位秒,目前默认值是5 * 60 5分钟。
// 配置信息:
{
pageVisibilityHiddenTimeout: 5 * 60
}
通过监听visibilityHiddenTimeout事件,来进行业务逻辑处理。
player.on('visibilityHiddenTimeout', function () {
// 窗口不可见5分钟超时
});
播放地址首次就请求失败(非超时)
根据自己的业务播放的url地址类型,来监听对应的错误事件。
监听playFailedAndPaused事件
见 dist/demo-retry.html demo 页面实现
jessibucaPro.on(JessibucaPro.EVENTS.playFailedAndPaused, (error, frameInfo, msg) => {
if (error === JessibucaPro.ERROR.fetchError) {
// http-flv 错误
} else if (error === JessibucaPro.ERROR.websocketError) {
// ws-flv 错误
}
})
语音通讯集成
具体集成的demo 可以看 dist/talk-demo.html文件
需要单独引用
jessibuca-pro-talk.js文件
单视频播放
只需要将
hasAudio设置为false即可, 播放器就不会解码音频流。
单音频播放
具体集成的demo 可以看 dist/only-audio-demo.html文件
只需要将
hasVideo设置为false即可, 播放器就不会解码视频流。
推荐使用单独的音频播放器(jessibuca-pro-audio-player.js),因为音频播放器的性能会更好。
纯音频播放器
纯音频播放器里面砍掉了和视频相关的逻辑,非常的轻量,并且可以支持移动端(IOS 和安卓)后台和息屏播放 。
页面需要引入jessibuca-pro-audio-plauer.js文件
具体集成demo 可以看 audio-player-demo.html文件
配置自定义底部UI按钮
只需要配置extendOperateBtns参数即可
看 dist/demo-control-btn.html 页面
配置右键菜单
只需要配置contextmenuBtns参数即可
看 dist/demo-control-dom.html 页面
jessibuca-pro.js decoder-pro.js(decoder-pro-simd.js) decoder-pro.wasm(decoder-pro-simd.wasm) 等文件想通过CDN加载
因为默认情况下 decoder-pro.js(decoder-pro-simd.js) 是通过相对路径引入 decoder-pro.wasm(decoder-pro-simd.wasm) 文件的。
如果想引用CDN的地址,需要修改成CDN的绝对地址。
所以如果想通过CDN加载,需要修改decoder-pro.js(decoder-pro-simd.js)文件
需要配置decoder 参数为CDN绝对地址文件。
最新版本已经支持了通过配置 rollup.config.js 来实现修改
decoder-pro.js和decoder-pro-simd.js文件。
jessibuca-pro.js decoder-pro.js(decoder-pro-simd.js) decoder-pro.wasm(decoder-pro-simd.wasm) 需要放在同一个目录下。
只需要配置
const jessibucaPro = new JessibucaPro({
decoder: 'https://your-cdn.com/decoder-pro.js',
isDecoderUseCDN: true,
...
})
然后在 rollup.config.js 里面
replace({
exclude: 'node_modules/**',
__ENV__: JSON.stringify(process.env.NODE_ENV || 'development'),
__VERSION__:JSON.stringify(version),
__BUILD_DAY__:JSON.stringify(buildDay),
__TIMEOUT__:JSON.stringify(1),
// wasm
// JESSIBUCA_PRO_WASM_URL:JSON.stringify('https://jessibuca.com/pro-cdn-https/decoder-pro.wasm'),
// simd wasm
// JESSIBUCA_PRO_SIMD_WASM_URL:JSON.stringify('https://jessibuca.com/pro-cdn-https/decoder-pro-simd.wasm'),
// ffmpeg simd wasm
// JESSIBUCA_PRO_F_SIMD_WASM_URL:JSON.stringify('https://jessibuca.com/pro-cdn-https/decoder-pro-f-simd.wasm'),
// audio wasm
// JESSIBUCA_PRO_AUDIO_WASM_URL:JSON.stringify('https://jessibuca.com/pro-cdn-https/decoder-pro-audio.wasm'),
// wasm mt
// JESSIBUCA_PRO_MT_WORKER_WASM_URL:JSON.stringify('https://jessibuca.com/pro-cdn-https/decoder-pro-mt-worker.wasm'),
// JESSIBUCA_PRO_MT_WORKER_JS_URL:JSON.stringify('https://jessibuca.com/pro-cdn-https/decoder-pro-mt-worker.worker.js'),
// wasm simd mt
// JESSIBUCA_PRO_SIMD_MT_WORKER_WASM_URL:JSON.stringify('https://jessibuca.com/js/pro-cdn-https/decoder-pro-simd-mt-worker.wasm'),
// JESSIBUCA_PRO_SIMD_MT_WORKER_JS_URL:JSON.stringify('https://jessibuca.com/js/pro-cdn-https/decoder-pro-simd-mt-worker.worker.js'),
// wasm ffmpeg simd mt
// JESSIBUCA_PRO_F_SIMD_MT_WORKER_WASM_URL:JSON.stringify('https://jessibuca.com/pro-cdn-https/decoder-pro-f-simd-mt-worker.wasm'),
// JESSIBUCA_PRO_F_SIMD_MT_WORKER_JS_URL:JSON.stringify('https://jessibuca.com/pro-cdn-https/decoder-pro-f-simd-mt-worker.worker.js'),
// wasm old wasm
// JESSIBUCA_PRO_OLD_WASM_URL:JSON.stringify('https://jessibuca.com/pro-cdn-https/decoder-pro-old.wasm'),
})
只需要把
- JESSIBUCA_PRO_WASM_URL
- JESSIBUCA_PRO_SIMD_WASM_URL
- JESSIBUCA_PRO_F_SIMD_WASM_URL
- JESSIBUCA_PRO_AUDIO_WASM_URL
- JESSIBUCA_PRO_MT_WORKER_WASM_URL
- JESSIBUCA_PRO_MT_WORKER_JS_URL
- JESSIBUCA_PRO_SIMD_MT_WORKER_WASM_URL
- JESSIBUCA_PRO_SIMD_MT_WORKER_JS_URL
- JESSIBUCA_PRO_F_SIMD_MT_WORKER_WASM_URL
- JESSIBUCA_PRO_F_SIMD_MT_WORKER_JS_URL
- JESSIBUCA_PRO_OLD_WASM_URL
并修改为贵公司的CDN地址即可。
然后执行npm run build 命令 就可以了。
限制js的使用域名和限制播放url的域名
可以看下utils文件夹下面的verify.js文件。
对于host的生成,可以看下utils文件夹下面的string2CharCodeHex.js文件。
然后可以通过在 jessibuca.js的 play() 方法里面添加判断逻辑。
//
// todo:这里校验url地址是否合法
if(!verify(url)){
reject('url is not valid');
return ;
}
// todo:这里校验当前页面是否合法
if (!verifyCurrentPage()) {
reject('current page is not valid');
return;
}
关于自定义按钮和系统默认提供的按钮
一般现在的问题:
- 系统自带的按钮顺序和icon不满足业务系统
- 系统自带的按钮的功能不满足业务系统
- 希望使用自带的按钮样式和功能(排序也有要求)
解决方案:
看 dist/demo-control-btn.html 页面
如果是按钮的功能不满足业务需求,可以通过配置playFn,pauseFn 等方法来配置自定义的方法、
如果不想要系统提供的按钮,可以通过配置extendOperateBtns 参数来配置、支持设置index,icon ,active icon , click , active click 等参数
关于性能面板
在调试过程中,性能面板是一个非常重要的一个东西,上面显示的是流的实时的数据。
可以通过配置
{
showPerformance:true, // 直接显示性能面板数据
operateBtns:{
performance:true // 底部控制条按钮
}
}
方法
jessibuca.togglePerformancePanel() // 切换性能面板显示
jessibuca.togglePerformancePanel(true) // 开
jessibuca.togglePerformancePanel(false) // 关
关于日志输出
关于日志,是主要是控制台输出的内容,可以通过配置debug:true 来打开日志输出。
不管是否配置了
debug:true,error的日志默认是强制直接输出的。
默认显示的日志级别是warn,可以通过配置debugLevel:'debug' 讲日志级别调成全量模式。
如果是多屏的输出,可以通过配置
isMulti:true来配置播放多实例模式。这个模式下,日志输出会有[uuid] 来区分各个实例日志。
关于水印
全屏水印
全屏水印指的是:播放器整个播放窗口重复显示水印。
可以通过参数fullscreenWatermarkConfig 来实现全屏水印,仅支持文字
局部水印
支持:图片 和 文字和 自定义HTML
可以通过配置watermarkConfig 来实现局部水印。
动态水印
支持文字
通过配置dynamicWatermarkConfig 来实现动态水印
看 dist/demo-dynamic-watermark.html 页面
幽灵水印
支持文字
通过配置ghostWatermarkConfig 来实现动态水印
看 dist/demo-dynamic-watermark.html 页面
使用那种标签渲染
见 dist/demo.html 页面
目前播放器支持video 和canvas两种标签渲染
可以通过参数 useVideoRender 和 useCanvasRender 来配置
播放器默认的是使用video标签渲染
当两者同时设置为true的时候,video的标签渲染优先级大于canvas。
video标签渲染性能要比canvas标签渲染性能要好。
canvas标签渲染会存在webgl丢失的情况。窗口被最小化、系统进入睡眠模式等用户操作都有可能导致WebGL上下文丢失。
对于chrome、edge等浏览器,webgl的上限是16个。
关于视频录制
目前播放器支持录制 mp4 和 webm 、flv 格式的视频
mp4 只支持录制视频
webm 格式支持录制视频和音频(音频需要在打开声音的状态才能被录制进去)
flv 格式支持录制视频和音频(静音状态下也能录制音频)
mp4 wasm 录制支持音频+视频
看 demo/demo-record.html 页面
关于录制mp4文件,并且要支持音频+视频
可以用扩展模块 wasm mp4录制模块来实现
视频支持的编码格式:h264、h265、
音频支持的编码格式:aac、mp3、
添加微信:bosswancheng 咨询
关于出现绿屏或者花屏的时候
如果流数据的首帧不是I帧,一般情况下,解码了之后,就会很容易出现绿屏或者花屏情况。
播放器支持配置检查首帧是否是I帧,如果不是I帧就直接过滤掉,直到等到I帧出现才开始解码流数据
只需要配置checkFirstIFrame:true
默认播放器就是设置为true的,不建议修改为false
如果本身流就是特殊的流,能够保证解码出来的画面不是花屏的,就可以设置为false
关于音频引擎
目前播放器支持三种音频引擎来播放音频数据,worklet、script、active
目前播放器会根据当前用户的实际情况来动态选择最适合的播放引擎。
会优先判断是否在
微信安卓环境
worklet
必须是https 环境下,配置才会生效。
默认https环境下,默认就是这个播放引擎。
script
兼容性最高的播放引擎。
一般情况下都是这种引擎。
active
为了支持在安卓的微信环境播放,特殊实现的一种播放引擎。
其他环境不建议使用这个引擎。
ptz 操作
看 dist/demo-ptz.html 页面
ptz是执行国标gb28181的ptz操作,目前支持的操作有:上下左右,左上,右上,左下,右下,缩放+-,光圈+-,聚焦+-,巡航开关,透雾开关,雨刷开关。
步骤:
- 点击播放器上面的ptz按钮。
- 通过监听事件
ptz来获取到对应的事件。 - 通过调用服务器端的接口来实现ptz操作。
支持的配置参数:
new JessibucaPro({
// 其他参数
ptzClickType: 'click | mouseDownAndUp', // ptz操作的交互方式
ptzStopEmitDelay: 0.3, // ptz操作停止后,延迟多久触发停止事件
ptzZoomShow: true, // 是否显示ptz的缩放按钮
ptzApertureShow: true, // 是否显示ptz的光圈按钮
ptzFocusShow: true, // 是否显示ptz的聚焦按钮
ptzMoreArrowShow: true, // 是否显示ptz的更多按钮(左上,右上,左下,右下)
//其他ptz参数
})
支持的事件:
jessibucaPro.on(JessibucaPro.EVENTS.ptz, function (data) {
console.log('ptzStart', data)
})
目前ptz操作支持两种交互方式click 和mouseDownAndUp, 可以通过配置ptzClickType: click | mouseDownAndUp 参数。
click
鼠标点击事件
可以通过配置ptzStopEmitDelay参数来配置ptz操作停止后,延迟多久触发stop停止事件。
mouseDownAndUp
鼠标按下,和松开 分别触发事件。
配置额外的按钮(更多方向、镜头、聚焦、光圈)
可以通过配置参数ptzMoreArrowShow, ptzZoomShow,ptzApertureShow,ptzFocusShow 等配置来配置是否显示额外的按钮。
ptz国标指令
目前播放器内部已经封装好了国标指令,可以通过getPTZCmd(cmd,speed)来获取封装过的指令集合
jessibuca.on('ptz', (arrow) => {
console.log('ptz', arrow);
const ptzCode = jessibuca.getPTZCmd(arrow)
console.log('ptzCode', ptzCode);
})
加密流播放
具体看加密流demo
m7s加密流(H264/H265)
看 dist/crypto-m7s-demo.html 页面
国标SM4加密流(H264/H265)
看 dist/crypto-sm4-demo.html 页面
XOR加密流(H264/H265)
看 dist/crypto-xor-demo.html 页面
关于集成语音通讯
见 dist/talk-demo.html 页面
整体逻辑
- 浏览器端采集麦克风数据
- 将麦克风数据(rtp包)发送给服务端
- 服务器端将麦克风数据(rtp包)转发给摄像头
- 摄像头播放声音
目前支持单独或者集成在播放器中使用语音通讯
单独使用需要单独引用jessibuca-pro-talk.js文件
目前语音通讯支持采集pcm、g711a、g711u、格式的数据,支持封装成rtp包格式。
并支持checkGetUserMediaTimeout 和 getUserMediaTimeout 参数用来检测获取getUserMedia 超时
需要监听websocket的事件和调用send 方法
会存在私有的websocket请求,需要授权才能播放,就需要监听websocket的open事件和调用send 方法。
为此,播放器提供了websocketOpen 事件和 sendWebsocketMessage 方法。
jessibucaPro.on(JessibucaPro.EVENTS.websocketOpen, function () {
console.log('websocket open')
// 在这里可以做授权的逻辑
jessibucaPro.sendWebsocketMessage('授权的消息')
})
手机端全屏
播放器内部会判断如果检测到浏览器不支持系统级别全屏API的时候,会自动把
webFullscreen配置为true,全屏的时候,会旋转屏幕。
可以通过配置
androidMobileFullscreenRotate:true来设置安卓手机全屏的时候,是否旋转屏幕
见 dist/mobile-demo.html 页面
多屏播放
可以使用jessibuca-pro-multi.js 来实现多屏播放。
具体demo 看
dist/multi-demo.html文件
如果引用了
jessibuca-pro-multi.js,那么jessibuca-pro.js就不需要引用了。
gzip 压缩资源文件
可以通过gzip压缩资源文件,来减少资源文件的大小。
mac(linux)
安装gzip
https://formulae.brew.sh/formula/gzip
jessibuca-pro.js
gzip jessibuca-pro.js
mv jessibuca-pro.js.gz jessibuca-pro.js
decoder-pro.js
gzip 和decoder-pro.js
mv 和decoder-pro.js.gz 和decoder-pro.js
decoder-pro.wasm
gzip 和decoder-pro.wasm
mv 和decoder-pro.wasm.gz 和decoder-pro.wasm
decoder-pro-simd.js
gzip 和decoder-pro-simd.js
mv 和decoder-pro-simd.js.gz 和decoder-pro-simd.js
decoder-pro-simd.wasm
gzip 和decoder-pro-simd.wasm
mv 和decoder-pro-simd.wasm.gz 和decoder-pro-simd.wasm
windows
安装gzip
http://gnuwin32.sourceforge.net/downlinks/gzip-bin-zip.php
解压后,将 jessibuca-pro.js 和 decoder-pro.js和 decoder-pro.wasm 和 decoder-pro-simd.js和 decoder-pro-simd.wasm 文件拖到 gzip.exe上,文件就压缩好了,也需要去掉.gz后缀
配置HTTP头
对于js文件 需要配置Content-Encoding: gzip,Content-Type: text/javascript
对于wasm文件,需要配置Content-Encoding: gzip,Content-Type: application/wasm
如何配置底部自定义按钮(事件)
见dist/demo-control-btn.html 页面
自定义按钮
通过extendOperateBtns配置来配置底部自定义按钮
自定义事件
目前播放器支持通过方法 toggleControlExtendBtn(name, isActive) 来切换自定义按钮的 默认状态和 激活状态。
支持通过getControlExtendBtnActive(name) 方法,支持获取控制栏扩展按钮的激活状态。
初始化的时机
目前播放器支持配置自定义按钮的显示时机,支持created,loading,playing 三个阶段配置
- created: 播放器创建完成之后,就会显示自定义按钮
- loading: 播放器开始加载流数据的时候,就会显示自定义按钮
- playing: 播放器开始播放的时候,就会显示自定义按钮
播放器默认的是
playing阶段显示自定义按钮
异步加载js文件
有客户不想通过script标签来加载js文件,而是想通过异步加载js文件的方式来加载。
可以通过loadJs方法来实现。
具体demo见:async-demo.html
如果业务层需要自己处理播放异常逻辑。
会存在客户的流,在一次播放之后,就没法再使用了。所以需要在播放异常的时候,重新请求流的地址。
需要客户把一些参数都关闭掉,不能触发播放器自己内部的重播。
// 推荐使用
{
playFailedAndReplay:false
}
播放器内部会统一的把原子化的replay 参数设置为 false。
可以通过监听playFailedAndPaused事件来监听。
然后后续操作:
- 销毁播放器
- 重新建立播放器
- 调用play()方法
支持重播的时候
var jessibucaPro = null;
//
function createPlayer(options,isReplay = false) {
jessibucaPro = new JessibucaPro({
// 其他参数
...options,
// 重播的时候,不显示loadingicon
loadingIcon:isReplay === true ? false : true,
// 异常导致内部重播的时候显示最后一帧。
replayUseLastFrameShow:true,
// 异常导致内部重播的时候不显示loadingicon
replayShowLoadingIcon: false,
})
// 监听事件
jessibucaPro.on("playFailedAndPaused", function (error,frameInfo) {
// 重播的时候,不希望出现黑屏,就将 frameInfo 传入。
resetPlayer(frameInfo).then(()=>{
// 延迟2秒之后,重新播放
setTimeout(()=>{
jessibucaPro.play('播放地址');
},2*1000)
});
})
}
// 重置播放器
function resetPlayer(options) {
return new Promise((resolve, reject)=>{
jessibucaPro.destroy().then(() => {
jessibucaPro = null;
createPlayer(options,true);
resolve();
})
})
}
// 创建播放器、
createPlayer({});
多屏需求
如果不需要播放音频
可以设置hasAudio为false,这样就不会解码音频数据了,可以提升性能。
只需要硬解码的话
可以通过设置
// 只需要配置下这个参数就行。
decoderErrorAutoWasm:false,
这样mse(wcs) 解码报错的时候,不降级到wasm解码(仍然使用mse或者wcs解码)。
确保当前环境支持mse(wcs),H264、H265解码。不然就直接播放失败了。
理解 loadingTimeout 和 delayTimeout 和 loadingTimeoutRetryEnd 和 delayTimeoutRetryEnd事件
loadingTimeout和delayTimeout事件 每次都会触发在配置了
heartTimeoutReplay或者loadingTimeoutReplay的情况下,播放器内部 会自动重播。当重播次数达到了
loadingTimeoutReplayTimes或者heartTimeoutReplayTimes的时候,会触发loadingTimeoutRetryEnd或者delayTimeoutRetryEnd事件。
所以如果业务逻辑需要在检测到重连次数结束之后,需要做一些事情,可以监听
loadingTimeoutRetryEnd或者delayTimeoutRetryEnd这两个事件。
7*24小时播放需求(支持断网重连)
看 dist/demo-retry.html 文件
目前播放器支持很多业务场景配置重播逻辑。具体参数可以看
dist/demo-retry.htmldemo 页面。
如果需要重播(内部)或网络断开手动触发重播的时候画面停留在失败前最后一帧(支持配置是否显示loading画面)
看 dist/demo-retry.html 文件
目前播放器支持的配置网络异常的参数有
websocket1006ErrorReplay:true, // websocket 1006错误重播
目前播放器内部会触发重播,还有通过监听playFailedAndPaused事件的重播。如果想要这两种重播的时候,显示最后一帧画面,并且想要不出现loading的icon。
首先:
replayUseLastFrameShow:true
目前默认是true的。不需要额外再设置了。
如果希望重播的时候,不出现loading画面,需要再配置下
replayShowLoadingIcon:false
如果触发了http 网络断开,或者websocke网络断开的业务场景。
在手动触发重播的时候,不希望出现黑屏。
// 看 `dist/demo-retry.html` 文件
var jessibucaPro = null;
//
function createPlayer(options,isReplay = false) {
jessibucaPro = new JessibucaPro({
// 其他参数
...options,
// 重播的时候,不显示loadingicon
loadingIcon:isReplay === true ? false : true,
// 异常导致内部重播的时候显示最后一帧。
replayUseLastFrameShow:true,
// 异常导致内部重播的时候不显示loadingicon
replayShowLoadingIcon: false,
})
// 监听事件
jessibucaPro.on("playFailedAndPaused", function (error,frameInfo) {
// 重播的时候,不希望出现黑屏,就将 frameInfo 传入。
resetPlayer(frameInfo).then(()=>{
// 延迟2秒之后,重新播放
setTimeout(()=>{
jessibucaPro.play('播放地址');
},2*1000)
});
})
}
// 重置播放器
function resetPlayer(options) {
return new Promise((resolve, reject)=>{
jessibucaPro.destroy().then(() => {
jessibucaPro = null;
createPlayer(options,true);
resolve();
})
})
}
// 创建播放器、
createPlayer({});
某些情况下,因为重置播放器的时候,是一个异步的过程,所以可能会出现画面闪烁下的情况。
如果是多屏需求(硬解码)
异常之后仍然使用硬解码
// 只需要配置下这个参数就行。
decoderErrorAutoWasm:false,
结合SEI数据+ currentPts/videoSEISyncPts事件+ addContentToCanvas()方法 实现给视频添加人脸或者物品打框子。
见 dist/demo-sei.html 文件
打框子的数据是通过流里面的SEI数据来获取到的,业务可以通过监听videoSEI事件来获取到SEI数据,然后缓存在数组里面。
jessibucaPro.on('videoSEI', (data) => {
console.log(`videoSEI ts is ${data.ts}, data is ${data.data}`);
const decoder = new TextDecoder(); // 创建一个 TextDecoder 对象
const str = decoder.decode(data.data);
console.log(str); // 解析出来sei的数据。
// 可以利用数组接收
seiList.push(data);
})
通过监听currentPts事件
推荐监听监听
videoSEISyncPts事件,播放器内部处理了sei数据与pts时间同步的问题。
jessibucaPro.on('currentPts',(ts)=>{
const diff = 200 // ms
const min = ts - diff;
const max = ts + diff;
const tsSeiList = [];
seiList.forEach((item)=>{
if(item.ts >= min && item.ts <= max){
tsSeiList.push(item);
}
})
tsSeiList.forEach((seiItem)=>{
// 通过addContentToCanvas()方法来实现给视频添加人脸或者物品打框子。
jessibucaPro.addContentToCanvas({
//
});
})
// 将无效的数据扔掉
seiList = dataList.filter((item) => {
return item.ts > max;
})
})
或者直接监听videoSEISyncPts事件。
播放器内部处理了sei数据与pts时间同步的问题。
jessibucaPro.on('videoSEISyncPts', (data) => {
// 通过addContentToCanvas()方法来实现给视频添加人脸或者物品打框子。
jessibucaPro.addContentToCanvas({
//
});
})
结合单独的ws接口 + currentPts事件+ addContentToCanvas()方法 实现给视频添加人脸或者物品打框子。
某些业务场景的元数据是从单独的ws接口同步获取到的。
const dataList = [];
// 业务系统通过监听ws.onmessage事件来获取到元数据
ws.onmessage = function (event) {
// 存储起来
dataList.push(event.data);
}
通过监听currentPts事件
jessibucaPro.on('currentPts', (ts) => {
const diff = 200 // ms
const min = ts - diff;
const max = ts + diff;
const tsSeiList = [];
seiList.forEach((item) => {
if (item.ts >= min && item.ts <= max) {
tsSeiList.push(item);
}
})
tsSeiList.forEach((seiItem) => {
// 通过addContentToCanvas()方法来实现给视频添加人脸或者物品打框子。
jessibucaPro.addContentToCanvas({
//
});
})
// 将无效的数据扔掉
seiList = dataList.filter((item) => {
return item.ts > max;
})
})
实时监听视频是否卡顿
通过监听videoSmooth事件来实现。
jessibucaPro.on(JessibucaPro.EVENTS.videoSmooth, function (videoSmooth, reason) {
console.log("is video smooth", videoSmooth, reason)
})
第二个参数就是啥原因导致的卡顿。
视频录制是否可以支持水印(图片,或者文字)
不支持录制有水印的视频。
因为如果视频需要增加水印的话,需要每一帧重新编码(裸流+水印),经历
解码+加水印+然后编码过程。而且非常吃性能,不推荐在客户端做这个。
配置分辨率,支持切换分辨率的时候切换播放地址。
例如目前需求有 720P——1280*720——HD(高清) 和 1080P——1920*1080——FHD(全高清) 两种分辨率。
在初始化播放的时候配置
const jessibuca = new JessibucaPro({
// 其他参数
qualityConfig:['高清','全高清'],
})
然后用户在切换UI上面的分辨率的时候,通过监听事件streamQualityChange,
jessibuca.on(JessibucaPro.EVENTS.streamQualityChange,(value)=>{
if(value === '高清'){
jessibuca.play('高清的播放地址');
}
else if(value === '全高清'){
jessibuca.play('全高清的播放地址');
}
})
关于集成webrtc
见 dist/demo-webrtc.html 页面
M7S
M7S的webrtc地址:
webrtc://localhost:8080/webrtc/play/live/test
注意 'live/test' 是streamPath
见 dist/demo-webrtc.html 页面
SRS
SRS的webrtc地址:
webrtc://127.0.0.1/live/livestream
注意:将SRS的path前面拼接个/rtc/v1/play/就可以了即:
webrtc://r.ossrs.net/rtc/v1/play/live/livestream
见 dist/demo-webrtc.html 页面
ZLM
ZLM的webrtc地址:
http://127.0.0.1/index/api/webrtc?app=live&stream=test&type=play
注意:将zlm的webrtc播放地址,https:// 修改为 webrtc:// 就可以了即:
webrtc://127.0.0.1/index/api/webrtc?app=live&stream=test&type=play
见 dist/demo-webrtc.html 页面
Aliyun
见 demo-aliyun-rtc.html 文件
Others
其他的webrtc地址:
webrtc://127.0.0.1/test/sdp
对于post 请求 sdp 内容,目前播放器支持返回的数据结构有:
- 直接返回sdp数据。
- 返回一个对象,对象里面有sdp数据。
{
code:0, // 0 表示成功,其他表示失败
sdp:'sdp数据' // sdp数据
}
调用播放地址需要传递授权信息(header头部添加认证数据)
目前播放器支持调用play() 方法的时候,通过第二个参数option 里面的headers字段添加
jessibucaPro.play('url',{
headers:{
Authorization:'test' // 身份认证
}
}).then(() => {
console.log('play success')
}).catch((e) => {
console.log('play error', e)
})
打开流地址响应速度
http 协议的响应时间要强于 ws 协议的响应时间。如果想要提升打开流地址的速度,可以考虑使用http协议。
打包在App里面想要通过file协议加载播放器
强制走硬解码
- 禁用软解码。
- 不使用worker线程。
缺点:没法使用软解码,如果遇到机器不支持硬解码,则会导致播放器没法正确播放。
通过cdn 形式加载。
见cdn配置 解决方案
uniapp 里面通过webview的方式打开页面
如果是uniapp里面通过webview的方式打开页面,想要使用播放器。
最好就是走CDN的方式加载播放器。
见cdn配置 解决方案