# 实现视频双录

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

# 加入会议

通过 JCMediaChannelJoinParam (opens new window) 可在加入会议前设置是否参会最大人数,参会密码,最大分辨率,全局长宽比等。

JCMediaChannelJoinParam param = new JCMediaChannelJoinParam
    {
        UploadLocalAudio = true,//是否上传本地音频流
        UploadLocalVideo = true,//是否上传本地视频流
    };
MediaChannel.Join(channelIdt, param);

加入频道结果回调:

/// <summary>
/// 加入频道结果回调
/// </summary>
/// <param name="result">true表示加入成功,false表示加入失败</param>
/// <param name="reason">加入失败原因,在result为false时该值有效</param>
/// <param name="channelId">媒体频道标识</param>
void OnJoin(bool result, JCMediaChannelReason reason, string channelId, JCMediaChannel obj);

示例代码:

// 加入频道结果回调
void JCMediaChannelCallback.OnJoin(bool result, JCMediaChannelReason reason, string channelId, JCMediaChannel obj)
    if (result) {
        // 加入频道成功
    } else {
        // 加入频道失败
    }
}

TIP

当加入会议后可通过 MediaChannel.GetParticipants (opens new window) 获取已经在会议中的成员 然后渲染当前所有成员 requestVideo,startVideo

# 打开本地摄像头

  • 创建本地视图画面

加入频道后,如果想看到本地视图画面,需要打开摄像头以创建视图画面。

创建视图画面需要用到 JCMediaDevice (opens new window) 类和 JCMediaDeviceVideoCanvas (opens new window) 类。

进行视图渲染前可通过 获取摄像头列表 接口获取摄像头列表。

本地视图渲染调用 JCMediaDevice 类中的 startCameraVideo (opens new window) 接口。

该接口会打开摄像头

/// <summary>
/// 获取预览视频对象,通过此对象能获得视图用于UI显示
/// </summary>
/// <param name="camera">摄像头对象</param>
/// <param name="mode">渲染方式</param>
/// <returns>JCMediaDeviceVideoCanvas对象</returns>
public JCMediaDeviceVideoCanvas startCameraVideo(JCMediaDeviceCamera camera, JCMediaDeviceRenderMode mode)

TIP

调用该方法后,在挂断通话或者关闭摄像头时需要对应调用 stopVideo (opens new window) 方法停止视频。

示例代码:

// 获取摄像头列表
List<JCMediaDeviceCamera> cameraDevices = mediaDevice.cameraDevices;
// 创建本地视频画面对象
JCMediaDeviceVideoCanvas localCanvas = mediaDevice.startCameraVideo(cameraDevices[0], JCMediaDevice.JCMediaDeviceRenderMode.FULLCONTENT);
ImageBrush image = new ImageBrush(localCanvas.videoView);
image.Stretch = Stretch.Uniform;
this.label.Background = image;

# 新成员加入

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

/// <summary>
/// 成员加入回调
/// </summary>
/// <param name="participant">成员对象</param>
void onParticipantJoin(JCMediaChannelParticipant participant);

此时可以进行远端视图渲染并请求远端成员的视频流。

  • 远端视频渲染

远端渲染调用 startVideo (opens new window) 获取视频对象:

/// <summary>
/// 获得视频对象,通过此对象能获得视图用于UI显示
/// </summary>
/// <param name="videoSource">渲染标识串,比如JCMediaChannelParticipant JCCallItem中的renderId</param>
/// <param name="mode">渲染模式</param>
/// <returns>JCMediaDeviceVideoCanvas对象</returns>
public JCMediaDeviceVideoCanvas startVideo(string videoSource, JCMediaDeviceRenderMode mode)

TIP

调用该方法后,在挂断通话或者关闭摄像头时需要对应调用 stopVideo (opens new window) 方法停止视频。

  • 请求远端成员视频流

由于服务器默认是不转发视频数据的,所以如果想看到远端成员画面需要调用 requestVideo (opens new window) 接口请求远端成员的视频流。

/// <summary>
/// 请求频道中的其他用户视频流
/// 当pictureSize为None表示关闭请求
/// </summary>
/// <param name="participant">用户对象</param>
/// <param name="pictureSize">视频请求尺寸类型</param>
/// <returns>返回true表示调用成功,false表示调用失败</returns>
public bool requestVideo(JCMediaChannelParticipant participant, JCMediaChannelPictureSize pictureSize)

其中,视频尺寸 JCMediaChannelPictureSize 有以下几种:

名称 描述
None 不请求
Min 最小尺寸,160x90
Small 小尺寸,320x180,小窗口模式下可以使用小尺
Large 大尺寸,640x360
Max 最大尺寸,360P 的会议为 640x360 ,720P 的会议为 1280x720

TIP

您可以根据相应的窗口大小使用相应的视频尺寸,比如窗口的大小是 160x90,则应该使用 JCMediaChannelPictureSizeMin ,避免造成不必要的流量浪费和额外的功耗。

现在您可以开始多方视频通话了。

示例代码:

// 成员加入回调
public void onParticipantJoin(JCMediaChannelParticipant participant, JCMediaChannel obj) {
    // 创建远端视频画面对象,renderId来源JCMediaChannelParticipant对象
    List<JCMediaChannelParticipant> partps = mediaChannel.getParticipants();
    JCMediaChannelParticipant item = partps.get(0);
    String renderId = item.renderId;
    JCMediaDeviceVideoCanvas remoteCanvas = mediaDevice.startVideo(renderId, JCMediaDevice.JCMediaDeviceRenderMode.FULLSCREEN);
    ImageBrush image = new ImageBrush(remoteCanvas.videoView);
    image.Stretch = Stretch.Uniform;
    this.label.Background = image;
    // 请求远端视频流,participant为JCMediaChannelParticipant对象
    mediaChannel.requestVideo(participant, JCMediaChannelPictureSize.Large);
}

# 离开频道

如果想离开频道,可以调用下面的接口:

/// <summary>
/// 离开频道
/// </summary>
/// <returns>返回true表示调用成功,false表示调用失败</returns>
public bool leave()

示例代码:

// 离开频道
mediaChannel.leave();

如果是多方视频通话,则在离开频道后还需要调用 JCMediaDevice (opens new window) 类中的 stopVideo (opens new window) 接口移除视频画面。

/// <summary>
/// 停止视频
/// </summary>
/// <param name="canvas">JCMediaDeviceVideoCanvas对象,由startVideo获得</param>
public void stopVideo(JCMediaDeviceVideoCanvas canvas)

离开频道后,UI 监听回调离开的原因:

/// <summary>
/// 离开频道结果标识
/// </summary>
/// <param name="reason">离开原因</param>
/// <param name="channelId">媒体频道标识</param>
void onLeave(JCMediaChannelReason reason, string channelId, JCMediaChannel obj);

示例代码:

public void onLeave(JCMediaChannelReason reason, string channelId, JCMediaChannel obj)
{
    // 停止视频
    // 销毁canvas
}

# 成员离开

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

/// <summary>
/// 成员离开回调
/// </summary>
/// <param name="participant">成员对象</param>
/// <param name="reason">成员离开原因</param>
void OnParticipantLeft(JCMediaChannelParticipant participant, JCMediaChannelReason reason, JCMediaChannel obj);

# 结束会议

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

/// <summary>
/// 结束会议,所有成员都将被退出
/// </summary>
/// <returns>返回true表示调用成功,false表示调用失败</returns>
public bool stop()

示例代码:

// 结束会议
mediaChannel.stop();

关闭会议的结果通过 onStop (opens new window) 回调:

/// <summary>
/// 结束会议结果回调
/// </summary>
/// <param name="result">true 表示成功,false 表示失败</param>
/// <param name="reason">解散失败原因,当 result 为 false 时该值有效</param>
void onStop(bool result, JCMediaChannelReason reason);

示例代码:

public void onStop(bool result, JCMediaChannelReason reason, JCMediaChannel obj)
{
    // 停止视频
    // 销毁canvas
}