如下是一个总体接入流程,详细细节请参见 RTC服务开通指南。
public void startCall(String appId, String bid) { // 创建 RTC 引擎 mRTCVideo = RTCVideo.createRTCVideo(AppUtil.getApplicationContext(), appId, mVideoEventHandler, null, null); // 采集视频:分辨率 540*960,帧率 15fps,最大码率1520kbps,最小码率300kbps VideoEncoderConfig config = new VideoEncoderConfig(540, 960, 15, 1520, 300); mRTCVideo.setVideoEncoderConfig(config); // 设置视频帧方向 mRTCVideo.setVideoOrientation(VideoOrientation.Portrait); // 设置默认音频路由 mRTCVideo.setDefaultAudioRoute(AudioRoute.AUDIO_ROUTE_SPEAKERPHONE); // 设置本地视频画布 VideoCanvas canvas = new VideoCanvas(mLocalVideoRenderView, VideoCanvas.RENDER_MODE_HIDDEN); mRTCVideo.setLocalVideoCanvas(StreamIndex.STREAM_INDEX_MAIN, canvas); // 设置本地视频采集,移动端默认会开启前置摄像头。 if (userSetting.openCamera) { mRTCVideo.startVideoCapture(); } else { mRTCVideo.stopVideoCapture(); } // 设置本地音频采集 if (userSetting.openMic) { mRTCVideo.startAudioCapture(); } else { mRTCVideo.stopAudioCapture(); } }
private static final int MIX_ID = 19; public void startRinging() { mMixingManager = mRTCVideo == null ? null : mRTCVideo.getAudioMixingManager(); if (mMixingManager == null || mRinging.get()) { return; } // 音频场景设置为媒体 mRTCVideo.setAudioScenario(AudioScenarioType.AUDIO_SCENARIO_MEDIA); // 音频文件路径 String filePathInAssets = "call_receive.mp3"; String parentPath = AppUtil.getApplicationContext().getExternalFilesDir("assets").getAbsolutePath() + "/resource/"; File ringMusicFile = new File(parentPath, filePathInAssets); if (ringMusicFile.exists()) { // 开始响铃 startAudioMixing(ringMusicFile); } else { AppExecutors.networkIO().execute(() -> { boolean success = copyAssetFile(AppUtil.getApplicationContext(), filePathInAssets, ringMusicFile.getAbsolutePath()); if (success) { startAudioMixing(ringMusicFile); } }); } } public void stopRinging() { if (mMixingManager != null && mRinging.get()) { mMixingManager.stopAudioMixing(MIX_ID); mRinging.set(false); } } private void startAudioMixing(File ringMusicFile) { mMixingManager.startAudioMixing(MIX_ID, ringMusicFile.getAbsolutePath(), new AudioMixingConfig(AudioMixingType.AUDIO_MIXING_TYPE_PLAYOUT, -1)); mRinging.set(true); }
public int creteAndJoinRTCRoom(String token, String userId, String roomID, boolean autoPublish) { mRTCRoom = mRTCVideo.createRTCRoom(roomID); if (mRoomEventHandler != null) { mRTCRoom.setRTCRoomEventHandler(mRoomEventHandler); } RTCRoomConfig roomConfig = new RTCRoomConfig(ChannelProfile.CHANNEL_PROFILE_COMMUNICATION, autoPublish, true, true); return mRTCRoom.joinRoom(token, new UserInfo(userId, null), roomConfig); } // 远端用户加入房间后设置渲染画布。 public void onUserJoined(UserInfo userInfo, int elapsed) { Runnable runnable = () -> { setRemoteVideoCanvas(userInfo.getUid(), mLocalVideoView); }; AppExecutors.execRunnableInMainThread(runnable); } // 切换前后置摄像头 public void switchCamera() { if (mRTCVideo == null) { return; } CameraId targetId = mCameraId == CameraId.CAMERA_ID_FRONT ? CameraId.CAMERA_ID_BACK : CameraId.CAMERA_ID_FRONT; mRTCVideo.setLocalVideoMirrorType( cameraId == CameraId.CAMERA_ID_FRONT ? MirrorType.MIRROR_TYPE_RENDER_AND_ENCODER : MirrorType.MIRROR_TYPE_NONE); mRTCVideo.switchCamera(targetId); mCameraId = targetId; } // 设置远端渲染画布 public void setRemoteVideoCanvas(String remoteUserId, TextureView view) { if (mRTCVideo == null || TextUtils.isEmpty(remoteUserId)) { return; } VideoCanvas canvas = new VideoCanvas(view, VideoCanvas.RENDER_MODE_HIDDEN); mRTCVideo.setRemoteVideoCanvas(new RemoteStreamKey(mRoomId, remoteUserId, StreamIndex.STREAM_INDEX_MAIN), canvas); }
用户加入 RTC 房间后,onNetworkQuality
每 2 s 回调一次,返回本地用户和已订阅远端用户的上下行网络质量评分。 RTC 根据 NetworkQuality 的数值,对网络状况进行判定,在网络质量不好时进行提示。
onNetworkTypeChanged(kNetworkTypeDisconnected)
会立即触发。onConnectionStateChanged(kConnectionStateDisconnected)
回调通知连接断开。public void onNetworkQuality(NetworkQualityStats localQuality, NetworkQualityStats[] remoteQualities) { if (remoteQualities.length == 0) { return; } int localQuality = max(localQuality.txQuality, localQuality.rxQuality); int remoteQuality = max(remoteQuality.txQuality, remoteQuality.rxQuality); if (localQuality <= NetworkQuality.NETWORK_QUALITY_POOR && remoteQuality <= NetworkQuality.NETWORK_QUALITY_POOR) { Runnable runnable = () -> { // 网络恢复,清除弱网提示。 }; AppExecutors.execRunnableInMainThread(runnable); return; } // 优先提示本地弱网状态 if (localQuality > NetworkQuality.NETWORK_QUALITY_POOR) { Runnable runnable = () -> { // 提示本地弱网 // 若 localQuality == NetworkQuality.NETWORK_QUALITY_VERY_BAD,提示建议用户关闭摄像头。 }; AppExecutors.execRunnableInMainThread(runnable); return; } // 本地网络正常,对端网络异常,提示对端弱网 if (remoteQuality > NetworkQuality.NETWORK_QUALITY_POOR) { Runnable runnable = () -> { // 提示对端弱网 // 若 localQuality == NetworkQuality.NETWORK_QUALITY_VERY_BAD,提示建议用户关闭摄像头。 }; AppExecutors.execRunnableInMainThread(runnable); return; } }
public void onLeaveCall() { if (mRTCRoom != null) { mRTCRoom.leaveRoom(); mRTCRoom.destroy(); mRTCRoom = null; } if (mRTCVideo != null) { mRTCVideo.stopAudioCapture(); mRTCVideo.stopVideoCapture(); RTCVideo.destroyRTCVideo(); RTCVideo = null; } }
功能点 | API |
---|---|
创建 ByteRTCVideo 实例 | createRTCVideo |
设置视频发布参数 | SetVideoEncoderConfig |
设置默认音频播放路由 | setDefaultAudioRoute |
设置视频朝向 | setVideoOrientation |
开启本地音频采集 | startAudioCapture |
开启本地视频采集 | startVideoCapture |
设置本地视频渲染 | setLocalVideoCanvas |
获取混音管理接口 | getAudioMixingManager |
开启 PCM 音频数据混音 | startAudioMixing |
关闭PCM 混音 | disableAudioMixingFrame |
创建 RTCRoom 实例 | createRTCRoom |
设置房间事件处理器 | setRTCRoomEventHandler |
加入 RTC 房间 | joinRoom |
切换前后置摄像头 | switchCamera |
开启镜像 | setLocalVideoMirrorType |
关闭内部音频采集 | stopAudioCapture |
关闭内部视频采集 | stopVideoCapture |
设置视频渲染视图 | setRemoteVideoCanvas |
离开房间 | leaveRoom |
销毁引擎实例对象 | destroyRTCVideo |
功能点 | 回调 |
---|---|
用户开启音频采集 | onUserStartAudioCapture |
用户停止音频采集 | onUserStopAudioCapture |
用户开启视频采集 | onUserStartVideoCapture |
用户停止视频采集 | onUserStopVideoCapture |
用户停止视频采集 | onUserStopVideoCapture |
音频混音文件播放状态改变 | onAudioMixingStateChanged |
远端首帧解码 | onFirstRemoteVideoFrameDecoded |
房间 token 即将失效回调 | onTokenWillExpire |
本地进房成功回调 | onRoomStateChanged |
远端可见用户加入房间 | onUserJoined |