jjjoy-video
v0.0.2
Published
一个基于 vue 框架和 jessibuce 插件的纯H5直播流视频播放组件。
Downloads
7
Readme
jy-video
一个基于 vue 框架和 jessibuce 插件的纯H5直播流视频播放组件,可用于视频、录像播放或实时数据展示等业务。
组件特点
1. 多屏播放
组件支持一屏、二屏、四屏、六屏、八屏、九屏、十二屏、十六屏、二十五屏、三十六屏播放。
<JyVideo :modelValue="4"></JyVideo>
2. 全端自适配
组件可以在电脑端、移动端自适应,无需额外的配置。
- 宽度自适应,组件内部容器设置了
width: 100%;height: 100%;
,在使用时需要在外层套一个容器;
<div style="width: 500px;height: 100%;">
<JyVideo :modelValue="4"></JyVideo>
</div>
- 事件自动适配,例如对单双击事件进行防抖处理;
/**
* 单双击事件处理
* @param i 窗口索引
*/
let clickTimer: number | undefined = undefined;
let clickTime = 0;
const videoClick = (i: number) => {
setAcIndex(i)
emits('viewportClick', viewportList.value[i], i, viewportList.value)
clickTime++
if (clickTime >= 2) {
emits("viewportDblClick", viewportList.value[i], i, viewportList.value)
}
clickTimer = setTimeout(() => {
clickTime = 0
}, 200)
}
注意:
理论上可以在移动端自适配,但笔者的业务需求主要集中在PC端,未在移动端进行深度测试
由于移动设备性能原因,目前移动端没有多屏需求(可以用,但没必要)
3. 支持软硬解码
4. 功能丰富
- 多屏播放 支持1、2、4、6、8、9、12、16、25、36屏,后期可以扩展更多类型的屏幕(加个 class 的事)
- 生命周期 支持
beforePlayer
、afterPlayer
、beforeDestroy
、destroyed
等生命周期 - 样式自定义 开放headerStyle、borderColor、footerStyle、header、footer等参数和插槽对样式进行设置
- 操作自定义 暴露单双击、拖拽放置等多个事件和方法以自由组合操作逻辑
- 组件独立 可以在同一页面内使用多个视频组件,互不干扰
- 事件监听 在多屏切换、视频播放等过程中会触发各类事件以监听组件的状态
- 默认配置 组件内部优化了 jessibuca 的默认配置,开发者只需调用 player 方法即可
- 支持所有 jessibuce 功能和配置
- 支持解码H.264视频(Baseline, Main, High Profile全支持,支持解码B帧视频)
- 支持解码H.265视频(flv id == 12)
- 支持enhanced-rtmp H265格式
- 支持解码AAC音频(LC,HE,HEv2 Profile全支持)
- 支持解码PCMA音频以及PCMU音频格式
- 可设置播放缓冲区时长,可设置0缓冲极限低延迟(网络抖动会造成卡顿现象)
- 支持WASM智能不花屏丢帧,前台长时间播放绝不累积延迟。
- 可创建多个播放实例
- 程序精简,经CDN加速,GZIP压缩(实际下载500k),加载速度更快
- 同时支持http-flv和websocket-flv协议以及websocket-raw私有协议(裸数据,传输量更小,需要搭配Monibuca服务器) 注:以http-flv请求时,存在跨域请求的问题,需要设置access-control-allow-origin, websocket-flv默认不存在此问题
- 支持HTTPS/WSS加密视频传输,保证视频内容传输安全
- 手机浏览器内打开视频不会变成全屏播放
- 手机浏览器内打开长时间不会息屏
- 支持解码8kHz PCM_ALAW, PCM_MULAW的G.711音频
- 支持填充,等比,等比缩放 3中视频缩放模式
- 支持0,90,180,270度画面旋转
- 自带底部UI,支持原子化配置是否显示(播放/暂停、音量调节、截屏、录制/暂停录制、全屏/取消全屏、流量显示)
- 自带底部UI适配H5移动端,并支持web端全屏(操作栏适配横屏)
- 自带底部UI支持设置成自动隐藏,只有鼠标聚焦到播放器内部才会显示,移除之后,会消失。
- 支持键盘快捷键
- 支持OffscreenCanvas,提升Webgl渲染性能
- 支持WebWorker多核解码,提升多画面播放性能
- 支持WebCodecs硬件解码API
- 支持WebCodecs硬件解码配置通过video标签渲染或者canvas标签渲染画面
- 支持MediaSourceExtensions 硬件解码
- 支持WebCodecs和MediaSourceExtensions硬解码失败的情况下自动切换到wasm软解码
- 支持同一个播放地址视频分辨率发生变化的时候视频不花屏(仅软解码)
- 支持同一个播放地址音频采样和编码发生改变的时候音频自动切换
- 支持视频录制(WebM、MP4格式[video/webm;codecs=h264]),(MP4格式支持在IOS VLC播放器显示时长播放,Android VLC播放器无法显示时长播放,PC VLC播放器可以播放)
5. 使用简单
- 可以在 vue 框架直接使用,甚至可做到无参使用
- 所有代码开源,并且代码注释详细,文档使用说明和示例齐全
- API 操作灵活,可以灵活的适用各种应用场景和定制化的二次开发
安装
pnpm install jjjoy-video -S
使用
引入jessibuca
提醒:
github demo 上面的jessibuca.js、 decoder.js、decoder.wasm 可能存在版本的延迟。如有问题,请更新到最新的文件使用
一般情况下,建议放置在 public/jessibuca
目录下面,如果需要放置在子目录,需要修改的地方有
index.html文件
<script src="./jessibuca/decoder.js"></script>
对于 jessibucaConfig 的配置
{
decoder:'./jessibuca/decoder.js', // 这也是组件内部默认配置
}
引入组件
main.ts
:
// 全局注册
import JyVideo from "jjjoy-video";
// 引入样式
import 'jjjoyjy-video/style.css'
Vue.use(JyVideo);
在 script
中引用组件:
// 如采用全局注册,页面就不需要再引用注册,可以直接使用
import JyVideo from "jjjoy-video";
import 'jjjoy-video/style.css'
在 template
中使用组件:
<!--无参使用时,参数使用全默认值, 4屏 -->
<JyVideo></JyVideo>
或
<JyVideo ref="jyVideoRef" :modelValue="4"></JyVideo>
API
属性
| 名称 | 说明 | 类型 | 默认 | | --- | --- | :---: | :---: | | v-model/modelValue | 分屏个数 | EViewportNum | 4 | | config | jessibuca配置,会与组件内部的默认配置进行合并,生成最终的有效配置 | object | 组件默认配置,详情看下文 | | footer | 是否显示默认的脚部 | boolean | true | | btnList | 默认脚部显示的默认按钮 | Array | [1, 2, 4, 6, 8, 9, 12, 16, 25, 36] | | borderColor | 边框颜色 | string | #e4e7ed | | activeBorderColor | 选中窗口的边框颜色 | string | #0085ff | | footerStyle | 脚部盒子插槽的css样式 | string | object | -- | | headerStyle | 头部盒子插槽的css样式 | string | object | -- | | fullscreenFn | 绑定全屏按钮的自定义方法,如设置了,点击全屏按钮的时候触发。返回false阻止默认的全屏行为 | (viewport: IViewport, index: number) => boolean | () => true | | fullscreenExitFn | 绑定退出全屏按钮的自定义方法,如设置了,点击退出全屏按钮的时候触发。返回false阻止默认的退出全屏行为 | (viewport: IViewport, index: number) => boolean | () => true | | screenshotFn | 绑定截图按钮的自定义方法,如设置了,点击截图按钮的时候触发。返回false阻止默认的截图行为 | (viewport: IViewport, index: number) => boolean | () => true | | playFn | 绑定播放按钮的自定义方法,如设置了,点击播放按钮的时候触发。返回false阻止默认的播放行为 | (viewport: IViewport, index: number) => boolean | () => true | | pauseFn | 绑定暂停按钮的自定义方法,如设置了,点击暂停按钮的时候触发。返回false阻止默认的暂停行为 | (viewport: IViewport, index: number) => boolean | () => true | | recordFn | 绑定录制按钮的自定义方法,如设置了,点击录制按钮的时候触发。返回false阻止默认的录制行为 | (viewport: IViewport, index: number) => boolean | () => true | | recordStopFn | 绑定停止录制按钮的自定义方法,如设置了,点击停止录制按钮的时候触发。返回false阻止默认的停止录制行为 | (viewport: IViewport, index: number) => boolean | () => true | | draggable | 控制窗口是否可拖拽 | boolean | false | | allowDrag | 判断某一个窗口是否允许拖拽,如果返回false,表示该窗口不允许拖拽,draggable为true 时有效 | (viewport: IViewport, index: number) => boolean | () => true | | allowDrop | 判断某一个窗口是否允许放置,如果返回false,表示该窗口不允许放置 | (viewport: IViewport, index: number, event: DragEvent) => boolean | () => true |
组件默认配置
// Jessibuca默认配置
export default {
videoBuffer: 0.2, // 缓存时长
decoder: "./jessibuca/decoder-pro.js", // // worker地址,默认引用的是根目录下面的decoder-pro.js文件
isResize: false, // 画面是否拉伸
text: "",
loadingText: "加载中", // // 加载过程中文案
showBandwidth: false, // 显示网速
showPerformance: false, // 是否显示性能面板
hasAudio: true, // 是否有音频,如果设置false,则不对音频数据解码,提升性能。
controlAutoHide: true, // 控制栏是否自动隐藏
qualityConfig: ["普清", "高清", "超清", "4K", "8K"],
// forceNoOffscreen: true, // 是否不使用离屏模式(提升渲染能力)
isNotMute: false, // 是否开启声音,默认是关闭声音播放的。
heartTimeout: 60, // 设置超时时长, 播放中途,如果超过设定时长无数据返回,则回调timeout事件
heartTimeoutReplayTimes: -1, // heartTimeoutReplay 重试次数
mseDecodeErrorReplay: true, // mse解码报错之后,是否不再抛出异常, 直接重新播放
wcsDecodeErrorReplay: true, // wcs解码报错之后,是否不再抛出异常, 直接重新播放
autoWasm: false, // 在使用MSE或者 Webcodecs 播放H265的时候,是否自动降级到wasm模式。
useMSE: true, // 是否开启MediaSource硬解码
demuxUseWorker: true, // 使用worker解析
loadingTimeoutReplayTimes: -1, // loadingTimeoutReplay 重试次数
debug: false, // 是否开启控制台调试打印
debugLevel: "debug", // debug模式下的日志级别,支持debug、warn,默认是warn
// 配置播放器播放过程中水印显示,支持图片和文字和矩形边框和自定义HTML
watermarkConfig: {
text: {
content: "",
},
right: 10,
top: 10,
},
operateBtns: {
fullscreen: true, // 是否显示全屏按钮
screenshot: true, // 是否显示截图按钮
performance: true, // 是否显示性能按钮
record: true, // 是否显示录制按钮
close: true, // 是否显示关闭按钮
audio: true, // 是否显示声音按钮
play: false, // 是否显示播放暂停按钮
ptz: false, // 是否显示PTZ轮盘按钮
quality: false, // 是否显示清晰度按钮
zoom: false, // 是否显示电子放大
face: false, // 是否显示人脸识别按钮
},
// 添加自定义按钮
extendOperateBtns: [],
// 添加自定义右键菜单按钮
contextmenuBtns: [],
};
EViewportNum 结构
declare const enum EViewportNum {
ONE = 1,
TOW = 2,
FOUR = 4,
SIX = 6,
EIGHT = 8,
NINE = 9,
TWELVE = 12,
SIXTEEN = 16,
TWENTY_FIVE = 25,
THIRTY_SIX = 36,
}
IViewport 结构
declare interface IVideoInfo {
[key: string]: any; // 后面再补全Jessibuca对象类型
}
declare interface IViewport {
// 对应窗口的错误信息
errorMsg: string | null,
// 窗口信息
deviceInfo: any,
// 窗口播放器信息
videoInfo: IVideoInfo | null,
}
方法
JyVideo
组件暴露了以下方法
| 方法名称 | 描述 | 参数 | | --- | --- | :---: | | player | 播放视频 | 接受三个参数:1、视频播放地址,string类型2、窗口额外信息,any类型3、窗口索引, 默认是当前激活窗口 | | setAcIndex | 设置激活的窗口,如果超过窗口个数,会默认激活第一个窗口 | 窗口索引 | | getAcIndex | 返回当前激活窗口的索引 | -- | | getAcViewport | 返回当前激活窗口的IViewport对象 | -- | | getViewportList | 返回所有的IViewport窗口对象 | -- | | isFree | 判断对应窗口是否空闲,当该窗口没有在播放视频时返回true | 窗口索引 | | findFreeViewportIndex | 寻找空闲窗口,返回下最近一个空闲窗口的索引,没有则返回-1 | -- | | setErrorMsg | 设置窗口错误信息,会把当前正在播放的视频销毁 | 接受两个参数:1、错误的信息,string类型2、窗口索引,默认为当前激活窗口 | | setDeviceInfo | 设置窗口信息 | 接受两个参数:1、要设置的信息,any类型2、窗口索引,默认为当前激活窗口 | | destroyPlayer | 销毁对应窗口,销毁成功返回true,销毁失败返回false | 窗口索引 | | destoryPlayerAll | 销毁所有窗口 | -- |
事件
| 事件名 | 说明 | 回调参数 | | --- | --- | :---: | | changeLayout | 当窗口个数发生变化时触发 | 当前窗口的个数 | | viewportClick | 单击窗口时触发 | 共三个参数,依次为:当前窗口的IViewport对象、窗口的索引、所有窗口的IViewport对象数组 | | viewportDblClick | 双击窗口时触发 | 共三个参数,依次为:当前窗口的IViewport对象、窗口的索引、所有窗口的IViewport对象数组 | | viewportDragStart | 开始拖拽窗口时触发 | 共三个参数,依次为:窗口的IViewport对象,窗口的索引、拖拽事件对象DragEvent | | viewportDrag | 窗口拖拽时触发 | 共三个参数,依次为:IViewport窗口对象,窗口的索引、拖拽事件对象DragEvent | | viewportDragEnd | 结束拖拽时触发 | 共三个参数,依次为:窗口的IViewport对象,窗口的索引、拖拽事件对象DragEvent | | viewportDragEnter | 进入到了窗口区域 | 共三个参数,依次为:窗口的IViewport对象,窗口的索引、拖拽事件对象DragEvent | | viewportDragOver | 在窗口区域内拖拽中 | 共三个参数,依次为:窗口的IViewport对象,窗口的索引、拖拽事件对象DragEvent | | viewportDragLeave | 离开了窗口区域 | 共三个参数,依次为:窗口的IViewport对象,窗口的索引、拖拽事件对象DragEvent | | viewportDrop | 在窗口区域内,放下了被拖拽元素 | 共三个参数,依次为:窗口的IViewport对象,窗口的索引、拖拽事件对象DragEvent | | beforePlayer | 播放视频之前触发 | 共三个参数,依次为:窗口的IViewport对象,窗口的索引、窗口的jessibuca对象 | | afterPlayer | 播放视频之后触发 | 共三个参数,依次为:窗口的IViewport对象,窗口的索引、窗口的jessibuca对象 | | beforeDestroy | 视频窗口销毁之前触发 | 共两个参数,依次为:窗口的IViewport对象,窗口的索引 | | destroyed | 视频窗口销毁之后触发 | 共两个参数,依次为:窗口的IViewport对象,窗口的索引 |
插槽
| 名称 | 说明 | 参数 | | --- | --- | --- | | header | 头部插槽 | -- | | footer | 脚部插槽,若定义了则会覆盖默认的脚部 | -- | | viewport | 播放窗口插槽,只有在有视频播放时才显示。由于视频播放时存在层叠,该插槽会被视频遮挡。需要设置样式style="position: relative/absolute;z-index: 2;" | { viewport: IViewport, index: number } viewport: 窗口的IViewport对象index: 窗口的索引 | | empty | 空状态 | { viewport: IViewport, index: number } viewport: 窗口的IViewport对象index: 窗口的索引 | | error | 错误状态,当窗口IViewport对象的errorMsg有值时显示,即使用了setErrorMsg设置了错误信息 | { viewport: IViewport, index: number } viewport: 窗口的IViewport对象index: 窗口的索引 |
最后说明
打包结果分为两个版本,index.es.js
和index.umd.js
,umd版本在html使用时,发现无法做到响应式,需要将整个props解构才行,详情看examples/index.html。
默认使用 esm 版本
以上就是本文的全部内容,希望对大家有所帮助,也希望大家多多支持。
update(更新内容)
- 2024-09-10 完成1.0.0版本需求整理和开发
- 2024-09-12 完善注释
- 2024-09-29 完善文档