本章将介绍如何实现多方音视频通话,多方视频通话的 API 调用时序见下图:
初始化
调用 JCMediaDevice.create() 和 JCMediaChannel.create() 以初始化实现多方通话需要的模块:
/// 声明对象
JCMediaDevice mMediaDevice;
JCMediaChannel mMediaChannel;
/// 初始化函数
public bool initialize(Context context) {
/// 1. 媒体类
mMediaDevice = JCMediaDevice.create(mClient, this);
/// 2. 媒体通道类
mMediaChannel = JCMediaChannel.create(client, mediaDevice, this);
}
其中:
JCMediaDevice create 方法中的 this 为实现 JCMediaDeviceCallback 接口的对象,用于将媒体设备相关的事件通知给上层。
JCMediaDeviceCallback 中的主要方法如下
//摄像头变化
public void onCameraUpdate()
{
}
//音频输出变化
public void onAudioOutputTypeChange(string audioOutputType)
{
}
JCMediaChannel create 方法中的 this 为实现 |JCMediaChannelCallback| 接口的对象,用于将频道中的相关事件通知给上层
JCMediaChannelCallback 中的主要方法如下
//自身状态变化回调
public void onMediaChannelStateChange(JCMediaChannelState state, JCMediaChannelState oldState)
{
}
//频道属性变化
public void onMediaChannelPropertyChange(JCMediaChannel.PropChangeParam propChangeParam)
{
}
//加入频道结果回调
public void onJoin(bool result, JCMediaChannelReason reason, string channelId)
{
}
//离开频道结果回调
public void onLeave(JCMediaChannelReason reason, string channelId)
{
}
//解散频道结果回调
public void onStop(bool result, JCMediaChannelReason reason)
{
}
//查询频道结果回调
public void onQuery(int operationId, bool result, JCMediaChannelReason reason, JCMediaChannelQueryInfo queryInfo)
{
}
//成员加入回调
public void onParticipantJoin(JCMediaChannelParticipant participant)
{
}
//成员离开回调
public void onParticipantLeft(JCMediaChannelParticipant participant)
{
}
//成员更新回调
public void onParticipantUpdate(JCMediaChannelParticipant participant, JCMediaChannelParticipant.ChangeParam changeParam)
{
}
//成员声音变化
public void onParticipantVolumeChange(JCMediaChannelParticipant participant)
{
}
加入频道
#. 调用 enableUploadAudioStream() 开启音频流。调用 enableUploadVideoStream() 开启视频流。
/// 1. 开启音频流
mMediaDeviceChannel.enableUploadAudioStream(true);
/// 2. 开启视频流
mMediaDeviceChannel.enableUploadVIdeoStream(true);
创建并加入频道,需要传入
channelIdOrUri
和 JCMediaChannel.JoinParam 。channelIdOrUri
表示频道 ID 或频道 Uri。JCMediaChannelJoinParam
中uriMode
参数设置为 true 时表示传入频道 Uri,设置其他参数时表示传入频道 ID。传入相同的频道 ID 或相同的频道 Uri 的用户会进入同一个频道。
mMediaChannel.join("222", null);
#. 加入频道后收到 onJoin() 回调。
public void onJoin(bool result, JCMediaChannelReason reason, String channelId) {
if (result) {
/// 加入频道成功
} else {
/// 加入频道失败
}
}
创建本地视频画面
加入频道后,调用 JCMediaChannel 中的 getParticipant() 获取频道内自身对象, 然后调用 JCMediaChannelParticipant 中的 startVideo() 方法打开本地视频预览。返回对象为 JCMediaDeviceVideoCanvas。(调用此方法会打开摄像头)
/// 打开本地视频预览
mMediaChannel.getSelfParticipant().startVideo(JCMediaDevice.RENDER_FULL_CONTENT, JCMediaChannel.PICTURESIZE_NONE);
创建远端视频画面
加入频道后,调用 JCMediaChannel 中的 getParticipants() 获取频道内所有成员对象。
然后调用 JCMediaChannelParticipant 类中的 startVideo() 获取远端视频画面。返回对象为 JCMediaDeviceVideoCanvas。
startVideo() 方法调用后,还需要调用 JCMediaChannel 中的 requestVideo() 方法请求频道中其他用户的视频流。
/// 获取所有成员对象
List<JCMediaChannelParticipant> participants = mMediaChannel.getSelfParticipant();
/// 调用创建视频画面的方法
participants.get(0).startVideo(JCMediaDevice.RENDER_FULL_CONTENT, JCMediaChannel.PICTURESIZE_NONE);
/// 请求远端视频流, 此处调用大尺寸视频窗口
mMediaChannel.requestVideo(participants.get(0), Large);
离开频道
调用 leave() 方法可以离开当前频道。
mMediaChannel.leave();
在多方视频通话中,离开频道还需要调用 stopVideo() 移除视频画面。
mParticipant.stopVideo();
离开频道后,自身收到 onLeave() 回调,其他成员同时收到 onParticipantLeft() 回调
/// 离开频道结果回调
public void onLeave(JCMediaChannelReason reason, String channelId) {
...
/// 销毁视频画面
mParticipant.stopVideo();
}
销毁本地和远端视频画面
在视频挂断后,调用 JCMediaChannelParticipant 里的 stopVideo() 销毁本地和远端视频画面。
mParticipant.stopVideo();
解散频道
如果想解散频道,可以调用下面的接口,此时所有成员都将被退出。
/// 结束频道
mMediaChannel.stop();
在多方视频通话中,离开频道还需要调用 stopVideo() 移除视频画面。
mParticipant.stopVideo();
解散频道后,发起结束的成员收到 onStop() 回调,其他成员同时收到 onLeave() 回调。 解散失败原因枚举值请参考 MediaChannelReason 。
public void onStop(bool result, JCMediaChannelReason reason) {
/// 销毁视频, canvas 为 JCMediaDeviceVideoCanvas 对象实例
mParticipant.stopVideo();
canvas = null;
}