SDK集成

如下是一个总体接入流程,详细细节请参见 RTC服务开通指南。

alt

整体实现流程
整体业务流程图

alt

核心功能实现
主播开启直播和观众进房
时序图

alt

示例代码
public void joinRoom(String roomId, String userId, String token) {
    Log.d(TAG, String.format("joinRoom: %s %s %s", roomId, userId, token));
    // 初始化 RTCVideo  对象
    mRTCVideo = RTCVideo.createRTCVideo(Utilities.getApplicationContext(), appId, mRTCVideoEventHandler, null, null);

    // 初始化 RTCRoom 对象    
    mRTCRoom = mRTCVideo.createRTCRoom(roomId);
    mRTCRoom.setRTCRoomEventHandler(mRTCRoomEventHandler);
    mRTCRoomEventHandler.setBaseClient(mRTSClient);
    
    // 加入 RTC 房间
    UserInfo userInfo = new UserInfo(userId, null);
    RTCRoomConfig roomConfig = new RTCRoomConfig(ChannelProfile.CHANNEL_PROFILE_COMMUNICATION,
            true, true, true);
    mRTCRoom.joinRoom(token, userInfo, roomConfig);
    
    // 设置采集分辨率
    VideoCaptureConfig captureConfig = new VideoCaptureConfig(720, 1280, 15);
    mRTCVideo.setVideoCaptureConfig(captureConfig);

    // 设置推流编码分辨率           
    VideoEncoderConfig config = new VideoEncoderConfig();
    config.width = 720;
    config.height = 1280;
    config.frameRate = 15;
    mRTCVideo.setVideoEncoderConfig(config);
    
    // 开启相机和麦克风采集
    mRTCVideo.startVideoCapture();
    mRTCVideo.startAudioCapture();
}

/**
  * RTC 业务房间相关事件回调
  */
private final RTCRoomEventHandlerWithRTS mRTCRoomEventHandler = new RTCRoomEventHandlerWithRTS() {
    @Override
    public void onRoomStateChanged(String roomId, String uid, int state, String extraInfo) {
        super.onRoomStateChanged(roomId, uid, state, extraInfo);
        Log.d(TAG, String.format("onRoomStateChanged: %s, %s, %d, %s", roomId, uid, state, extraInfo));
        mRoomId = roomId;
        if (isFirstJoinRoomSuccess(state, extraInfo)) {
            // mSingleLiveInfo 记录了主播的直播信息
            if (mSingleLiveInfo != null) {
                startLiveTranscoding(roomId, uid, mSingleLiveInfo.pushUrl);
            }
        }
    }

    /**
     * 判断 onRoomStateChanged 中的extraInfo,是不是首次加入房间成功
     *
     * @param extraInfo 额外信息
     * @return true:加入房间成功
     */
    protected boolean isFirstJoinRoomSuccess(int state, String extraInfo) {
        int joinType = -1;
        try {
            JSONObject json = new JSONObject(extraInfo);
            // joinType表示加入房间的类型,0为首次进房,1为重连进房。
            joinType = json.getInt("join_type");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return joinType == 0 && state == 0;
     }
}

/**
  * 开启合流转推
  *  @param roomId 房间id
  *  @param userId 用户id
  *  @param liveUrl rtmp 推流地址
  */
private void startLiveTranscoding(String roomId, String userId, String liveUrl) {
    Log.d(TAG, String.format("startLiveTranscoding: %s  %s  %s", roomId, userId, liveUrl));
    mRoomId = roomId;
    LiveTranscoding liveTranscoding = LiveTranscoding.getDefualtLiveTranscode();
    // 设置房间id
    liveTranscoding.setRoomId(roomId);
    // 设置用户id
    liveTranscoding.setUserId(userId);
    // 设置推流的直播地址
    liveTranscoding.setUrl(liveUrl);
    // 设置合流模式,0 代表服务端合流
    liveTranscoding.setMixType(ByteRTCStreamMixingType.STREAM_MIXING_BY_SERVER);
    // 设置合流视频参数,具体参数根据情况而定
    LiveTranscoding.VideoConfig videoConfig = liveTranscoding.getVideo();
    videoConfig.setWidth(mHostConfig.width);
    videoConfig.setHeight(mHostConfig.height);
    videoConfig.setFps(mHostConfig.frameRate);
    videoConfig.setKBitRate(mHostConfig.bitRate);
    liveTranscoding.setVideo(videoConfig);
    // 设置合流音频参数,具体参数根据情况而定
    LiveTranscoding.AudioConfig audioConfig = liveTranscoding.getAudio();
    audioConfig.setSampleRate(44100);
    audioConfig.setChannels(2);
    liveTranscoding.setAudio(audioConfig);
    // 设置合流视频布局参数
    LiveTranscoding.Layout.Builder layoutBuilder = new LiveTranscoding.Layout.Builder();
    LiveTranscoding.Region selfRegion = new LiveTranscoding.Region();
    selfRegion.uid(userId);
    selfRegion.roomId(roomId);
    selfRegion.position(0, 0);
    selfRegion.size(1, 1);
    selfRegion.alpha(1);
    selfRegion.zorder(0);
    selfRegion.renderMode(LiveTranscoding.TranscoderRenderMode.RENDER_HIDDEN);
    layoutBuilder.addRegion(selfRegion);
    liveTranscoding.setLayout(layoutBuilder.builder());
    // 开始服务端合流任务,taskid使用空字符串即可
    mRTCVideo.startLiveTranscoding("", liveTranscoding, mILiveTranscodingObserver);
}
java
主播与观众连麦互动
时序图

alt

示例代码
public void audienceOnMic(String roomId, String userId, String token) {
    // 初始化 RTCVideo 对象
    mRTCVideo = RTCVideo.createRTCVideo(Utilities.getApplicationContext(), appId, mRTCVideoEventHandler, null, null);

    // 初始化 RTCRoom 对象     
    mRTCRoom = mRTCVideo.createRTCRoom(roomId);
    mRTCRoom.setRTCRoomEventHandler(mRTCRoomEventHandler);
    mRTCRoomEventHandler.setBaseClient(mRTSClient);
    
    // 设置推流编码分辨率           
    VideoEncoderConfig config = new VideoEncoderConfig();
    config.width = 250;
    config.height = 250;
    config.frameRate = 15;
    mRTCVideo.setVideoEncoderConfig(config);
    
    // 加入 RTC 房间
    UserInfo userInfo = new UserInfo(userId, null);
    RTCRoomConfig roomConfig = new RTCRoomConfig(ChannelProfile.CHANNEL_PROFILE_COMMUNICATION,
            true, true, true);
    mRTCRoom.joinRoom(token, userInfo, roomConfig);
    
    // 开启相机和麦克风采集
    mRTCVideo.startVideoCapture();
    mRTCVideo.startAudioCapture();
}
java
public void audienceLeaveMic() {
    Log.d(TAG, "audienceLeaveMic");
    if (mRTCRoom != null) {
        // 离开 RTC 房间
        mRTCRoom.leaveRoom();
        // 释放 rtcRoom 对象
        mRTCRoom.destroy();
        mRTCRoom = null;
    }
    if (mRTCVideo != null) {
    // 关闭相机和麦克风采集
        mRTCVideo.stopVideoCapture();
        mRTCVideo.stopAudioCapture();
        mRTCVideo = null;
    }
}
java
主播与主播连麦PK
时序图

alt

示例代码
public void startForwardStreamToRooms(String coHostRoomId, String coHostUserId, String token,
                                      String selfRoomId, String selfUserId, String pushUrl) {
    // 开启跨房转推
    // 使用 mCoHostInfo 记录对方主播信息 
    mCoHostInfo = new LiveTranscodingInfo(pushUrl, selfRoomId, selfUserId, coHostRoomId, coHostUserId);
    ForwardStreamInfo forwardStreamInfo = new ForwardStreamInfo(coHostRoomId, token);
    if (mRTCRoom != null) {
        mRTCRoom.startForwardStreamToRooms(Collections.singletonList(forwardStreamInfo));
    }
}

/**
 * RTC 业务加房事件回调
 */
private final RTCRoomEventHandlerWithRTS mRTCRoomEventHandler = new RTCRoomEventHandlerWithRTS() {
    @Override
    public void onUserPublishStream(String uid, MediaStreamType type) {
        super.onUserPublishStream(uid, type);
        if (type == MediaStreamType.RTC_MEDIA_STREAM_TYPE_AUDIO) {
            return;
        }
        // 主播连麦
        if (mCoHostInfo != null && TextUtils.equals(uid, mCoHostInfo.coHostUserId)) {
            updateLiveTranscodingWithHost(mCoHostInfo.pushUrl, mCoHostInfo.selfRoomId, mCoHostInfo.selfUserId,
                                          mCoHostInfo.coHostUserId);
        }
    }
};

/**
 * 更新合流转推布局
 * @param selfRoomId 房间id
 * @param selfUserId 自己的用户Id
 * @param coHostRoomId 对方房间id
 * @param coHostUserId 对方主播的用户Id
 */
public void updateLiveTranscodingWithHost(String liveUrl, String selfRoomId,
                                          String selfUserId, String coHostUserId) {

    if (mRTCVideo == null) {
        return;
    }

    LiveTranscoding liveTranscoding = LiveTranscoding.getDefualtLiveTranscode();
    // 设置房间id
    liveTranscoding.setRoomId(selfRoomId);
    // 设置推流的直播地址
    liveTranscoding.setUrl(liveUrl);
    // 设置合流模式
    liveTranscoding.setMixType(ByteRTCStreamMixingType.STREAM_MIXING_BY_SERVER);

    // 设置合流视频参数,具体参数根据情况而定
    LiveTranscoding.VideoConfig videoConfig = liveTranscoding.getVideo();
    videoConfig.setWidth(mFrameWidth);
    videoConfig.setHeight(mFrameHeight);
    videoConfig.setFps(mFrameRate);
    videoConfig.setKBitRate(mBitrate);
    liveTranscoding.setVideo(videoConfig);

    // 设置合流音频参数,具体参数根据情况而定
    LiveTranscoding.AudioConfig audioConfig = liveTranscoding.getAudio();
    audioConfig.setSampleRate(44100);
    audioConfig.setChannels(2);
    liveTranscoding.setAudio(audioConfig);

    LiveTranscoding.Layout.Builder layoutBuilder = new LiveTranscoding.Layout.Builder();
    LiveTranscoding.Region selfRegion = new LiveTranscoding.Region();
    selfRegion.uid(selfUserId);
    selfRegion.roomId(selfRoomId);
    selfRegion.position(0, 0.25); // 设置用户视频布局的相对位置,取值范围[0, 1],(0,0)为左上角,根据实际情况调整
    selfRegion.size(0.5, 0.5); // 设置用户视频相对大小,取值范围[0, 1],根据实际情况调整
    selfRegion.alpha(1); // 设置透明度,取值范围[0, 1],0代表完全透明
    selfRegion.zorder(0); // 设置用户视频布局在画布中的层级,取值范围为[0 - 100]。0为底层,值越大越上层。
    layoutBuilder.addRegion(selfRegion);

    LiveTranscoding.Region hostRegion = new LiveTranscoding.Region();
    hostRegion.uid(coHostUserId);
    hostRegion.roomId(selfRoomId);
    hostRegion.position(0.5, 0.25);
    hostRegion.size(0.5, 0.5);
    hostRegion.alpha(1);
    hostRegion.zorder(0);
    layoutBuilder.addRegion(hostRegion);
    liveTranscoding.setLayout(layoutBuilder.builder());
    liveTranscoding.setLayout(layoutBuilder.builder());

    mRTCVideo.updateLiveTranscoding("", liveTranscoding);
}
java
核心功能 API 与回调参考
API
功能点API
创建 ByteRTCVideo 实例createRTCVideo
创建 ByteRTCRoom 实例createRTCRoom
设置相机采集参数setVideoCaptureConfig
设置视频发布参数setVideoEncoderConfig
设置镜像setLocalVideoMirrorType
获取合流转推默认配置参数LiveTranscoding.getDefualtLiveTranscode
加入RTC房间joinRoom
离开RTC房间leaveRoom
销毁房间对象destroy
开启合流转推startLiveTranscoding
更新合流转推参数updateLiveTranscoding
关闭合流转推stopLiveTranscoding
开启跨房间转推startForwardStreamToRooms:
关闭跨房间转推stopForwardStreamToRooms
开启相机采集startVideoCapture
关闭相机采集stopVideoCapture
开启麦克风采集startAudioCapture
关闭麦克风采集stopAudioCapture
切换前置/后置摄像头switchCamera
暂停接收来自远端的媒体流pauseAllSubscribedStream
恢复接收来自远端的媒体流resumeAllSubscribedStream
回调
功能点回调
本地用户加入 RTC 回调onRoomStateChanged
远端用户加入 RTC 回调onUserJoined
收到远端用户音视频流回调onUserPublishStream
本地流数据统计以及网络质量回调onLocalStreamStats
远端流数据统计以及网络质量回调onRemoteStreamStats