iOS

# 视频管理

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

# 1. 控制视频流上传

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

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

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

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

示例代码:

// 关闭视频流发送
agent.enableUploadVideoStream(false);
// 开启视频流发送
agent.enableUploadVideoStream(true);
// 通话中成员属性更新回调
public void onMemberUpdate(JRTCRoomParticipant part, ChangeParam param) {
    if(param.video){
     if(part.isVideo) {
     	// 该成员打开了视频流
     } else {
     	// 该成员关闭了视频流
     }
    }
};

# 2. 视频属性设置

# 设置请求分辨率

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

/**
 * 获取视频请求尺寸
 *
 * 影响自己看其他成员的视频分辨率
 *
 * @return 视频请求尺寸
 */
public abstract JRTCVideoSize getRequestSize();

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

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

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

示例代码:

// 订阅视频流
JRTCVideoSize size = new JRTCVideoSize();
size.setWidth(720);
size.setHeight(1080);
agent.requestVideo(participant, size);

//取消订阅视频流
agent.unRequestVideo(participant);

订阅/取消订阅屏幕共享视频流,该接口可以在通话中调用实时生效,比如可以实时从订阅低分辨率视频流改成订阅高分辨率视频流

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

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

示例代码:

// 订阅屏幕共享视频流
JRTCVideoSize size = new JRTCVideoSize();
size.setWidth(720);
size.setHeight(1080);
agent.requestScreenVideo(size);

// 取消订阅屏幕共享视频流
guest.unRequestScreenVideo();

# SVC 设置说明

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

具体使用详见 SVC 说明 (opens new window)

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

/**
 * 设置 svc 分辨率,默认为 "1 180 250 360 600 720 1400"
 *
 * @note 当参数 {@link #setVideoDefinition(int)} videoDefinition} 为 {@link JRTCRoom#DEFINITION_CUSTOM DEFINITION_CUSTOM} 时有效
 *
 * 用于自定义分层参数和码率
 *
 * 格式:
 * 高度公约数 第一层高倍数 第一层码率 第二层高倍数 第二层码率 第三层高倍数 第三层码率 第四层高倍数 第四层码率 <br>
 * 说明 <br>
 * 1)默认宽高比16:9,即 @ref  wholeRatio <br>
 * 2)编码宽高最后被裁成16整除 <br>
 * 例如 "1 180 250 360 600 720 1400" <br>
 * 第一层 分辨率 宽320(180*1/9*16)高 180(180*1); 码率250kbps <br>
 * 第二层 分辨率 宽640(360*1/9*16)高 360(360*1); 码率600kbps <br>
 * 第三层 分辨率 宽1280(720*1/9*16)高 720(720*1); 码率1400kbps <br>
 * 此情况下只有三层,若需要四层,则需补充为 "1 180 250 360 600 720 1400 1080 1600" <br>
 * 第四层 分辨率 宽1920(1080*1/9*16)高 1080(1080*1); 码率1600kbps <br>
 */
public void setSvcResolution(String svcResolution);

示例代码:

// 创建呼叫配置参数
JRTCCallCenterCallParam param = new JRTCCallCenterCallParam();
// 配置SVC
param.setSvcResolution("1 180 250 360 600 720 1400 1080 1600");
// 发起呼叫
guest.recall("10086", param);

# 设置本地视频宽高比

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

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

示例代码:

void onCallStateChanged(@GuestCallStateChangeType int type, @CallIncomingType int incomingType, JRTCInviter inviter, @CallTermReason int reason) {
    if (type == JRTCCallCenter.GUEST_CHANGE_TYPE_TALKING) {
        // 注:在通话建立后调用才能生效
        agent.setRatio(0.5625f);
    }
}

# 设置房间视频清晰度

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

/**
 * 设置通话视频清晰度,主要通过修改 {@link #setSvcResolution(String) svcResolution} 参数和 {@link #setMaxFrameRate(int) maxFrameRate} 参数调整清晰度,
 * 默认为 {@link JRTCRoom#DEFINITION_CUSTOM DEFINITION_CUSTOM}
 */
public void setVideoDefinition(@JRTCRoom.VideoDefinition int videoDefinition)

示例代码:

// 创建呼叫配置参数
JRTCCallCenterCallParam param = new JRTCCallCenterCallParam();
// 设置通话视频清晰为流畅模式,低帧率
param.setVideoDefinition(JRTCRoom.DEFINITION_FLUENCY_FRAME_LOW);
// 发起呼叫
guest.recall("10086", param);

# 3. 视频渲染管理

# 渲染视频画面

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

/**
 * 开始本端视频渲染
 *
 * 获取本端视频预览对象 JRTCMediaDeviceVideoCanvas,通过此对象能获得视图用于UI显示
 * @note
 * 调用此方法时需要保证默认摄像头不为空,即 {@link #defaultCamera} 不为空,否则将直接返回 null
 * @param renderType 渲染模式:
 * - {@link #RENDER_FULL_SCREEN RENDER_FULL_SCREEN} : 铺满窗口,会有裁剪
 * - {@link #RENDER_FULL_CONTENT RENDER_FULL_CONTENT} : 全图像显示,会有黑边
 * - {@link #RENDER_FULL_AUTO RENDER_FULL_AUTO} : 自适应
 * @param useTextureView 是否使用TextureView作为视图控件,默认SurfaceView作为视图控件
 * @return
 * - JRTCMediaDeviceVideoCanvas 对象: 开始自身视频渲染成功
 * - null: 开始自身视频渲染失败
 */
public abstract JRTCMediaDeviceVideoCanvas startCameraVideo(@RenderType int renderType, boolean useTextureView);

/**
 * 开始远端的视频渲染
 *
 * 获取其他端的视频预览对象 JRTCMediaDeviceVideoCanvas,通过此对象能获得视图用于UI显示
 *
 * @param streamId 视频流ID
 * @param renderType  渲染模式:
 * - {@link #RENDER_FULL_SCREEN RENDER_FULL_SCREEN} : 铺满窗口,会有裁剪
 * - {@link #RENDER_FULL_CONTENT RENDER_FULL_CONTENT} : 全图像显示,会有黑边
 * - {@link #RENDER_FULL_AUTO RENDER_FULL_AUTO} : 自适应
 * @return
 * - JRTCMediaDeviceVideoCanvas 对象: 开始自身视频渲染成功
 * - null: 开始自身视频渲染失败
 */
public abstract JRTCMediaDeviceVideoCanvas startVideo(String streamId, @RenderType int renderType);

/**
 * 开始其他端的视频渲染
 *
 * 获取其他端的视频预览对象 JRTCMediaDeviceVideoCanvas,通过此对象能获得视图用于UI显示
 *
 * @param streamId 视频流ID
 * @param renderType  渲染模式:
 * - {@link #RENDER_FULL_SCREEN RENDER_FULL_SCREEN} : 铺满窗口,会有裁剪
 * - {@link #RENDER_FULL_CONTENT RENDER_FULL_CONTENT} : 全图像显示,会有黑边
 * - {@link #RENDER_FULL_AUTO RENDER_FULL_AUTO} : 自适应
 * @param useTextureView 是否使用TextureView作为视图控件,默认SurfaceView作为视图控件
 * @return
 * - JRTCMediaDeviceVideoCanvas 对象: 开始自身视频渲染成功
 * - null: 开始自身视频渲染失败
 */
public abstract JRTCMediaDeviceVideoCanvas startVideo(String streamId, @RenderType int renderType, boolean useTextureView);

示例代码:

//渲染本地视频画面
JRCMediaDeviceVideoCanvas localCanvas = 
    mediaDevice.startCameraVideo(JRTCMediaDevice.RENDER_FULL_SCREEN);
viewGroup.addView(localCanvas.getVideoView());

//渲染成员视频画面
JRTCMediaDeviceVideoCanvas canvas = mediaDevice.startVideo("streamId", JRTCMediaDevice.RENDER_FULL_CONTENT);
view.addView(canvas.getVideoView());

# 停止视频渲染

/**
 * 停止视频
 *
 * @param canvas JRTCMediaDeviceVideoCanvas 对象,由 {@link #startVideo startVideo} 或 {@link #startCameraVideo startCameraVideo} 接口返回
 */
public abstract void stopVideo(JRTCMediaDeviceVideoCanvas canvas);

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

示例代码:

//停止视频渲染
mediaDevice.stopVideo(canvas);

# 视频渲染回调

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

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

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

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

# 4. 视频截图

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

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

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

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

示例代码:

// 截取指定 视频流ID的帧图片并且保存到指定路径
// 视频流,可以是本地视频流、对端视频流或者屏幕共享视频流
mediaDevice.snapshotWithStreamId("user_renderId", "file_save_path");
// 截图完成回调
public void onSnapshotComplete(String file, int width, 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 error 异常信息
 */
void onVideoError(String error);