# 高级媒体流管理

用于管理视频会议的媒体流相关功能。

# 本地录制

# 开启本地录制

/**
 * @brief 开关会议录制(本地录制),内部根据状态决定是否开启
 *
 * @param enable 是否开启视频录制, true开始录制, false结束录制
 * @param recordLocalParams 录制参数
 * @see JCConferenceRecordLocalParams
 * @return 返回 true 表示正常执行调用流程,false 表示调用异常
 */
- (BOOL)enableLocalRecord:(BOOL)enable recordLocalParams:(JCConferenceRecordLocalParams*)recordLocalParams;

recordLocalParams的值有:

/**
 * @brief 录制帧率,默认18
 */
@property (nonatomic, assign) int frameRate;

/**
 * @brief 媒体录制视频合并模式,默认智能分屏模式,取值枚举如下:
 * JCConferenceVideoMergeModeMergeScreen(平铺屏幕共享和所有视频);
 * JCConferenceVideoMergeModeMergePlateForm(将屏幕共享和所有视频内容合并);
 * JCConferenceVideoMergeModeMergeSpeaker(将屏幕共享和焦点视频内容合并);
 * JCConferenceVideoMergeModeRealtimeVideo(只发送当前焦点视频);
 * JCConferenceVideoMergeModeMergeIntelligentLayout(智能分屏, 默认值);
 * JCConferenceVideoMergeModeScreenSharing(只发送屏幕共享);
 */
@property (nonatomic, assign) JCConferenceVideoMergeMode mergeMode;

/**
 * @brief  MergeMode为智能分屏模式下的布局样式(无屏幕共享),取值枚举如下:
 * JCConferenceIntelligentMergeModeFreeLayout(自由布局);
 * JCConferenceIntelligentMergeModeRectLayout(矩形布局);
 * JCConferenceIntelligentMergeModeBigSmallx2(大小屏放大2倍);
 * JCConferenceIntelligentMergeModeBigSmallx3(大小屏放大3倍);
 * JCConferenceIntelligentMergeModeBigSmallx4(大小屏放大4倍);
 * JCConferenceIntelligentMergeModeBigSmallx5(大小屏放大5倍);
 * JCConferenceIntelligentMergeModeBigSmallx6(大小屏放大6倍);
 * JCConferenceIntelligentMergeModeBigSmallx7(大小屏放大7倍);
 * JCConferenceIntelligentMergeModeBigSmallx8(大小屏放大8倍);
 * JCConferenceIntelligentMergeModeBigSmallx9(大小屏放大9倍);
 * JCConferenceIntelligentMergeModeBigSmallx10(大小屏放大10倍);
 * JCConferenceIntelligentMergeModeBigSmallTop(大小屏放大到顶部);
 * JCConferenceIntelligentMergeModeBigSmallBottom(大小屏放大到底部);
 * JCConferenceIntelligentMergeModeDivideLayout(绝对等分模式);
 * JCConferenceIntelligentMergeModeDivideLayoutNoangle(绝对等分模式不带图像角度);
 */
@property (nonatomic, assign) JCConferenceIntelligentMergeMode intelligentMergeMode;

/**
 * @brief MergeMode为智能分屏模式下的布局样式(有屏幕共享),取值枚举如下:
 * JCConferencelSrcMergeModeScreenShare(屏幕共享);
 * JCConferenceSrcMergeModePlateForm(将屏幕共享和所有视频内容合并, 所有视频不覆盖屏幕共享);
 * JCConferenceSrcMergeModePlateFormCover(将屏幕共享和所有视频内容合并, 所有视频覆盖在屏幕共享上);
 * JCConferenceSrcMergeModeSpeaker(将屏幕共享和焦点视频内容合并);
 * JCConferenceSrcMergeModeWithoutScreenShare(忽略屏幕共享);
 */
@property (nonatomic, assign) JCConferenceScsMergeMode scsMergeMode;

/**
 * @brief 视频的宽度,默认640
 */
@property (nonatomic, assign) int videoWidth;

/**
 * @brief 视频的高度,默认360
 */
@property (nonatomic, assign) int videoHeight;

/**
 * @brief 码率,默认0,自适应调节
 */
@property (nonatomic, assign) int iBitRate;

/**
 * @brief 保存的文件路径,必须包含文件名(xxx.mp4或者只录音的话xxx.aac)
 */
@property (nonatomic, copy, nonnull) NSString *filePath;

/**
 * @brief 是否录制视频,默认true
 */
@property (nonatomic) BOOL recVideo;

/**
 * @brief 是否录制音频,默认true
 */
@property (nonatomic) BOOL recAudio;

/**
 * @brief 录制是否包含自己,默认true
 */
@property (nonatomic) BOOL includeSelf;

示例代码:

if(conference.getConferenceInfo.getLocalRecordingState) {
  //开始录制
  JCConferenceRecordLocalParams *recordRecordLocalParams= [[JCConferenceRecordLocalParams alloc] init];
  [recordRecordLocalParams setFilePath:@"/juphoon/01.mp4"];
  ...
  [conference enableLocalRecord:true recordLocalParams:recordRecordLocalParams];
}  else {
  //关闭录制
}

# 关闭本地录制

/**
 * @brief 开关会议录制(本地录制),内部根据状态决定是否开启
 *
 * @param enable 是否开启视频录制, true开始录制, false结束录制
 * @param recordLocalParams 录制参数
 * @see JCConferenceRecordLocalParams
 * @return 返回 true 表示正常执行调用流程,false 表示调用异常
 */
- (BOOL)enableLocalRecord:(BOOL)enable recordLocalParams:(JCConferenceRecordLocalParams*)recordLocalParams;

示例代码:

if(conference.getConferenceInfo.getLocalRecordingState) {
  //开始录制
}  else {
  //关闭录制
  JCConferenceRecordLocalParams *recordRecordLocalParams= [[JCConferenceRecordLocalParams alloc] init];
  [conference enableLocalRecord:false recordLocalParams:recordRecordLocalParams];
}

# 服务器录制

# 录制准备

如果需要进行服务器音视频录制,需要在创建会议之前设置录制参数,然后在创建会议的时候传入录制参数。

示例代码:

// 设置录制参数
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
...其他参数...
[dic setObject:@YES forKey:JCConferenceConfigRemoteRecord]; YES需要服务器录制, 默认NO
[dic setObject:@YES forKey:JCConferenceConfigFixedResolution]; YES固定分辨率、码率, 默认NO
// 创建频道
[conference start:confNumber video:true config:dic];
// 或者首个成员加入频道不存在则创建
[dic setObject:@"1" forKey:JCConferenceConfigCreateAndJoin]; 创建设置 "1",不创建设置 "0",默认不创建
[conference join:confNumber video:true config:dic];

# 开始录制

根据目前的录制状态来判断是否可以开启音视频录制。

/**
 *  @brief 开关服务器视频录制
 *  @param enable 是否开启录制
 *  @param recordRemoteParams 录制参数
 *  @return 返回 true 表示正常执行调用流程,false 表示调用异常
 */
-(bool)enableRemoteRecord:(bool)enable recordRemoteParams:(JCConferenceRecordRemoteParams*)recordRemoteParams;

当会议中收到回调接口 onCommandReceivedResult (opens new window) 的回调并且 JCConferenceCommandInfo (opens new window) 参数的type属性值等于 JCConferenceCommandInfo.COMMANDINFO_DELIVERY_JOIN 后,表示录制就绪,即可开始录制。

JCConferenceRecordRemoteParams (opens new window) 有以下属性:

/**
 * @brief 录制是否包含视频,false的时候服务器为录音文件aac,默认为true
 */
@property (nonatomic) BOOL recordVideo;

/**
 * @brief媒体录制视频合并模式,取值枚举如下:
 * JCConferenceVideoMergeModeMergeScreen(平铺屏幕共享和所有视频);
 * JCConferenceVideoMergeModeMergePlateForm(将屏幕共享和所有视频内容合并);
 * JCConferenceVideoMergeModeMergeSpeaker将屏幕共享和焦点视频内容合并);
 * JCConferenceVideoMergeModeRealtimeVideo(只发送当前焦点视频);
 * JCConferenceVideoMergeModeMergeIntelligentLayout(智能分屏, 默认值);
 * JCConferenceVideoMergeModeScreenSharing(只发送屏幕共享);
 */
@property (nonatomic, assign) JCConferenceVideoMergeMode mergeMode;

/**
 * @brief 录制帧率,默认18
 */
@property (nonatomic, assign) int frameRate;

/**
 * @brief 视频的宽度,默认640
 */
@property (nonatomic, assign) int videoWidth;

/**
 * @brief 视频的高度,默认360
 */
@property (nonatomic, assign) int videoHeight;

/**
 * @brief 码率,默认0,自适应调节
 */
@property (nonatomic, assign) int iBitrate;

/**
 * @brief 其他参数, json格式
 */
@property (nonatomic, copy) NSString* extraInfo;

/**
 * @brief 水印串
 */
@property (nonatomic, strong) NSMutableDictionary* watermarkTextDic;

///以下存储参数
/**
 * @brief 存储环境 aws qiniu ftp等, 默认aws
 */
@property (nonatomic, copy) NSString* protocol;

/**
 * @brief 接入地址,ftp模式下例:ftp://127.0.0.1:21
 */
@property (nonatomic, copy) NSString* uploadEndpoint;

/**
 * @brief 存储环境相关key, ftp模式传ftp服务器登录名
 */
@property (nonatomic, copy) NSString* accessKey;

/**
 * @brief 存储环境相关key, ftp模式传ftp服务器登录密码
 */
@property (nonatomic, copy) NSString* secretKey;

/**
 * @brief 存储环境相关key
 */
@property (nonatomic, copy) NSString* bucketName;

/**
 * @brief 存储文件名, ftp模式下可以带路径如:juphoon/1.mp4
 */
@property (nonatomic, copy) NSString* fileName;

/**
 * @brief 分割文件大小
 */
@property (nonatomic, assign) int splitFileSize;

/**
 * @brief 对应portal上配置的录制样式的名字, 不传则用默认
 */
@property (nonatomic, copy) NSString* recLayoutType;

onCommandReceivedResult (opens new window) 回调接口:

/**
* @brief 收到会议属性变化或会议其他通知
*
* @param type 消息类型
*
*/
- (void)onCommandReceivedResult:(JCConferenceCommandInfo *)commandInfo;

示例代码:

JCConferenceRecordRemoteParams *recordRemoteParams = [[JCConferenceRecordRemoteParams alloc] init];
[recordRemoteParams setBucketName:@"lr23_00_record.00"];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:@"6226090219298788 龚子清" forKey:@"name1"];
[dic setValue:@"601611 心悦人生综合保险产品计划" forKey:@"name2"];
[dic setValue:@"80231222 姓名" forKey:@"name3"];
[recordRemoteParams setWatermarkTextDic:dic];
[recordRemoteParams setFileName:@"202002042015_av.mp4"];

// 根据音视频录制状态判断是否开启音视频录制
if (conference.getConferenceInfo.remoteRecordState == JCConferenceRecordStateReady) {
    // 可以开启音视频录制
    [conference enableRemoteRecord:true recordB01Params:recordB01Params];
}

//录制开启后会收到onCommandReceivedResult回调
- (void)onCommandReceivedResult:(JCConferenceCommandInfo *)commandInfo {
    if(commandInfo.type == JCConferenceCommandInfoTypeDeliveryJoin){
        //执行开启录制成功后的操作
    }
}

# 结束录制

如果需要结束服务器音视频录制,调用接口 enableRemoteRecord (opens new window),并且设置参数 enable 设置为 false

/**
 *  @brief 开关服务器视频录制
 *  @param enable 是否开启屏幕录制
 *  @param recordRemoteParams 录制参数
 *  @return 返回 true 表示正常执行调用流程,false 表示调用异常
 */
-(bool)enableRemoteRecord:(bool)enable recordRemoteParams:(JCConferenceRecordRemoteParams*)recordRemoteParams;

当会议中收到回调接口 onCommandReceivedResult (opens new window) 的回调并且 JCConferenceCommandInfo (opens new window) 参数的type属性值等于 JCConferenceCommandInfo.COMMANDINFO_DELIVERY_JOIN 后,表示录制关闭。

示例代码:

// 根据音视频录制状态判断是否关闭音视频录制
if (conference.getConferenceInfo.remoteRecordState == JCConferenceRecordStateRunning) {
    // 可以关闭音视频录制
    [conference enableRemoteRecord:false recordB01Params:recordB01Params];
}

//录制关闭后会收到onCommandReceivedResult回调
- (void)onCommandReceivedResult:(JCConferenceCommandInfo *)commandInfo {
    if(commandInfo.type == JCConferenceCommandInfoTypeDeliveryJoin){
        //执行关闭录制后的操作
    }
}

# 获取录制状态

录制状态可通过 conference.getConferenceInfo().getRemoteRecordState 属性获得。

录制状态枚举:

/// 无法进行视频录制
JCConferenceRecordStateNone,
/// 可以开启视频录制
JCConferenceRecordStateReady,
/// 视频录制中
JCConferenceRecordStateRunning,

示例代码:

// 根据音视频录制状态判断是否开启音视频录制
if (conference.getConferenceInfo.remoteRecordState == JCConferenceRecordStateNone) {
    // 无法进行音视频录制
} else if (conference.getConferenceInfo.remoteRecordState == JCConferenceRecordStateReady) {
    // 可以开启音视频录制
    [conference enableRemoteRecord:true recordB01Params:recordB01Params];
} else if (conference.getConferenceInfo.remoteRecordState == JCConferenceRecordStateRunning) {
    // 音视频录制中,可以关闭音视频录制
    [conference enableRemoteRecord:false recordB01Params:recordB01Params];
}

# CDN推流

CDN 推流服务适用于各类音视频直播场景,如企业级音视频会议、赛事、游戏直播、在线教育、娱乐直播等, CDN 推流集成简单高效,开发者只需调用相关 API 即可将 CDN 推流无缝对接到自己的业务应用中。

# 准备工作

如果需要开启 CDN 推流,需要在创建会议之前设置 CDN 地址。

// 设置录制参数
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
...其他参数...
[dic setObject:@"推流地址" forKey:JCConferenceConfigCdn];
// 创建频道
[conference start:confNumber video:true config:dic];
// 或者首个成员加入频道不存在则创建
[dic setObject:@"1" forKey:JCConferenceConfigCreateAndJoin]; 创建设置 "1",不创建设置 "0",默认不创建
[conference join:confNumber video:true config:dic];

# 开启 CDN 推流

只有 CDN 当前状态为 CConferenceCdnState.CDN_STATE_READY 时才可以进行 CDN 推流。其中,CDN 推流状态有以下几种:

/// 无法进行Cdn推流
JCConferenceCdnStateNone,
/// 可以开启Cdn推流
JCConferenceCdnStateReady,
/// Cdn推流中
JCConferenceCdnStateRunning,

开启 CDN 推流调用如下接口:

/**
 *  @brief  开关CDN推流,内部根据状态决定是否开启
 *  @return 返回 true 表示正常执行调用流程,false 表示调用异常
 */
- (bool)enableCdn;

当会议中收到回调接口 onCommandReceivedResult (opens new window) 的回调并且 JCConferenceCommandInfo 参数的 type 属性值等于 JCConferenceCommandInfo.COMMANDINFO_DELIVERY_JOIN 后,表示 CDN 已开启。

onCommandReceivedResult (opens new window) 回调接口:

/**
* @brief 收到会议属性变化或会议其他通知
*
* @param type 消息类型
*
*/
- (void)onCommandReceivedResult:(JCConferenceCommandInfo *)commandInfo;

示例代码:

// 根据CDN推流状态判断是否开启推流
if (conference.cdnState == JCConferenceCdnState.JCConferenceCdnStateReady) {
    // 可以开启 CDN 推流
    [conference enableCdn];
}

//CDN开启后会收到onCommandReceivedResult回调
- (void)onCommandReceivedResult:(JCConferenceCommandInfo *)commandInfo {
    if(commandInfo.type == JCConferenceCommandInfoTypeDeliveryJoin){
        //执行推流成功后的操作
    }
}

# 关闭 CDN 推流

关闭 CDN 推流调用如下接口:

/**
 *  @brief  开关CDN推流,内部根据状态决定是否开启
 *  @return 返回 true 表示正常执行调用流程,false 表示调用异常
 */
- (bool)enableCdn;

当会议中收到回调接口 onCommandReceivedResult (opens new window) 的回调并且 JCConferenceCommandInfo 参数的 type 属性值等于JCConferenceCommandInfo.COMMANDINFO_DELIVERY_JOIN 后,表示 CDN 已关闭。

示例代码:

// 根据CDN推流状态判断是否关闭推流
if (conference.cdnState == JCConferenceCdnState.JCConferenceCdnStateRunning) {
    // 关闭 CDN 推流
    [conference enableCdn];
}

//CDN关闭后会收到onCommandReceivedResult回调
- (void)onCommandReceivedResult:(JCConferenceCommandInfo *)commandInfo {
    if(commandInfo.type == JCConferenceCommandInfoTypeDeliveryJoin){
        //执行关闭推流后的操作
    }
}

# Sip 呼叫

# 邀请 Sip 用户

sip 呼叫用于对接 Polycom 会议。

/**
 * @brief           邀请Sip用户,一般用于对接落地网关等
 *
 * @param sipParam  邀请sip用户入会的配置参数
 * @return          成功返回值大于等于0,返回-1表示接口调用失败,与 onInviteSipUserResult 回调中的 operationId 对应
 */
-(int)inviteSipUser:(JCConferenceSipInviteInfo*)sipParam;

其中 JCConferenceSipInviteInfo (opens new window) 类有如下属性:

/**
 *  @brief 一般为号码(必填)
 */
@property (nonatomic, copy) NSString* userId;

/**
 *  @brief sip用户加入会议后的昵称
 */
@property (nonatomic, copy) NSString* displayName;

/**
 *  @brief UserId是号码设false,是sipUri设true
 */
@property (nonatomic) bool isSipUri;

/**
 *  @brief 是否视频接入
 */
@property (nonatomic) bool isVideo;

示例代码:

JCConferenceSipInviteInfo *sipInfo = [[JCConferenceSipInviteInfo alloc] init];
sipInfo.userId = @"13586556568";
sipInfo.displayName = @"ceshi"
sipInfo.isSipUri = false;
sipInfo.isVideo = true;
int operationId = [conference inviteSipUser:sipInfo];

调用该方法后会收到 onInviteSipUserResult (opens new window) 回调,当接收到的参数 resulttrue 时,表示邀请 Sip 用户成功,否则邀请失败;operationId 对应调用 inviteSipUser 后返回的 operationId

/**
 * @brief 邀请Sip用户操作结果回调,成功后会触发 onParticipantJoin
 *
 * @param operationId 操作id对应调用 inviteSipUser 后返回的 operationId
 * @param result 操作结果 true表示成功,false表示失败
 * @param reason 操作原因
 */
-(void)onInviteSipUserResult:(int)operationId result:(bool)result reason:(int)reason;

# 对接 Polycom 会议

JCConferenceSipInviteInfo inviteInfo = [[JCConferenceSipInviteInfo alloc] init];
inviteInfo.userId = "sip:xxx@xconf.china.com";
inviteInfo.displayName = "显示名";
inviteInfo.dtmfPassword = "yyy";
inviteInfo.isVideo = true;
inviteInfo.isMcu = true;
inviteInfo.coreNetwork = "zh_polycom";
inviteInfo.isRoute = false;
inviteInfo.sipUri = true;

# 屏幕共享

屏幕共享可以让您和频道中的其他成员一起分享设备里的精彩内容,您可以在频道中利用屏幕共享的功能进行文档演示、在线教育演示、视频会议以及游戏过程分享等。

通过 ReplayKit 2 的系统库,实现屏幕共享,该库仅支持iOS 11.0 以上的系统进行共享系统的屏幕,iOS11及以下的系统只能共享应用内屏幕。

# 添加 Broadcast Upload Extension 扩展

步骤一:项目中选择 target,添加 extension,用于屏幕录制。

createExtension1.jpg

createExtension2.jpg

如上所示,在添加 extension 时选中 Broadcast Upload Extension 扩展进行添加。

步骤二:app 和 extension 加入同一个 app group 后,实现 extension 和宿主 app 间的数据共享,加入步骤如下图所示。

AddToSameAppGroup1.jpgAddToSameAppGroup2.jpgAddToSameAppGroup3.jpg

JCBroadcastSampleHandler (opens new window) 里实现了数据采集,并通过 socket 传输到宿主 app。

@interface JCBroadcastSampleHandler : NSObject

 /**
  * @brief broadcastStartedWithSetupInfo时调用,开启屏幕共享
  * @param appGroupId app和extension共同的groupId
  */
 + (void)broadcastStartedWithAppGroupId:(NSString *)appGroupId initWithSampleHandler:(RPBroadcastSampleHandler *)sampleHandler;

 /**
  * @brief processSampleBuffer时调用
  * @param sampleBuffer processSampleBuffer采集上来的sampleBuffer
  * @param sampleBufferType processSampleBuffer采集上来的sampleBufferType
  */
 + (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType;

 /**
  * @brief broadcastFinished时调用
  */
 + (void)broadcastFinished;

 /**
  * @brief broadcastResumed时调用
  */
 + (void)broadcastResumed;

 /**
  * @brief broadcastPaused时调用
  */
 + (void)broadcastPaused;

 @end

示例代码:

#import "SampleHandler.h"
#import <JMSDK/JMSDK.h>

@implementation SampleHandler

    - (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {
        [JCBroadcastSampleHandler broadcastStartedWithAppGroupId:@"group.com.juphoon.uploadExTest" initWithSampleHandler:self];
    }

    - (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
        [JCBroadcastSampleHandler processSampleBuffer:sampleBuffer withType:sampleBufferType];
    }

    - (void)broadcastFinished {
        [JCBroadcastSampleHandler broadcastFinished];
    }

@end

# 开启屏幕共享

开启屏幕共享,调用如下接口 enableScreenShare (opens new window),并且设置参数 enable 设置为 true

/**
 * @brief 开关屏幕共享
 * @param enable 是否开启屏幕共享
 * @param appGroupId  extension和app所处于的同一个groupId iOS11以上需要传,iOS11以下传空
 * @param preferredExtension 希望打开的extension的ID  iOS11以上需要传,iOS11以下传空
 * @return 返回 true 表示正常执行调用流程,false 表示调用异常
 */
- (bool)enableScreenShare:(bool)enable appGroupId:(NSString *)appGroupId preferredExtension:(NSString *)preferredExtension;

示例代码:

// 开启屏幕共享
[conference enableScreenShare:true appGroupId:@"group.com.juphoon.uploadExTest" preferredExtension:@"com.juphoon.conference.JCShare"];

收到 onCommandReceivedResult (opens new window) 回调,同时 commandInfo.type 为 JCConferenceCommandInfo.JCConferenceCommandInfoTypeScreenShareStart (opens new window) 时,表示成员开启屏幕共享,需要请求屏幕共享的视频流。

/**
 *  @brief              请求屏幕共享的视频流
 *  @param screenUri    屏幕分享uri
 *  @param pictureSize  视频请求尺寸类型
 *  @return             返回 true 表示正常执行调用流程,false 表示调用异常
 *  @see JCConferencePictureSize
 *  @warning 当 pictureSize 为 JCConferencePictureSizeNone 标识关闭请求
 */
- (bool)requestScreenVideo:(NSString *)screenUri pictureSize:(JCConferencePictureSize)pictureSize;

其中 pictureSize 的值有:

///初始值
JCConferencePictureSizeInit = -1,
/// 不请求
JCConferencePictureSizeNone,
/// 最小尺寸
JCConferencePictureSizeMin,
/// 小尺寸
JCConferencePictureSizeSmall,
/// 大尺寸
JCConferencePictureSizeLarge,
/// 最大尺寸
JCConferencePictureSizeMax,

请求屏幕共享的视频流后调用 JCMediaDevice (opens new window) 类中的 startVideo (opens new window) 接口,该接口能够返回 JCMediaDeviceVideoCanvas (opens new window) 这个视频对象类通过 JCMediaDeviceVideoCanvas.videoView (opens new window) 能够获取视频渲染视图。

/**
 *  @brief 获得预览视频对象,通过此对象能获得视图用于UI显示
 *  @param videoSource 渲染标识串,比如 JCMediaChannelParticipant JCCallItem 中的 renderId  JCConferenceParticipant 中的renderId

 *  @param type        渲染模式,@ref JCMediaDeviceRender
 *  @return JCMediaDeviceVideoCanvas 对象
 */
- (JCMediaDeviceVideoCanvas*)startVideo:(NSString*)videoSource renderType:(int)type;

其中 renderType 的值有:

/// 视频图像按比例填充整个渲染区域(裁剪掉超出渲染区域的部分区域)
JCMediaDeviceRenderFullScreen = 0,
/// 视频图像的内容完全呈现到渲染区域(可能会出现黑边,类似放电影的荧幕)
JCMediaDeviceRenderFullContent,
/// 自动
JCMediaDeviceRenderFullAuto,

onCommandReceivedResult (opens new window) 回调接口:

/**
* @brief 收到会议属性变化或会议其他通知
*
* @param type 消息类型
*
*/
- (void)onCommandReceivedResult:(JCConferenceCommandInfo *)commandInfo;

commandInfo.typeConferenceCommandInfo.JCConferenceCommandInfoTypeScreenShareStart (opens new window) 时,表示成员开启屏幕共享。

示例代码:

//屏幕共享开启后会收到onCommandReceivedResult回调
- (void)onCommandReceivedResult:(JCConferenceCommandInfo *)commandInfo {
    if(commandInfo.type == JCConferenceCommandInfo.JCConferenceCommandInfoTypeScreenShareStart){
        //执行开启屏幕共享成功后的操作
        _screen.canvas = [mediaDevice startVideo:conference.getConferenceInfo.screenRenderId renderType:JCMediaDeviceRenderFullContent];
        [conference requestScreenVideo:conference.getConferenceInfo.screenRenderId pictureSize:JCConferencePictureSizeLarge];
        [_renderView addSubview:_screen.canvas.videoView];
        ...
    }
}

您可以调用 JCMediaDevice 类中的 setScreenCaptureProperty 方法设置屏幕共享采集属性,包括采集的高度、宽度和帧速率。

/**
 *  @breif 设置屏幕共享采集属性
 *  @param width 采集宽度,默认640
 *  @param height 采集高度,默认360
 *  @param framerate 帧速率,默认10
 */
- (void)setScreenCaptureProperty:(int)width height:(int)height framerate:(int)framerate;

TIP

该方法可以在开启屏幕共享前调用,也可以在屏幕共享中调用;如果在屏幕共享中调用,则设置的采集属性要在下次屏幕共享开启时生效。

# 关闭屏幕共享

如果需要关闭屏幕共享,调用接口 enableScreenShare (opens new window),并且设置参数enable设置为false

/**
 * @brief 开关屏幕共享
 * @param enable 是否开启屏幕共享
 * @param appGroupId  extension和app所处于的同一个groupId iOS11以上需要传,iOS11以下传空
 * @param preferredExtension 希望打开的extension的ID  iOS11以上需要传,iOS11以下传空
 * @return 返回 true 表示正常执行调用流程,false 表示调用异常
 */
- (bool)enableScreenShare:(bool)enable appGroupId:(NSString *)appGroupId preferredExtension:(NSString *)preferredExtension;

关闭屏幕共享时,会议中的成员会收到回调 onCommandReceivedResult (opens new window)

// 关闭屏幕共享
[conference enableScreenShare:false appGroupId:@"" preferredExtension:@""];

//屏幕共享关闭后会收到onCommandReceivedResult回调
- (void)onCommandReceivedResult:(JCConferenceCommandInfo *)commandInfo {
    if(commandInfo.type == JCConferenceCommandInfo.JCConferenceCommandInfoTypeScreenShareStop){
        //执行关闭屏幕共享成功后的操作
        [conference requestScreenVideo:conference.getConferenceInfo.screenRenderId pictureSize:JCConferencePictureSizeNone];
        [mediaDevice stopVideo:_canvas];
        ...
    }
}

commandInfo.type 为 JCConferenceInfo.JCConferenceCommandInfoTypeScreenShareStop (opens new window) 时,表示成员关闭屏幕共享。

示例代码:

// 关闭屏幕共享
[conference enableScreenShare:false appGroupId:@"" preferredExtension:@""];

//屏幕共享关闭后会收到onCommandReceivedResult回调
- (void)onCommandReceivedResult:(JCConferenceCommandInfo *)commandInfo {
    if(commandInfo.type == JCConferenceCommandInfo.JCConferenceCommandInfoTypeScreenShareStop){
        //执行关闭屏幕共享成功后的操作
        [conference requestScreenVideo:conference.getConferenceInfo.screenRenderId pictureSize:JCConferencePictureSizeNone];
        [mediaDevice stopVideo:_canvas];
        ...
    }
}

# 屏幕共享使用操作

由于 ReplayKit 2仅支持 iOS 12.0 以上的机型进行系统屏幕共享, iOS12 及以下只能共享应用内屏幕。

iOS12 及以上机型开启屏幕共享。

ios12opera1.jpg

关闭屏幕共享如下图所示:

ios12opera2.jpg