自定义插件实现人名条功能

阿里云ARTC Web SDK支持创建自定义插件以实现人名条功能。人名条通常是指会议或视频聊天中出现在用户视频画面上,显示其姓名或其他标识信息的文本标签。本文为您介绍自定义插件实现人名条功能的示例代码。

前提条件

  1. 开通应用获取应用ID和AppKey

  2. 快速使用阿里云ARTC Web SDK

功能实现

定义UserNamePlugin,需要继承AliRtcPlugin,并实现其中的构造函数和抽象方法。

示例代码

import { AliRtcPlugin, LocalStreamInfo } from 'aliyun-rtc-sdk';

export default class UserNamePlugin extends AliRtcPlugin {
  private canvas: HTMLCanvasElement;
  private requestId?: number;

  // text 为希望绘制的人名
  constructor(text: string) {
    super('UserNamePlugin'); // 插件的名称,可自定义,须保证全局唯一
    this.options = { text };
    this.canvas = document.createElement('canvas');
  }

  isSupported(): boolean {
    // 本插件不需要依赖特定版本 aliyun-rtc-sdk 的功能,所以直接返回 true 即可
    return true;
  }

  setOptions(options: { text: string }): void {
    // 用于动态更新希望绘制的人名
    this.options = options;
  }

  shouldUpdate(): boolean {
    // 当流发生改变的时候(比如开关摄像头),是否要调用 process 方法,这里我们直接返回 true
    return true;
  }

  process(streamInfo: LocalStreamInfo): Promise<void> {
    if (streamInfo.currentVideoTrack) {
      // 如果有视频轨道,我们定义对视频轨道的处理方式
      const videoTrack = streamInfo.currentVideoTrack as MediaStreamVideoTrack;
      const settings = videoTrack.getSettings();
      // 将画布的宽高调整为与视频流相同
      this.canvas.width = settings.width!;
      this.canvas.height = settings.height!;

      // 将 MediaStreamTrack 转换为视频元素的源
      const stream = new MediaStream([videoTrack]);
      const videoElement = document.createElement('video');
      videoElement.srcObject = stream;
      videoElement.play();

      const ctx = this.canvas.getContext('2d')!;

      // 定时绘制视频帧到 canvas,并添加文字
      const drawFrame = () => {
        if (videoElement.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {
          ctx.drawImage(videoElement, 0, 0, this.canvas.width, this.canvas.height);

          // 在右下角添加文字
          ctx.fillStyle = 'white'; // 文字颜色
          ctx.font = '40px Arial'; // 文字大小和字体
          ctx.textAlign = 'right'; // 文本对齐
          ctx.fillText(this.options.text, this.canvas.width - 20, this.canvas.height - 20); // 文本位置
        }
        this.requestId = requestAnimationFrame(drawFrame); // 持续绘制帧
      }
      this.requestId = requestAnimationFrame(drawFrame);

      // 创建新的 MediaStream
      const newStream = this.canvas.captureStream(settings.frameRate); // 或根据需要设置其他帧率
      const newVideoTrack = newStream.getVideoTracks()[0];

      // 调用 streamInfo.updateVideoTrack 替换视频流
      streamInfo.updateVideoTrack(newVideoTrack);
    } else if (this.requestId) {
      // 如果之前设置了 requestAnimationFrame,且此时没有视频轨道,则取消绘制
      cancelAnimationFrame(this.requestId);
    }

    return Promise.resolve();
  }
}

使用插件

SDK内部提供了与Plugin使用相关的API,例如enablePluginsetPluginOptionremovePlugin等。

开启人名条插件

调用以下代码后,可以看到本地预览的视频流中,右下角显示人名条A的文字。

// instance 为 AliRtcEngine 的实例
instance.enablePlugin(new UserNamePlugin('人名条A'));

更新人名条插件

调用以下代码后,可以看到本地预览的视频流中,右下角的文字变成了人名条B

// instance 为 AliRtcEngine 的实例
instance.setPluginOption('UserNamePlugin', { text: '人名条B' });

移除人名条插件

调用以下代码后,可以看到本地预览的视频流中,右下角的文字已经移除。

// instance 为 AliRtcEngine 的实例
instance.removePlugin('UserNamePlugin');