iOS

# 视频管理

Juphoon 视频能力平台支持跨平台的一对一、多对多的通话模式的高清音视频通话,Juphoon RTC SDK 供业务灵活集成应用,实现视频管理能力。

# 1. 控制视频流上传

通话中的成员可通过调用 enableUploadVideoStream (opens new window) 方法来开启关闭发送本地视频流。

/**
 * 开启/关闭发送本地视频流
 *
 * 通话中调用该方法可开启或关闭发送本地视频流。开启后,通话中的其他成员将看见本端画面;关闭后,通话中的其他成员将看不见本端画面 <br>
 * 通话中调用此方法成功后,服务器会更新状态并同步给通话中所有成员,即所有成员会收到 {@link JRTCGuestCallback.onMemberUpdate:changeParam: onMemberUpdate} 或 {@link JRTCAgentCallback.onMemberUpdate:changeParam: onMemberUpdate} 回调,具体可关注 {@link JRTCRoomParticipant.video} 和 {@link JRTCRoomParticipantChangeParam.video} <br>
 * 通话中调用此方法不影响接收其他成员的视频流
 * @param enable 开启/关闭发送本地视频流
 * - true: 开启,即发送本地视频流
 * - false: 关闭,即不发送本地视频流
 * @return 接口调用结果
 * - true: 接口调用成功
 * - false: 接口调用异常
 */
- (bool)enableUploadVideoStream:(bool)enable;

通话中成员视频流变化通过实现 JRTCGuestCallback (opens new window) 中的 onMemberUpdate (opens new window) 接口上报。

/**
 * 通话中成员属性更新回调
 *
 * 常用的有 {@link JRTCRoomParticipantChangeParam.volume 音量值}、{@link JRTCRoomParticipantChangeParam.audio 音频上传状态}、{@link JRTCRoomParticipantChangeParam.video 视频上传状态}等。<br>
 * 例如当通话中有成员关闭视频传输,通话中所有成员都会收到此回调。
 * @param part 属性更新的成员对象
 * @param changeParam 更新的属性对象
 */
- (void)onMemberUpdate:(JRTCRoomParticipant *)part changeParam:(JRTCRoomParticipantChangeParam *)changeParam;

示例代码:

// 关闭视频流发送
[_guest enableUploadVideoStream:false];
// 开启视频流发送
[_guest enableUploadVideoStream:true];
// 通话中成员属性更新回调
- (void)onMemberUpdate:(JRTCRoomParticipant *)part changeParam:(JRTCRoomParticipantChangeParam *)changeParam {
    if (changeParam.video) {
        if (part.video) {
            //该成员视频流打开
        } else {
            //该成员视频流关闭
        }  
    } 
}

# 2. 视频属性设置

# 设置请求分辨率

在通话中修改对端画面的分辨率,这个参数结合访客 SVC 来使用可以实现通话中切换设置的分辨率。

/**
 * 订阅通话中其他成员的视频流
 *
 * @param participant   成员对象
 * @param videoSize   视频请求的尺寸,详见 @ref JRTCVideoSize
 * @return 接口调用结果
 * - true: 接口调用成功
 * - false: 接口调用异常
 */
- (bool)requestVideo:(JRTCRoomParticipant* __nonnull)participant videoSize:(JRTCVideoSize* __nonnull)videoSize;

/**
 * 取消订阅通话中其他成员的视频流
 * @param participant 成员对象
 * @return 接口调用结果
 * - true: 接口调用成功,会收到 {@link JRTCGuestCallback.onMemberUpdate:changeParam: onMemberUpdate} 回调,具体可关注 {@link JRTCRoomParticipantChangeParam.pictureSize pictureSize} 和 {@link JRTCRoomParticipant.videoSize videoSize} 属性
 * - false: 接口调用异常
 */
- (bool)unRequestVideo:(JRTCRoomParticipant* __nonnull)participant;

/**
 * 设置视频请求尺寸
 *
 * 在渲染画面前设置才有效,建议在通话开始前设置。
 * @param size 视频尺寸大小
 */
- (void)setRequestSize:(JRTCVideoSize *)requestSize;

示例代码:

// 订阅视频流
JRTCVideoSize *size = [[JRTCVideoSize alloc] init];
size.width = 720;
size.height = 1280;
[_guest requestVideo:p videoSize:size];
    
// 取消订阅视频流
[_guest unRequestVideo:p];

订阅/取消订阅屏幕共享视频流

/**
 * 订阅通话中屏幕共享的视频流
 *
 * @param videoSize 视频请求的尺寸,详见 @ref JRTCVideoSize
 * @return 接口调用结果
 * - true: 接口调用成功
 * - false: 接口调用异常
 */
- (bool)requestScreenVideo:(JRTCVideoSize* __nonnull)videoSize;

/**
 * 取消订阅通话中屏幕共享的视频流
 * @return 接口调用结果
 * - true: 接口调用成功
 * - false: 接口调用异常
 */
- (bool)unRequestScreenVideo;

示例代码:

// 订阅屏幕共享视频流
JRTCVideoSize *size = [[JRTCVideoSize alloc] init];
size.width = 720;
size.height = 1280;
[_guest requestScreenVideo: size];
    
// 取消订阅屏幕共享视频流
[_guest unRequestScreenVideo];

# SVC 设置说明

根据实际订阅需求和网络状况动态调整视频发送分辨率是视频通话的特性之一,SVC 可用于设置通话视频的每一层编码分辨率。该参数在发起呼叫时设置,且全局统一。

详见 SVC 说明 (opens new window)

可在访客发起呼叫时,通过呼叫参数 JRTCCallCenterCallParam (opens new window)svcResolution (opens new window) 属性进行设置,通话全局属性,只有发起呼叫用户设置有效。

/**
 * svc分辨率,默认为 "1 180 250 360 600 720 1400"
 *
 * 用于自定义分层参数和码率
 *
 * 格式:
 * 高度公约数 第一层高倍数 第一层码率 第二层高倍数 第二层码率 第三层高倍数 第三层码率 第四层高倍数 第四层码率 <br>
 * 说明
 * 1)默认宽高比16:9,即 wholeRatio
 * 2)编码宽高最后被裁成16整除
 * 例如 "1 180 250 360 600 720 1400"
 * 第一层 分辨率 宽320(180*1/9*16)高 180(180*1); 码率250kbps
 * 第二层 分辨率 宽640(360*1/9*16)高 360(360*1); 码率600kbps 
 * 第三层 分辨率 宽1280(720*1/9*16)高 720(720*1); 码率1400kbps 
 * 此情况下只有三层,若需要四层,则需补充为 "1 180 250 360 600 720 1400 1080 1600" 
 * 第四层 分辨率 宽1920(1080*1/9*16)高 1080(1080*1); 码率1600kbps 
 */
@property (nonatomic, copy) NSString *svcResolution;

示例代码:

// 创建呼叫配置参数
JRTCCallCenterCallParam *param = [[JRTCCallCenterCallParam alloc] init];
// 配置SVC
param.svcResolution = @"1 180 250 360 600 720 1400 1080 1600";
// 发起呼叫
[_guest call:@"10080" callParams:param];

# 设置本地宽高比

设置本端视频宽高比,用于适配不同屏幕的显示需求,需在通话建立后调用。

/**
* 设置本端视频宽高比
*
* 将自己的视频采集根据宽高比裁剪后进行发送,通话中其他成员收到的画面将是裁剪后的比例。<br>
* 该方法不影响其他成员的画面在本端的显示比例,也不影响其他成员相互之间的画面显示比例。<br>
* 必须 ***开始通话后*** 设置才能生效,即收到 {@link JRTCGuestCallback.onCallStateChanged:incomingType:inviter:termReason: onCallStateChanged} 回调且 type == GuestCallStateChangeTypeTalking 时设置才生效。
* @param ratio 视频宽高比
* @return 接口调用结果
* - true: 接口调用成功
* - false: 接口调用异常
*/
- (bool)setRatio:(float)ratio;

示例代码:

- (void)onCallStateChanged:(GuestCallStateChangeType)type incomingType:(CallIncomingType)incomingType inviter:(nullable JRTCInviter *)inviter termReason:(CallTermReason)reason {
    if (type == GuestCallStateChangeTypeTalking) {
        // 注:在通话建立后调用才能生效
        [_guest setRatio:9/16.0];
    }
}

# 设置房间视频清晰度

如果觉得设置 SVC 不好理解,可以直接设置属性 videoDefinition (opens new window) 来调整通话视频清晰度(一组已经定义的 SVC 和 帧率),VideoDefinitionType (opens new window) 详见 API 文档。

/**
 * 设置通话视频清晰度,主要通过修改 svcResolution 参数和 maxFrameRate 参数调整清晰度,
 * 默认为 DefinitionCustom
 */
@property (nonatomic, assign) VideoDefinitionType videoDefinition;

示例代码:

// 创建呼叫配置参数
JRTCCallCenterCallParam *param = [[JRTCCallCenterCallParam alloc] init];
// 设置通话视频清晰为流畅模式,低帧率
param.videoDefinition = DefinitionFluencyFrameLow;
// 发起呼叫
[_guest call:@"10080" callParams:param];

# 3. 视频渲染管理

# 渲染视频画面

/**
 * 开始本端视频渲染
 *
 * 获取本端视频预览对象 JRTCMediaDeviceVideoCanvas ,通过此对象能获得视图用于UI显示
 * @note
 * 调用此方法时需要保证默认摄像头不为空,即 @ref defaultCamera 不为空,否则将直接返回 nil
 * @param renderType 渲染模式:
 * - @ref JRTCMediaDeviceRenderFullScreen : 铺满窗口,会有裁剪
 * - @ref JRTCMediaDeviceRenderFullContent : 全图像显示,会有黑边
 * - @ref JRTCMediaDeviceRenderFullAuto : 自适应
 * @return
 * - JRTCMediaDeviceVideoCanvas 对象: 开始自身视频渲染成功
 * - nil: 开始自身视频渲染失败
 */
- (JRTCMediaDeviceVideoCanvas* __nullable)startCameraVideo:(JRTCMediaDeviceRender)renderType;

/**
 * 开始自身视频渲染
 *
 * 获取本端视频预览对象 JRTCMediaDeviceVideoCanvas ,通过此对象能获得视图用于UI显示
 * @note
 * 调用此方法时需要保证默认摄像头不为空,即 @ref defaultCamera 不为空,否则将直接返回 nil
 * @param type 渲染模式:
 * - @ref JRTCMediaDeviceRenderFullScreen : 铺满窗口,会有裁剪
 * - @ref JRTCMediaDeviceRenderFullContent : 全图像显示,会有黑边
 * - @ref JRTCMediaDeviceRenderFullAuto : 自适应
 * @param view 渲染视图控件
 * @return
 * - JRTCMediaDeviceVideoCanvas 对象: 开始自身视频渲染成功
 * - nil: 开始自身视频渲染失败
 */
- (JRTCMediaDeviceVideoCanvas* __nullable)startCameraVideo:(JRTCMediaDeviceRender)type view:(JCView* __nonnull)view;

/**
 * 开始其他端的视频渲染
 *
 * 获取其他端的视频预览对象 JRTCMediaDeviceVideoCanvas ,通过此对象能获得视图用于UI显示
 *
 * @param streamId 视频流ID
 * @param type  渲染模式:
 * - @ref JRTCMediaDeviceRenderFullScreen : 铺满窗口,会有裁剪
 * - @ref JRTCMediaDeviceRenderFullContent : 全图像显示,会有黑边
 * - @ref JRTCMediaDeviceRenderFullAuto : 自适应
 * @return
 * - JRTCMediaDeviceVideoCanvas 对象: 开始其他端视频渲染成功
 * - nil: 开始其他端视频渲染失败
 */
- (JRTCMediaDeviceVideoCanvas* __nullable)startVideo:(NSString* __nonnull)streamId renderType:(JRTCMediaDeviceRender)type;

/**
 * 开始其他端的视频渲染
 *
 * 获取其他端的视频预览对象 JRTCMediaDeviceVideoCanvas ,通过此对象能获得视图用于UI显示
 *
 * @param streamId 视频流ID
 * @param type  渲染模式:
 * - @ref JRTCMediaDeviceRenderFullScreen : 铺满窗口,会有裁剪
 * - @ref JRTCMediaDeviceRenderFullContent : 全图像显示,会有黑边
 * - @ref JRTCMediaDeviceRenderFullAuto : 自适应
 * @param view 渲染视图控件
 * @return
 * - JRTCMediaDeviceVideoCanvas 对象: 开始其他端视频渲染成功
 * - nil: 开始其他端视频渲染失败
 */
- (JRTCMediaDeviceVideoCanvas* __nullable)startVideo:(NSString* __nonnull)streamId renderType:(JRTCMediaDeviceRender)type view:(JCView* __nonnull)view;

示例代码:

// 渲染本地视频画面
JRTCMediaDeviceVideoCanvas *localCanvas = [_mediaDevice startCameraVideo:JRTCMediaDeviceRenderFullScreen];
localCanvas.videoView.frame = CGRectMake(0, 0, 100, 100);
[self.view addSubview:localCanvas.videoView];

// 渲染其他成员视图画面
JRTCMediaDeviceVideoCanvas *remoteCanvas = [_mediaDevice startVideo:@"streamId" renderType:JRTCMediaDeviceRenderFullScreen];
remoteCanvas.videoView.frame = CGRectMake(100, 100, 100, 100);
[self.view addSubview:remoteCanvas.videoView];

# 停止视频渲染

/**
 * 停止视频渲染
 * @param canvas JRTCMediaDeviceVideoCanvas 对象,由 {@link startVideo:renderType: startVideo} 或 {@link startCameraVideo: startCameraVideo} 接口返回
 */
- (void)stopVideo:(JRTCMediaDeviceVideoCanvas* __nonnull)canvas;

/**
 * 停止所有视频渲染
 */
- (void)stopAllVideos;

注:开启渲染后必须在结束通话等不需要时进行关闭,否则会造成内存泄漏

示例代码:

//停止视频渲染
[_mediaDevice stopVideo:canvas];
//停止所有视频渲染
[_mediaDevice stopAllVideo];

# 视频渲染回调

调用视频渲染接口后主要关注两个回调接口 onRenderReceived (opens new window)onRenderStart (opens new window)

使用场景举例:为了提升交互体验,可以在调用渲染接口后,UI 界面先显示 "视频加载中" 字样,等收到渲染开始接口时,再显示视频画面。

/**
 * 收到第一帧数据回调
 *
 * @param canvas 视图渲染对象
 * @param ratio 宽高比
 */
- (void)onRenderReceived:(JRTCMediaDeviceVideoCanvas*)canvas ratio:(CGFloat)ratio;

/**
 * 渲染开始回调
 *
 * @param canvas 视图渲染对象
 * @param ratio 宽高比
 */
- (void)onRenderStart:(JRTCMediaDeviceVideoCanvas*)canvas ratio:(CGFloat)ratio;

# 4. 视频截图

视频业务存在对当前通话截屏的业务操作,以便于记录用户的操作行为;详见 snapshotWithStreamId (opens new window)

/**
 * 截图
 *
 * @param streamId 要截图的视频流ID
 * @param path 要存放截图的文件路径
 * @return 接口调用结果
 * - true: 接口调用成功
 * - false: 接口调用异常
 */
- (bool)snapshotWithStreamId:(NSString* __nonnull)streamId path:(NSString* __nonnull)path;

结果通过实现 JRTCMediaDeviceCallback (opens new window) 中的 onSnapShotComplete (opens new window) 接口上报

/**
 * 截图完成回调
 *
 * @param file 截图路径
 * @param width 图片像素宽
 * @param height 图片像素高
 */
- (void)onSnapshotComplete:(NSString *)file width:(int)width height:(int)height;

示例代码:

// 截取指定视频流ID的帧图片并且保存到指定路径
// 视频流,可以是本地视频流、对端视频流或者屏幕共享视频流
[_mediaDevice snapshotWithStreamId:@"streamId" path:@"path"];
// 截图完成回调
- (void)onSnapshotComplete:(NSString *)file width:(int)width height:(int)height {
 	//截图完成,可以从文件路径获取截图文件进行后续操作 
}

# 5. 视频采集回调

当打开本端摄像头视频预览或者打开本地屏幕采集时,通过实现 JRTCMediaDeviceCallback (opens new window) 中的 onVideoCaptureDidStart (opens new window) 接口能收到采集开始通知

/**
 * 视频采集开始回调
 *
 * @param streamId 视频流ID
 * @param ratio    宽高比
 */
void onVideoCaptureDidStart(String streamId, double ratio);

# 6. 视频异常回调

通过实现 JRTCMediaDeviceCallback (opens new window) 中的 onVideoError (opens new window) 接口来监听视频异常、采集异常、渲染错误等事件,具体原因查看参数 error 描述。

/**
 * 视频异常,渲染错误,包括摄像头采集错误、屏幕采集错误等回调
 *
 * @param errorType     异常类型
 * @param errorDetail 异常详细描述
 */
- (void)onVideoError:(JRTCMediaDeviceVideoErrorType)errorType errorDetail:(NSString *)errorDetail;