集成插件

本文介绍如何集成支付宝小程序端的实时音视频通话插件。

插件支持 3 种集成模式:

  • 全屏:调用时,插件自动跳转视频通话全屏页。

  • Flex:视频通话界面可以嵌入到自己的小程序的指定区域中。

  • Answer:可以将视频通话界面嵌入到自己的小程序指定区域中。可以自定义覆盖已有的 UI 样式,不可以与 Flex 模式同时使用。

说明

  • 配置上如果同时禁止摄像头和语音,会订阅失败,客户端目前逻辑判断中必须要有一个为 true。

  • 组件在引入的时候会做权限引导(麦克风、摄像头),但也提供方法供您在使用组件前做权限判断。

全屏模式(通过 JS API 调用)

示例代码

const { rtc } = requirePlugin('rtc')

// 视频通话区分两个角色
// - 视频发起人:发起视频通过的人
// - 加入的人员:要加入通话的人

// 流程
// - 1、发起,调用 start(config) ,得到 roomId 和 token 
// - 2、将 roomId  和 token  通过 PUSH、短信等渠道给到需要加入的人员
// - 3、其他人唤起插件,调用 join(roomId, config) 加入到通话中来

// 发起人调用这个 API
rtc.start(config).then(roomInfo => {
  const { roomId, token } = roomInfo
  // 这里拿到创建的 roomId 和 token ,用于后续其他人加入使用
})

// ======================

// 加入的人调用这个 API
rtc.join(roomId, config) // config 是需要的参数。 
说明

config 参数的说明请参见 Config 参数

调用流程

视频通话需要区分两个角色。一是视频发起人,二是要加入视频通话的人。

  • 视频发起人发起视频通话,调用 start(config) ,得到 roomId 和 token。

  • 将 roomId 和 token 通过 PUSH、短信等渠道给到需要加入的人员。

  • 其他人唤起插件,调用 join(roomId, config) 加入到通话中来。

API 接口

const { rtc, EventType } = requirePlugin('rtc')
  • 发起视频通话 start (config: Config): Promise<RoomInfo>

  • 加入视频通话 join (roomId: string, config: Config): Promise<RoomInfo>

  • 监听通话事件 on(type: EventType, handler: data => void)

获取 RoomInfo 的方法

视频通话由一方发起,发起后得到 RoomInfo,用于后续其他人加入,获取 RoomInfo 有以下两种方式(选择其中一种即可)。

  • 通过 API join ,调用后返回 Promise<RoomInfo>

    rtc.start(config).then(roomInfo => {
      const { roomId, token } = roomInfo
      // 这里拿到创建的 roomId 和 token,用于后续其他人加入使用
    })
  • 通过 ROOM_CREATED 事件得到。

    rtc.on(EventType.ROOM_CREATED, data => {
      // 这里拿到发起人创建的 roomId 和 token,用于后续其他人加入使用
      const { roomId, token } = data
    })

Flex 模式(通过组件调用)

引入组件

{
  "usingComponents": {
    "rtc": "plugin://rtc/flex"
  }
}

使用组件

<rtc
  config="{{ config }}"
  currentUserId="{{ currentUserId }}"
  onPlayerChange="handlePlayerChange"
  onUserChange="handleUserChange"
  onHangup="handleHangup"
  onError="handleError"
/>
  • config 对象参见 重要参数 说明。

  • currentUserId 当前播放的内容可以通过这个参数传入 userId 进行切换。

  • onPlayerChange(userId: string, preUserId: string): void 用户播放界面切换事件。

  • onUserChange(state: UserState): void 用户变化事件。

  • onError(error: Error): void 通用报错。

  • onHangup(): void 挂断事件。

interface UserState {
  joined: string[]  // 加入的用户列表
  exited: string[]  // 退出的用户列表
  users: string[]   // 当前房间内的用户列表
  current?: string  // 当前播放内容的用户 ID
}

API 接口

const { rtc, EventType } = requirePlugin('rtc')
  • 发起视频通话 start (config: Config): Promise<RoomInfo>

  • 加入视频通话 join (roomId: string, config: Config): Promise<RoomInfo>

  • 监听通话事件 on(type: EventType, handler: data => void)

  • 邀请 invite (userId: string, data?: InviteInfo): Promise<Result>

Config 对象参见 重要参数 说明。

  • InviteInfo

以下邀请接口中可选(?)的参数,用于描述被邀请人展示的内容。

interface InviteInfo {
  nickName?: string // 邀请人昵称
  page?: string // 小程序的落地页
  inviteType?: InviteType // 被邀请人类型 (0: web, 1: app), 默认为 1
  roomType?: RoomType // 房间类型 (1: 音视频通话, 2: 音频通话),默认为 1
  params?: Record<string, unknown> | null
}

Answer(通过组件调用)

引入组件

{
  "usingComponents": {
    "answer": "plugin://rtc/answer"
  }
}

使用组件

<answer
  screenname="{{screenname}}" // 覆盖 screen 的 class name,默认‘screen'
  namespace="{{namespace}}" // UI 样式 class name,默认"answer"
  config="{{ config }}"
  currentUserId="{{ currentUserId }}"
  onPlayerChange="handlePlayerChange"
  onUserChange="handleUserChange"
  onHangup="handleHangup"
  onError="handleError"
/>

需要覆盖的 CSS 样式请在项目的 app.acss 中说明。

需要覆盖的 CSS
.screen {
  position: relative;
  background: rgba(31,33,41,0.95);
}
.screen.full {
  height: 100vh;
}
.screen.full .content {
  height: 100vh;
}
.screen.flex {
  height: 100%;
}
.screen.flex .content {
  height: 100%;
}
.screen .content {
  position: relative;
}
.screen .actions {
  position: absolute;
  bottom: 100rpx;
  height: 260rpx;
  width: 100%;
  display: flex;
}
.screen .actions .action {
  flex: 1;
  height: 100%;
  position: relative;
}
.answer .pusher-view,
.answer .player-view {
  width: 100%;
  height: 100%;
}
.answer .pusher-view.mini,
.answer .player-view.mini {
  position: absolute;
  top: 168rpx;
  right: 4px;
  width: 240rpx;
  height: 426rpx;
  z-index: 1;
}
.answer .pusher-view.hidden,
.answer .player-view.hidden {
  width: 0;
  z-index: -999;
}
.answer .pusher-view .message,
.answer .player-view .message {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(31,33,41,0.95);
  color: #fff;
}
.answer .live-player,
.answer .live-pusher {
  width: 100%;
  height: 100%;
}
.answer .user-list {
  white-space: nowrap;
  position: absolute;
  display: flex;
  bottom: 360rpx;
  height: 180rpx;
  width: 100%;
}
.answer .user-list-item {
  width: 160rpx;
  height: 160rpx;
  margin: 0 10rpx;
  background: #333;
  overflow: hidden;
  flex-shrink: 0;
  flex-grow: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  padding: 8px;
}
.answer .user-list-item:first-child {
  margin-left: 25rpx;
}
.answer .user-list-item:last-child {
  margin-right: 25rpx;
}
.answer .user-list-item-text {
  color: #fff;
  word-wrap: break-word;
}
.answer .user-list-item.selected .user-list-item-text {
  color: #1677ff;
}
.answer .btn {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  width: 106rpx;
  height: 106rpx;
  line-height: 106rpx;
  border-radius: 50%;
  text-align: center;
  color: #fff;
  background: #262a32;
}
.answer .btn .icon {
  width: 50%;
  height: 50%;
  margin: 25% auto;
}
.answer .btn-mute .icon {
  background: url("xxxx") center center no-repeat;
  background-size: contain;
}
.answer .btn-mute .icon.disable {
  background: url("xxx") center center no-repeat;
  background-size: contain;
}
.answer .btn-speaker .icon {
  background: url("xxx") center center no-repeat;
  background-size: contain;
}
.answer .btn-camera .icon {
  background: url("xxx") center center no-repeat;
  background-size: contain;
}
.answer .btn-camera .icon.disable {
  background: url("xx") center center no-repeat;
  background-size: contain;
}
.answer .btn-hangup {
  background: #fa4b4b;
}
.answer .btn-hangup .icon {
  background: url("xxx") center center no-repeat;
  background-size: contain;
}
.answer .btn-switch-camera .icon {
  background: url("xxx") center center no-repeat;
  background-size: contain;
}
.answer .btn-screenshot .icon {
  background: url("xxx") center center no-repeat;
  background-size: contain;
}

API 接口

const { rtc, EventType } = requirePlugin('rtc')
  • 发起视频通话 start (config: Config): Promise<RoomInfo>

  • 加入视频通话 join (roomId: string, config: Config): Promise<RoomInfo>

  • 监听通话事件 on(type: EventType, handler: data =>void)

  • 邀请 invite (userId: string, data?: InviteInfo): Promise<Result>

  • 权限引导 async authCheck()

  • 挂断通话 hangup(roomId?:string) :void

Config 对象参见 重要参数 说明。