# 实现视频双录

本文档为您展示通过 SDK 实现视频双录(无排队机)的相关步骤,帮助您在多人视频通话场景下实现创建会议、邀请新成员加入、结束/离开会议的相关能力。

# 加入会议

/**
    * 加入一个会议,结果回调由{@link ConferenceEventType.CONFERENCE_JOIN}上报
  *
  * @param confNumber - 可传字母或数字作为自定义会议号
  * @param video - 传递 true 即可. **目前强制为视频会议, 语音会议暂不可用**
  * @param joinParam - 加入会议额外参数
  */
join(confNumber: string, video: boolean, joinParam: ConferenceJoinParam): Promise<any>;

ConferenceJoinParam (opens new window) 参数说明:

属性名 类型 描述
confrencePassword string (数字/字母) 会议密码
enableRecord boolean 是否开启服务端录制注:开启服务端录制后需要在收到 ConferenceEventType.RECORD_DELIVERY_JOIN 事件后才能开始录制
role ConferenceRole

如会议已存在,且会议密码错误,将会通过 ConferenceEventType.ERROR (opens new window) 事件回调。

可通过错误类型判断是否为会议密码错误。

this.client.addEventListener(ConferenceEventType.ERROR, (ev) => {
  switch (ev.error) {
    case ConferenceErrorType.CONFERENCE_PASSWORD_ERROR:
      wx.showModal({
        content: '会议密码错误'
      });
      break;
  }
});

如存在用户校验,且校验未通过,将会通过 ConferenceEventType.ERROR (opens new window) 事件回调。可通过判断错误类型为 CongerenceErrorType.LOGIN_PASSWORD_ERROR 确定是否为用户校验失败。

client.addEventListener(ConferenceEventType.ERROR, (ev) => {
  switch (ev.error) {
    case ConferenceErrorType.LOGIN_PASSWORD_ERROR:
      alert('用户名或密码错误');
      reset(true);
      break;
  }
})

示例代码:

var {SimpleRoleCompose} = JuphoonRTCConferenceSDK;
// SimpleRoleCompose.NORMAL 普通角色(默认)
// SimpleRoleCompose.AGENT 坐席
// SimpleRoleCompose.GUEST 访客

client.start('12345678', true, {nickName: 'siaikin', role: SimpleRoleCompose.NORMAL});

通过 ConferenceJoinParam (opens new window) 可在加入会议前设置会议最大人数、昵称、 参会密码、 是否开启录制、在会议中的角色等。

调用该方法后会收到 ConferenceEventType.CONFERENCE_JOIN (opens new window) 事件, 可以在该事件中调用 requestVideo (opens new window)startVideo (opens new window) 设置请求的视频画面大小以及渲染画面。

startVideo (opens new window) 方法会返回一个 Prmise, 当返回值变为 resolve 状态时, then方法会接受到一个 RTCStream 对象,可以调用该对象的 start 方法在界面上渲染视频画面。

start方法接受一个 DOM 元素的 id 为参数,之后将会把视频画面渲染到该DOM 元素中。

TIP

请勿传入空元素 (Empty element) 的 id, 空元素中无法插入视频画面

client.addEventListener(ConferenceEventType.CONFERENCE_JOIN, (ev) => {
  // 设置远端画面的分辨率为最小值
  client.requestVideo(null, ConferencePictureSize.MIN)
    .catch(reason => console.error(reason));
  //    渲染远端画面到id为 `remote-video` 的dom元素中
  client.startVideo()
    .then(stream => {
    stream.start('remote-video');
  });
});
//  视频尺寸枚举
export enum ConferencePictureSize
{
  /**
   * 不请求
   */
  NONE = '0x0',
  /**
   * 最小尺寸
   */
  MIN = '0x100',
  /**
   * 小尺寸
   */
  SMALL = '0x200',
  /**
   * 大尺寸
   */
  LARGE = '0x300',
  /**
   * 最大尺寸
   */
  MAX = '0x400'
}

# 创建本地视频画面

startCameraVideo (opens new window) 接口会打开摄像头并返回一个 RTCStream 对象, 可以通过该对象将画面渲染到页面上。

渲染模式可指定两种渲染模式RenderType.COVER(保持原有尺寸比例,内容被缩放)和 RenderType.CONTAIN (保持原有尺寸比例。但部分内容可能被剪切)。

返回的 RTCStream (opens new window) 对象可通过调用 start(id) 方法将画面渲染到指定 id 的 DOM 元素中。

/**
    * 获得视频预览对象,通过此对象能获得本地摄像头画面用于UI显示
    *
    * @param renderType - 渲染模式
    * @see RenderType
    */
startCameraVideo(renderType): Promise<Stream>;

示例代码:

<div id="local-video" style="width: 400px; height: 300px;"></div>
client.startCameraVideo('cover')
  .then(stream => {
  stream.start('local-video'); //   将画面渲染到id为 local-video 的 dom元素中
})
  .catch(err => {
  console.error(err);
});

# 新成员加入

当新成员加入频道后,其他成员会收到成员加入的回调。

client.addEventListener(ConferenceEventType.CONFERENCE_PARTICIPANT_UPDATE, (ev) => {
  const
        //  变化之前的状态
    old = ev.message.old,
        //  变化之后的状态
    new = ev.message.new;
});

# 创建远端视频画面

/**
    * 获得视频对象,通过此对象能获得远端画面用于UI显示
  */
startVideo(): Promise<Stream>;

# Autoplay问题

当我们获取到了远端的音视频数据并开始播放时,有可能会收到浏览器的自动播放策略限制 (opens new window)自动播放限制是指如果以下任何一项未发生则媒体不允许播放:

  1. 音频被静音或其音量设置为0

  2. 用户已经与站点进行了交互(通过单击,按键等)

  3. 如果该网站已被列入白名单;如果浏览器确定用户经常与媒体互动,则可能会自动发生这种情况,也可能通过首选项或其他用户界面功能手动发生这种情况

  4. 已通过自动播放功能策略向<iframe>授予自动播放权限

示例代码:

<div id="remote-video" style="width: 400px; height: 300px;"></div>
client.addEventListener(RTCConference.CONFERENCE_JOIN, (ev) => {
  client.startVideo()
    .then(stream => {
    stream.start('remote-video');
  });
});

# 离开会议

离开会议需要调用下面的接口

/**
    * 离开会议
  */
leave(): Promise<any>;

/**
  * 离开会议回调
  */
client.addEventListener(ConferenceEventType.CONFERENCE_LEAVE, (ev) => {
  if (ev.message.result) {
    //  离开成功
  } else {
    // 离开失败
  }
});

# 成员离开

当成员离开频道后,其他成员会收到成员离开的回调。

client.addEventListener(ConferenceEventType.CONFERENCE_PARTICIPANT_LEFT, (ev) => {
  const
        //  离开的成员信息
    participant = ev.message.participant;
});

# 结束会议

如果想结束会议,可以调用下面的接口,此时所有成员都将被退出。

/**
  * 结束会议,主持人才能调用该接口结束会议,结果回调由{@link ConferenceEventType.CONFERENCE_LEAVE}上报
  */
stop(): Promise<any>;

结束会议的回调通过 ConferenceEventType.CONFERENCE_DESTROY (opens new window) 事件进行上报。

client.addEventListener(ConferenceEventType.CONFERENCE_DESTROY, () => {
});