# 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 升级到高版本。
  • 点播需要 cidcolumnId 属性,需要在 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

每次拉弹幕后台下发轮询时间,时间到轮询拉一次弹幕

上次更新: 4/25/2022, 7:17:59 PM