多人音视频通话

本章节介绍多人实时音视频通话的相关功能。多人实时音视频通话顾名思义是支持多个人同时进行实时音视频通话,可以选择纯音频模式,或音视频模式。在这里需要明确几个概念:

房间:房间就是用户进行多人实时音视频通话的地方,房间以房间名称为唯一标识,多人房间需要先创建成功后才能加入,当所有用户都离开房间后,可以复用该房间名重新创建。

互动者:互动者是指在多人通话时可以参与互动,可以发言的人,这些用户可以发送上行的音频或视频数据,也可以接收其他互动者下行的音频或视频数据。

观众:观众是指在多人通话时只可以观看的人,没有发言的权限,这些用户只可以接收互动者下行的音频或视频数据,不可以发送上行音频或视频数据。

其中互动者和观众身份可以随时切换。

多人音视频通话流程图

与点对点通话的流程不同,多人房间暂不支持呼叫、推送和挂断等服务,只提供基本的创建、加入和离开房间接口。目前呼叫方案可以使用IM点对点自定义通知发送呼叫

请开发者自己做好呼叫超时处理

sequenceDiagram 发起者-> 发起者: 1. 创建房间: netcall.createChannel 发起者-> 发起者: 2. 加入房间: netcall.joinChannel 发起者-> 参与者A: 发送IM点对点自定义通知: nim.sendTipMsg 发起者-> 参与者B: 发送IM点对点自定义通知: nim.sendTipMsg 发起者-> 参与者C: 发送IM点对点自定义通知: nim.sendTipMsg 参与者A-> 参与者A: 1. 收到IM自定义通知 参与者A-> 参与者A: 2. 加入房间: netcall.joinChannel 参与者B-> 参与者B: 1. 收到IM自定义通知 参与者B-> 参与者B: 2. 加入房间: netcall.joinChannel 参与者C-> 参与者C: 1. 收到IM自定义通知 参与者C-> 参与者C: 2. 加入房间: netcall.joinChannel

创建房间

netcall.createChannel({
  channelName: 'testChannelName' //必填
  custom: '测试自定义数据' //可选
  webrtcEnable: true // 是否支持WebRTC方式接入,可选,默认为不开启
}).then(function(obj) {
  // 预定房间成功后的上层逻辑操作
  // eg: 初始化房间UI显示
  // eg: 加入房间
})
参数名 类型 说明
channelName string 房间房号,可以任意英文字母和数组的组合
custom string 扩展字段,在通话的创建和加入之间传递自定义的额外信息
webrtcEnable bool 如果需要与 WebRTC 客户端互通,需要指定 WebRTC 兼容开关 webrtcEnable 为 true, 如果没有 WebRTC 客户端参与, 不要打开该开关

加入房间

const sessionConfig = {
  videoQuality: Netcall.CHAT_VIDEO_QUALITY_HIGH,
  videoFrameRate: Netcall.CHAT_VIDEO_FRAME_RATE_15,
  videoEncodeMode: Netcall.CHAT_VIDEO_ENCODEMODE_NORMAL,
  videoBitrate: 0,
  recordVideo: false,
  recordAudio: false,
  highAudio: false,
  bypassRtmp: false,
  rtmpUrl: '',
  rtmpRecord: false,
  splitMode: Netcall.LAYOUT_SPLITLATTICETILE
};
netcall
  .joinChannel({
    channelName: 'testChannelName', //必填
    type: Netcall.NETCALL_TYPE_VIDEO,
    sessionConfig: sessionConfig
  })
  .then(function(obj) {
    // 加入房间成功后的上层逻辑操作
    // eg: 开启摄像头
    // eg: 开启麦克风
    // eg: 开启本地流
    // eg: 设置音量采集、播放
    // eg: 设置视频画面尺寸等等,具体请参照p2p呼叫模式
  });
参数名 类型 说明
channelName string 房间房号,可以任意英文字母和数组的组合
type number 房间通话类型,音频、视频
sessionConfig object 通话配置, 每次通话会伴随着一次通话, 可以对此次通话进行一些配置,具体属性见这里

开启音视频连接

音视频连接(PC Agent)

graph TB A(Start) --> C[netcall.startDevice: 开启本地麦克风] C --> D[netcall.startDevice: 开启本地摄像头] D --> E[netcall.startLocalStream: 开启本地视频预览] E --> F[netcall.startRemoteStream: 开启对端视频预览] F --> G[netcall.setCaptureVolume: 设置己方音频采集音量] G --> H[netcall.setPlayVolume: 设置己方音频播放音量] H --> I[netcall.setVideoViewSize: 设置本地画面大小] I --> J[netcall.on'joinChannel': 监听对方加入通话的通知] J --> K(End)
// 缓存netcall实例
const netcall = this.netcall;
// 开启麦克风
netcall
  .startDevice({
    type: Netcall.DEVICE_TYPE_AUDIO_IN
  })
  .then(function() {
    // 通知对方自己开启了麦克风
    netcall.control({
      command: Netcall.NETCALL_CONTROL_COMMAND_NOTIFY_AUDIO_ON
    });
  })
  .catch(function(err) {
    console.log('启动麦克风失败');
    console.log(err);
  });

// 开启摄像头
netcall
  .startDevice({
    type: Netcall.DEVICE_TYPE_VIDEO,
    width: 640,
    height: 480
  })
  .then(function() {
    // 通知对方自己开启了摄像头
    netcall.control({
      command: Netcall.NETCALL_CONTROL_COMMAND_NOTIFY_VIDEO_ON
    });
  })
  .catch(function(err) {
    // 通知对方自己的摄像头不可用
    netcall.control({
      command: Netcall.NETCALL_CONTROL_COMMAND_SELF_CAMERA_INVALID
    });
    console.log('启动摄像头失败');
    console.error(err);
  });

// 开启本地视频预览
netcall.startLocalStream();

// 设置本地音量采集大小, 该API可以在通话过程中动态调用调整自己的音量采集大小
netcall.setCaptureVolume(255);

// 设置本地音量播放大小, 该API可以在通话过程中动态调用调整自己的音量播放大小(即自己听对端的音量)
netcall.setPlayVolume(255);

// 设置本地视频画面大小
netcall.setVideoViewSize({
  width: 500,
  height: 500,
  cut: true
});

// 在回调里监听对方加入通话,并显示对方的视频画面
netcall.on('joinChannel', function(obj) {
  console.log('user join', obj);
  // 播放对方声音
  netcall
    .startDevice({
      type: Netcall.DEVICE_TYPE_AUDIO_OUT_CHAT
    })
    .catch(function(err) {
      console.log('播放对方的声音失败');
      console.error(err);
    });
  // 预览对方视频画面
  netcall.startRemoteStream({
    account: obj.account,
    node: document.getElementById('remoteContainer')
  });
  // 设置对方预览画面大小
  netcall.setVideoViewRemoteSize({
    account: 'testAccount',
    with: 500,
    height: 500,
    cut: true
  });
});
返回类型 方法名 说明
promise netcall.startDevice 开启本地麦克风
promise netcall.startDevice 开启本地摄像头
promise netcall.startLocalStream 开启本地视频预览
promise netcall.setCaptureVolume 设置己方音频采集音量
promise netcall.setPlayVolume 设置己方音频播放音量
promise netcall.setVideoViewSize 设置本地画面大小
promise netcall.startDevice 播放对方声音
promise netcall.startRemoteStream 预览对方视频画面
promise netcall.setVideoViewRemoteSize 设置对方画面大小

音视频连接(WebRTC)

graph TB A(Start) --> C[netcall.startDevice: 开启本地麦克风] C --> D[netcall.startDevice: 开启本地摄像头] D --> E[netcall.startLocalStream: 开启本地视频预览] E --> F[netcall.startRemoteStream: 开启对端视频预览] F --> G[netcall.setCaptureVolume: 设置己方音频采集音量] G --> H[netcall.setPlayVolume: 设置己方音频播放音量] H --> I[netcall.setVideoViewSize: 设置本地画面大小] I --> J[netcall.on'joinChannel': 监听对方加入通话的通知] J --> K(End)
const promise;
const netcall = this.netcall
const promise = Promise.resolve()

promise.then(function() {
  // 开启麦克风
  return netcall.startDevice({
    type: Netcall.DEVICE_TYPE_AUDIO_IN
  }).catch(function(err) {
    console.log('启动麦克风失败')
    console.error(err)
  })
})
.then(function() {
  // 设置采集音量
  netcall.setCaptureVolume(255)
  // 开启摄像头
  return netcall.startDevice({
      type: Netcall.DEVICE_TYPE_VIDEO,
      width: 640,
      height: 480
    })
  .catch(function(err) {
    console.log('启动摄像头失败')
    console.error(err)
  })
})
.then(function() {
  // 设置本地预览画面大小
  netcall.setVideoViewSize({
    with: 500,
    height: 500,
    cut:true
  })
})
.then(function() {
  // 设置互动者角色
  netcall.changeRoleToPlayer()
  // 开启RTC连接
  console.log("开始webrtc")
  netcall.startRtc()
})
.then(function() {
  console.log("webrtc连接成功")
})
.catch(function(err) {
  console.log('发生错误, 挂断通话')
  console.log(err)
  netcall.hangup()
})

// 在回调里监听对方加入通话,并显示对方的视频画面
netcall.on('remoteTrack', function(obj) {
  console.log('user join', obj)
  // 播放对方声音
  netcall.startDevice({
    type: Netcall.DEVICE_TYPE_AUDIO_OUT_CHAT
  }).catch(function(err) {
    console.log('播放对方的声音失败')
    console.error(err)
  })
  // 预览对方视频画面
  netcall.startRemoteStream({
    account: obj.account,
    node: document.getElementById('remoteContainer')
  })
  // 设置对方预览画面大小
  netcall.setVideoViewRemoteSize({
    account: 'testAccount',
    with: 500,
    height: 500,
    cut:true
  })
})
返回类型 方法名 说明
promise netcall.startDevice 开启本地麦克风
promise netcall.startDevice 开启本地摄像头
promise netcall.startLocalStream 开启本地视频预览
promise netcall.setCaptureVolume 设置己方音频采集音量
promise netcall.setPlayVolume 设置己方音频播放音量
promise netcall.setVideoViewSize 设置本地画面大小
promise netcall.startDevice 播放对方声音
promise netcall.startRemoteStream 预览对方视频画面
promise netcall.setVideoViewRemoteSize 设置对方画面大小

离开房间

netcall.leaveChannel().then(function(obj) {
  // 离开房间后的扫尾工作
});

通话结束的清理工作

graph TB A(Start) --> B[上层逻辑清理自己维护的各种状态: calling等] B --> C[清空各种计时器: 如果有的话] C --> D[netcall.stopLocalStream: 停止本地视频预览] D --> E[netcall.stopRemoteStream: 停止对端视频预览] E --> F[netcall.stopDevice: 停止播放本地音频] F --> G[netcall.stopDevice: 停止播放远程音频] G --> H[netcall.stopDevice: 停止设备麦克风] H --> I[netcall.stopDevice: 停止设备摄像头] I --> J(End)
返回类型 方法名 说明
void netcall.stopLocalStream 停止本地视频预览
void netcall.stopRemoteStream 停止对端视频预览
void netcall.stopDevice 停止设备麦克风
void netcall.stopDevice 停止设备摄像头
void netcall.stopDevice 停止播放本地音频
void netcall.stopDevice 停止播放远程音频
// 停止本地视频预览
netcall.stopLocalStream();

// 停止对端视频预览
netcall.stopRemoteStream();

// 停止设备麦克风
netcall.stopDevice(Netcall.DEVICE_TYPE_AUDIO_IN);

// 停止设备摄像头
netcall.stopDevice(Netcall.DEVICE_TYPE_VIDEO);

// 停止播放本地音频
netcall.stopDevice(Netcall.DEVICE_TYPE_AUDIO_OUT_LOCAL);

// 停止播放对端音频
netcall.stopDevice(Netcall.DEVICE_TYPE_AUDIO_OUT_CHAT);

用户加入房间通知

netcall.on('joinChannel', function(obj) {
  console.log('user joinchannel', obj);
});

obj 为通知消息对象

obj 属性 类型 说明
account string 新加入同伴的 accid
channelId number 加入的房间 id

收到用户媒体流的通知

netcall.on('remoteTrack', function(obj) {
  console.log('收到远程轨道信息', obj);
  // 音频:播放对方的音频
  if (obj.track.kind === 'audio') {
    // 播放对方声音
    netcall
      .startDevice({
        type: Netcall.DEVICE_TYPE_AUDIO_OUT_CHAT
      })
      .catch(function() {
        console.log('播放对方的声音失败');
      });
  }

  // 视频:展示对方的画面
  if (obj.track.kind === 'video') {
    // 预览加入的同学的视频流
    netcall.startRemoteStream({
      uid: obj.uid,
      node: document.getElementById('remoteContainer')
    });

    // 设置对方预览画面大小
    netcall.setVideoViewRemoteSize({
      uid: 'testUid',
      with: 500,
      height: 500,
      cut: true
    });
  }
});

obj 为通知消息对象

obj 属性 类型 说明
uid string 新加入同伴的 uid
channelId number 加入的房间 id
返回类型 方法名 说明
promise netcall.startDevice 播放对方声音
promise netcall.startRemoteStream 预览对方视频画面
promise netcall.setVideoViewRemoteSize 设置对方画面大小

用户离开房间通知

netcall.on('leaveChannel', function(obj) {
  // 通知上层有其他用户离开了会议,上层做相应逻辑和UI处理

  // 停止预览该同伴的视频流
  netcall.stopRemoteStream(obj.account);
});

obj 为通知消息对象

obj 属性 类型 说明
account string 离开同伴的 accid
channelId number 离开的房间 id
返回类型 方法名 说明
promise netcall.stopRemoteStream 停止预览对方视频画面