# 实现互动直播

本章将介绍如何实现视频互动直播,视频互动直播的 API 调用时序见下图:

../../../../_images/multivideoworkflow.jpg

# 初始化

调用 JCMediaDevice.create (opens new window)JCMediaChannel.create (opens new window) 以初始化实现多方通话需要的模块:

/// 声明对象
JCMediaDevice mMediaDevice;
JCMediaChannel mMediaChannel;

/// 初始化函数
public bool initialize(Context context) {

    /// 1. 媒体类
    mMediaDevice = JCMediaDevice.create(mClient, this);
    /// 2. 媒体通道类
    mMediaChannel = JCMediaChannel.create(client, mediaDevice, this);
}

其中:

JCMediaDeviceCallback 中的主要方法如下

//摄像头变化
public void onCameraUpdate()
{
}
//音频输出变化
public void onAudioOutputTypeChange(string audioOutputType)
{
}

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)
{
}

# 角色设置

加入频道前要先进行角色的设置。其中角色设置包括主播和观众。 角色值可以根据 JCMediaChannel.CustomRole (opens new window) 枚举值进行自定义,例如

//自定义主播角色
JCMediaChannelCustomRole ROLE_BROASCASTER = JCMediaChannelConstants.CUSTOM_ROLE_0;
//自定义观众角色
JCMediaChannelCustomRole ROLE_AUDIENCE = JCMediaChannelConstants.CUSTOM_ROLE_1;

调用 setCustomRole (opens new window) 设置自己的角色以进入频道。

/// 设置角色,participant(第二个参数) 值为 null 代表设置自身的角色
mediaChannel.setCustomRole(ROLE_BROASCASTER, null);

# 加入频道

  1. 调用 enableUploadAudioStream (opens new window) 开启音频流。调用 enableUploadVideoStream (opens new window) 开启视频流。
/// 1. 开启音频流
mMediaDeviceChannel.enableUploadAudioStream(true);
/// 2. 开启视频流
mMediaDeviceChannel.enableUploadVIdeoStream(true);
  1. 创建并加入频道,需要传入 channelIdOrUriJCMediaChannel.JoinParam (opens new window)

    • channelIdOrUri 表示频道 ID 或频道 Uri。

    • JCMediaChannelJoinParamuriMode 参数设置为 true 时表示传入频道 Uri,设置其他参数时表示传入频道 ID。传入相同的频道 ID 或相同的频道 Uri 的用户会进入同一个频道。

    mMediaChannel.join("222", null);
    
  2. 加入频道后自身会收到 onJoin (opens new window) 回调。其他成员会收到 onParticipantJoin (opens new window) 回调。

public void onJoin(bool result, JCMediaChannelReason reason, String channelId) {
    if (result) {
        /// 加入频道成功
    } else {
        /// 加入频道失败
    }
}

# 创建本地视频画面

加入频道后,调用 JCMediaChannel (opens new window) 中的 getParticipant (opens new window) 获取频道内自身对象, 然后调用 JCMediaChannelParticipant (opens new window) 中的 startVideo (opens new window) 方法打开本地视频预览。返回对象为 JCMediaDeviceVideoCanvas (opens new window)。(调用此方法会打开摄像头)

/// 打开本地视频预览
mMediaChannel.getSelfParticipant().startVideo(JCMediaDeviceRenderMode.FULLCONTENT, JCMediaChannelPictureSize.LARGE);

# 创建远端视频画面

加入频道后,调用 JCMediaChannel (opens new window) 中的 getParticipants (opens new window) 获取频道内所有成员对象。

然后调用 JCMediaChannelParticipant (opens new window) 类中的 startVideo (opens new window) 获取远端视频画面。返回对象为 JCMediaDeviceVideoCanvas (opens new window)

startVideo (opens new window) 方法调用后,还需要调用 JCMediaChannel (opens new window) 中的 requestVideo (opens new window) 方法请求频道中其他用户的视频流。

/// 获取所有成员对象
List<JCMediaChannelParticipant> participants = mMediaChannel.getParticipants();
/// 调用创建视频画面的方法
participants.get(0).startVideo(JCMediaDeviceRenderMode.FULLCONTENT, JCMediaChannelPictureSize.LARGE);
/// 请求远端视频流, 此处调用大尺寸视频窗口
mMediaChannel.requestVideo(participants.get(0), Large);

# 离开频道

调用 leave (opens new window) 方法可以离开当前频道。

mMediaChannel.leave();

在多方视频通话中,离开频道还需要调用 stopVideo (opens new window) 移除视频画面。

mParticipant.stopVideo();

离开频道后,自身收到 onLeave (opens new window) 回调,其他成员同时收到 onParticipantLeft (opens new window) 回调

/// 离开频道结果回调

public void onLeave(JCMediaChannelReason reason, String channelId) {
    ...
    /// 销毁视频画面
    mParticipant.stopVideo();
}

# 销毁本地和远端视频画面

在视频挂断后,调用 JCMediaChannelParticipant (opens new window) 里的 stopVideo (opens new window) 销毁本地和远端视频画面。

mParticipant.stopVideo();

# 解散频道

如果想解散频道,可以调用下面的接口,此时所有成员都将被退出。

/// 结束频道
mMediaChannel.stop();

在多方视频通话中,离开频道还需要调用 stopVideo (opens new window) 移除视频画面。

mParticipant.stopVideo();

解散频道后,发起结束的成员收到 onStop (opens new window) 回调,其他成员同时收到 onLeave (opens new window) 回调。 解散失败原因枚举值请参考 MediaChannelReason (opens new window)

public void onStop(bool result, JCMediaChannelReason reason) {
    /// 销毁视频, canvas 为 JCMediaDeviceVideoCanvas 对象实例
    mParticipant.stopVideo();
    canvas = null;
}