# ThumbPlayer 腾讯视频业务弹幕插件
目前,许多调用方有在使用 SuperPlayer 播放腾讯视频内容,在播放腾讯视频内容时,希望能够播放器上能够有一个统一的默认弹幕配置,直接获得类似现网 v 站发弹幕、看弹幕的能力。 因此,可以将弹幕相关业务需求做成一个独立的业务组件,当调用方在 Thumbplayer 中引入该组件时,自动获得弹幕相关业务能力。
# 项目介绍
# 注意
- 本插件仅针对播放腾讯视频 vid / 腾讯视频直播 cnlid 业务,如想为其他业务定制弹幕能力,请使用
@tencent/ovb-barrage
- 插件将读取
player.config.type
属性来决定应当使用点播弹幕还是直播弹幕,因此在使用对应点直播场景时,请务必设置type
属性 - 直播发弹幕需要
livepid
属性,需要在SuperPlayer.play({cnlid: '', livepid: ''})
传入。此外,由于历史原因,老版本(1.3.65
及以下版本)的SuperPlayer
暂时未存储该字段, 需要在player.play()
之前,使用player.setCommonKv(COMMON_DATA_KEY.livepid, livepid);
设置,或是将 SuperPlayer 升级到高版本。 - 点播需要
cid
和columnId
属性,需要在 play 前,使用player.setCommonKv(COMMON_DATA_KEY.cid, cid)
和player.setCommonKv(COMMON_DATA_KEY.columnId || 'columnId', columnId)
传入。 livepid
存储逻辑在SuperPlayer
层,如果使用的是Thumbplayer-H5
,请使用player.setCommonKv(COMMON_DATA_KEY.livepid, livepid)
自行注入- 移动端不推荐开启弹幕,在全屏下播放容易被系统播放器(如 iOS)接管,导致弹幕失效
- 直播因为是定时轮询,如果直接展示,可能会出现一次轮询获取到弹幕时,弹幕展示非常密集,但后 n 秒一个弹幕都不展示(弹幕一波接一波,中间有很大空白)。因此,内部逻辑会按照轮询时长,把弹幕均分,确保每秒都有弹幕(如果弹幕数足够情况下)。
# 使用
import { H5Player } from '@tencent/thumbplayer-h5';
// 导入弹幕包,内部会自动注册到播放器上
import { BarragePlugin } from '@tencent/thumbplayer-plugin-barrage';
new H5Player({
plugins: [BarragePlugin.pluginName],
barrageConfig: {
// 弹幕配置
},
});
# 配置
弹幕插件配置继承于 @ovb/barrage
,配置将透传,新增的配置项和相关注释如下:
export interface BarrageConfig extends IBarrageManagerConfig {
/* 在 CGI 有弹幕的情况下,是否开启弹幕,如果 CGI 无弹幕,则配置无效 */
enable?: boolean;
/* 弹幕浮层 z-index 值 */
zIndex?: number;
/* 如果希望修改默认渲染样式或 DOM 结构,可以覆盖渲染函数,实现自定义拼接逻辑 */
render?: IBarrageRender;
/* 渲染弹幕的时间间隔(毫秒) */
renderTimeGap?: number;
/* 弹幕预加载时间(毫秒) */
preloadTime?: number;
/* 控制栏相关配置 */
control?: IControlBarConfig;
}
/* 控制栏配置 */
export interface IControlBarConfig {
/* 控制栏容器 */
container: string | HTMLElement;
/* 是否展示状态栏: false 将设置 display: none 属性*/
display?: boolean;
/* 输入框 placeholder */
placeholder?: string;
/* 发弹幕防刷延迟(点击发表后 n 秒才能发下一条弹幕)*/
postDelay?: number;
/* 在 input 中发弹幕快捷键 */
postShortCut?: string;
}
在传入配置时,插件将对合并传入的插件配置和默认配置,默认配置如下:
export const DEFAULT_CONFIG: Partial<BarrageConfig> = {
/* 1000ms 渲染一次弹幕 */
renderTimeGap: 1000,
/* 弹幕是否开启 */
enable: true,
/* 默认弹幕 z-index: 1 */
zIndex: 1,
/* 弹幕请求预加载时间 */
preloadTime: 0,
control: {
display: true,
// 如果不传,默认没有控制栏
container: '',
},
};
# 直播配置参考
// 注册插件
H5Player.registerPlugin(GetInfoLive.pluginName, GetInfoLive);
const config: BarrageConfig = {
enable: true,
zIndex: 3,
control: {
display: true,
container: '#barrage-control',
placeholder: '发条弹幕,证明你来过',
postDelay: 3,
},
};
const player = new H5Player({
container: '#demo',
plugins: [BarragePlugin.pluginName, GetInfoLive.pluginName],
barrageConfig: config,
type: 'live',
});
# 点播配置参考
H5Player.registerPlugin(GetInfoVod.pluginName, GetInfoVod);
const config: BarrageConfig = {
enable: true,
zIndex: 10,
vod: {
cid: 'mzc00200024ubd1',
columnID: '89697',
},
control: {
display: true,
container: '#barrage-control',
placeholder: '发条弹幕,证明你来过',
postShortCut: 'enter',
postDelay: 10,
},
};
const player = new H5Player({
container: '#demo',
plugins: [BarragePlugin.pluginName, GetInfoVod.pluginName],
barrageConfig: config,
});
# 常用场景
# 全屏变化
为了不与官方控制栏插件耦合,插件默认不监听全屏事件(CSS 全屏/真全屏),如果有全屏需求,请自行监听全屏事件,并调用 resize
重设弹幕位置
const ctrl = player.plugins[CtrlbarPlugin.pluginName];
const barrage = player.plugins[BarragePlugin.pluginName];
ctrl.on(CTRL_EVENTS.FULLSCREEN_CHANGE, () => {
barrage.resize();
});
# 播下一条
若调用 player.play()
播放下一条视频,在 cid / columnId 变更的情况下,需要重新设置:
// 重播 / 切 vid 时候重设专辑配置
player.setCommonKv(COMMON_DATA_KEY.cid, cid);
player.setCommonKv(COMMON_DATA_KEY.columnId || 'columnId', columnId);
player.play(nextVid);
# 自定义弹幕 / hooks
插件内建了一套弹幕结构,如果希望修改弹幕 DOM 结构,可以选择传入自定义渲染函数覆盖。
const render: IBarrageRender = (barrage: IBarrageItem) =>
`<div style="color: red">${barrage.content}</div>`;
new H5Player({
// ...省略其他配置
barrageConfig: {
render,
},
});
另外, @ovb/barrage
提供了一些弹幕 hooks 函数,能够在某些弹幕周期执行对应回调,具体可以参考 仓库文档 (opens new window)
const config: BarrageConfig = {
// ...忽略其他配置
hooks: {
onBarrageCreate: (barrage: Barrage) => {
console.log('弹幕创建', barrage);
},
onBarrageClick: (barrage: Barrage) => {
console.log('点击了弹幕');
},
},
};
# API
export declare class BarragePlugin extends Plugin {
/*
* 弹幕开启状态
* 规则:
* 在 CGI 有弹幕的情况下,由传入的 config 配置是否开启弹幕
* 如果 CGI 无弹幕,则 config 上的配置无效,关闭弹幕
*/
public get enable(): boolean;
public set enable(status: boolean);
/**
* 登陆态,决定控制栏上登陆按钮展示情况
*/
public get login(): boolean;
public set login(status: boolean);
/**
* 不需要关心,由 H5Player 维护
* @param player
*/
public constructor(player: IH5Player);
/**
* 设置插件点播设置,即 config.vod 项,播下一条视频时使用
* @param vodConfig
*/
public setVodConfig(vodConfig: BarrageConfig['vod']): void;
/**
* 发送弹幕接口,请求 CGI 并假显到弹幕管理器中
* @param barrage 需要发送的弹幕信息体(无 ID)
*/
public postBarrage(barrage: PostBarrageBody): Promise<boolean>;
/**
* 设置控制栏 display: none 情况
* @param display 控制栏是否可见
*/
public setCtrlDisplay(display: boolean): void;
/**
* 当播放器容器大小改变时,调用该方法更新弹幕位置
*/
public resize(): void;
/**
* 销毁插件,移除 DOM 实例
*/
public destroy(): void;
}
# 开发
如果第一次克隆此仓库,请参考 仓库文档 初始化并安装依赖
# 本地预览
npm run dev
# 构建
npm run build
# 架构设计
BarragePlugin
:插件本体,整体的控制器,整合、监听各个模块来配合最终完成业务需求Provider
:CGI 抽象,相当于数据源,提供拉弹幕和发弹幕封装。将播放时长根据拉弹幕 / 轮询间隔分为 n 多个弹幕片(block),根据提供的播放时长去拉取对应弹幕片数据,并提供缓存逻辑,如果从数据源请求同一弹幕片,则默认走缓存逻辑。Render
:一条弹幕渲染函数,内部实现 HTML 字符串拼接规则,传入弹幕数据,返回拼接好的字符串。拉到弹幕片数据后,会遍历所有弹幕并执行渲染函数转换为字符串。Manager
:由@ovb-barrage
包提供,提供弹幕渲染逻辑CtrlBar
:控制栏 UI,提供弹幕开关、发弹幕输入框、发弹幕按钮 UI 和相关点击逻辑,相关 UI 响应(如点击了弹幕开关)以事件方式在插件内广播,BarragePlugin 统一去监听弹幕事件,作出处理并修改对应属性(enable
)。外部想要监听也可以通过(BarragePlugin.on()
)来添加监听。
# 目录
.
├── README.md
├── demo # 本地预览
├── package-lock.json
├── package.json
├── protocol # 后台接口协议
├── src
│ ├── ctrl # 控制栏
│ ├── manager # 弹幕管理器
│ ├── provider # 弹幕数据源
│ ├── render # 弹幕渲染函数
│ ├── styles # 样式
│ └── utils
└── tsconfig.json
# 参考逻辑
# TXPlayer
将整个播放周期按照预设时长分为 n 个时间片(预设 30 秒),拉弹幕后根据时间片,当播弹幕到最一个时间片时,拉弹幕
# TXVLive
每次拉弹幕后台下发轮询时间,时间到轮询拉一次弹幕