You need to enable JavaScript to run this app.
导航

场景搭建(Android)

最近更新时间2024.02.05 19:50:10

首次发布时间2022.11.15 15:46:49

SDK集成

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

alt

整体实现流程

整体业务流程图

  • 主播与主播进行 PK
    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 对象
    // Initialize the RTCVideo object
    mRTCVideo = RTCVideo.createRTCVideo(Utilities.getApplicationContext(), appId, mRTCVideoEventHandler, null, null);

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

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

/**
 * RTC 业务房间相关事件回调
 */
private final IRTCRoomEventHandler mRTCRoomEventHandler = new IRTCRoomEventHandler() {
    @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);
            // 341后 SDK传的固定键 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,String taskId) {
    MixedStreamConfig config = MixedStreamConfig.defaultMixedStreamConfig();
    config.setRoomID(roomId);
    config.setUserID(userId);
    config.setPushURL(liveUrl);
    config.setExpectedMixingType(ByteRTCStreamMixingType.STREAM_MIXING_BY_SERVER);
    
    //设置合流视频参数,具体参数根据情况而定
    MixedStreamVideoConfig videoConfig = config.getVideoConfig();
    videoConfig.setWidth(mHostConfig.width);//设置合流视频宽度。单位为 px,范围为 [2, 1920],必须是偶数。默认值为 640 px。 设置值为非偶数时,自动向上取偶数
    videoConfig.setHeight(mHostConfig.height);//设置合流视频高度。单位为 px,范围为 [2, 1920],必须是偶数。默认值为 360 px。 设置值为非偶数时,自动向上取偶数
    videoConfig.setFps(mHostConfig.frameRate);
    videoConfig.setBitrate(mHostConfig.bitRate);
    config.setVideoConfig(videoConfig);
    
    //设置合流音频参数,具体参数根据情况而定
    MixedStreamAudioConfig audioConfig = config.getAudioConfig();
    audioConfig.setSampleRate(44100);
    audioConfig.setChannels(2);
    config.setAudioConfig(audioConfig);
    
    //设置合流视频布局参数
    MixedStreamLayoutRegionConfig localRegionConfig = new MixedStreamLayoutRegionConfig();
    localRegionConfig.setUserID(userId);
    localRegionConfig.setIsLocalUser(true);
    localRegionConfig.setRoomID(roomId);
    localRegionConfig.setLocationX(0);//设置本地主播画面左上角在整个画布坐标系中的 X 坐标(pixel),即以画布左上角为原点,用户画面左上角相对于原点的横向位移,取值范围为 [0, 整体画布宽度)
    localRegionConfig.setLocationY(0);//设置本地主播画面左上角在整个画布坐标系中的 Y 坐标(pixel),即以画布左上角为原点,用户画面左上角相对于原点的纵向位移,取值范围为 [0, 整体画布高度)
    localRegionConfig.setWidth(mHostConfig.width);//设置本地主播画面宽度。取值范围为 [0, 整体画布宽度],默认值为 360
    localRegionConfig.setHeight(mHostConfig.height);//设置本地主播画面高度。取值范围为 [0, 整体画布高度],默认值为 640
    localRegionConfig.setAlpha(1);
    localRegionConfig.setZOrder(0);
    localRegionConfig.setRenderMode(MixedStreamRenderMode.MIXED_STREAM_RENDER_MODE_HIDDEN);
    
    MixedStreamLayoutRegionConfig[] regions = new MixedStreamLayoutRegionConfig[]{localRegionConfig};
    MixedStreamLayoutConfig layoutConfig = new MixedStreamLayoutConfig();
    layoutConfig.setRegions(regions);
    JsonObject json = new JsonObject();
    json.addProperty(KEY_SEI_KEY_SOURCE, KEY_SEI_VALUE_SOURCE_NONE);
    //设置SEI信息
    layoutConfig.setUserConfigExtraInfo(json.toString());
    config.setLayout(layoutConfig);
    //开始合流任务
    mRTCVideo.startPushMixedStreamToCDN(taskId, config, mMixedStreamObserver);
   }

主播与观众连麦互动

时序图

alt

示例代码

  • 观众上麦
public void audienceOnMic(String roomId, String userId, String token) {
    // 初始化 RTCVideo 对象
    // Initialize the RTCVideo object
    mRTCVideo = RTCVideo.createRTCVideo(Utilities.getApplicationContext(), appId, mRTCVideoEventHandler, null, null);

    // 初始化 RTCRoom 对象  
    // Initialize the RTCRoom object
    mRTCRoom = mRTCVideo.createRTCRoom(roomId);
    mRTCRoom.setRTCRoomEventHandler(mRTCRoomEventHandler);
    mRTCRoomEventHandler.setBaseClient(mRTSClient);
    
    // 设置推流编码分辨率        
    // Set the video encoder config
    VideoEncoderConfig config = new VideoEncoderConfig();
    config.width = 250;
    config.height = 250;
    config.frameRate = 15;
    mRTCVideo.setVideoEncoderConfig(config);
    
    // 加入 RTC 房间
    // join the RTC room
    UserInfo userInfo = new UserInfo(userId, null);
    RTCRoomConfig roomConfig = new RTCRoomConfig(ChannelProfile.CHANNEL_PROFILE_COMMUNICATION,
            true, true, true);
    mRTCRoom.joinRoom(token, userInfo, roomConfig);
    
    // 开启相机和麦克风采集
    // Start video and audio capture
    mRTCVideo.startVideoCapture();
    mRTCVideo.startAudioCapture();
}
  • 观众下麦
public void audienceLeaveMic() {
    Log.d(TAG, "audienceLeaveMic");
    if (mRTCRoom != null) {
        // 离开 RTC 房间
        // Leave the RTC room
        mRTCRoom.leaveRoom();
        // 释放 rtcRoom 对象
        // destroy the rtcRoom object
        mRTCRoom.destroy();
        mRTCRoom = null;
    }
    if (mRTCVideo != null) {
        // 关闭相机和麦克风采集
        // Stop video and audio capture
        mRTCVideo.stopVideoCapture();
        mRTCVideo.stopAudioCapture();
        mRTCVideo = null;
    }
}

主播与主播连麦PK

时序图

alt

示例代码

public void startForwardStreamToRooms(String coHostRoomId, String coHostUserId, String token,
                                      String selfRoomId, String selfUserId, String pushUrl) {
    // 开启跨房转推
    // Enable span the room retweet stream
    // 使用 mCoHostInfo 记录对方主播信息 
    mCoHostInfo = new MixedStreamInfo(pushUrl, selfRoomId, selfUserId, coHostRoomId, coHostUserId);
    ForwardStreamInfo forwardStreamInfo = new ForwardStreamInfo(coHostRoomId, token);
    if (mRTCRoom != null) {
        mRTCRoom.startForwardStreamToRooms(Collections.singletonList(forwardStreamInfo));
    }
}

/**
 * RTC 业务加房事件回调
 */
private final IRTCRoomEventHandler mRTCRoomEventHandler = new IRTCRoomEventHandler() {
    @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,
                                           String taskId) {
    if (mRTCVideo == null) {
        return;
    }
    MixedStreamConfig config = MixedStreamConfig.defaultMixedStreamConfig();
    // 设置房间id
    config.setRoomID(selfRoomId);
     // 设置推流的直播地址
    config.setPushURL(liveUrl);
    // 设置合流模式
    config.setExpectedMixingType(ByteRTCStreamMixingType.STREAM_MIXING_BY_SERVER);

    //设置合流视频参数,具体参数根据情况而定
    MixedStreamVideoConfig videoConfig = config.getVideoConfig();
    videoConfig.setWidth(mHostConfig.width);// 设置合流视频宽度。单位为 px,范围为 [2, 1920],必须是偶数。默认值为 640 px。 设置值为非偶数时,自动向上取偶数
    videoConfig.setHeight(mHostConfig.height);//设置合流视频高度。单位为 px,范围为 [2, 1920],必须是偶数。默认值为 360 px。 设置值为非偶数时,自动向上取偶数
    videoConfig.setFps(mHostConfig.frameRate);
    videoConfig.setBitrate(mHostConfig.bitRate);
    //设置合流音频参数,具体参数根据情况而定
    MixedStreamAudioConfig audioConfig = config.getAudioConfig();
    audioConfig.setSampleRate(44100);
    audioConfig.setChannels(2);
    
    MixedStreamLayoutConfig layoutConfig = new MixedStreamLayoutConfig();
    //设置本地主播的UI属性
    LiveTranscoding.Layout.Builder layoutBuilder = new LiveTranscoding.Layout.Builder();
    MixedStreamLayoutRegionConfig localRegion = new MixedStreamLayoutRegionConfig();
    localRegion.setUserID(selfUserId);
    localRegion.setIsLocalUser(true);
    localRegion.setRoomID(selfRoomId);
    localRegion.setLocationX(0);// 设置本地主播画面左上角在整个画布坐标系中的 X 坐标(pixel),即以画布左上角为原点,用户画面左上角相对于原点的横向位移。取值范围为 [0, 整体画布宽度)
    localRegion.setLocationY(0.25);// 设置本地主播画面左上角在整个画布坐标系中的 Y 坐标(pixel),即以画布左上角为原点,用户画面左上角相对于原点的纵向位移。取值范围为 [0, 整体画布高度)
    localRegion.setWidth((int) (mHostConfig.width * 0.5));//用户画面宽度。取值范围为 [0, 整体画布宽度],默认值为 360
    localRegion.setHeight((int) (mHostConfig.height * 0.5));//用户画面高度。取值范围为 [0, 整体画布高度],默认值为 640
    localRegion.setAlpha(1);// 设置透明度,取值范围[0, 1],0代表完全透明
    localRegion.setZOrder(0);// 设置用户视频布局在画布中的层级,取值范围为[0 - 100]。0为底层,值越大越上层。
    //设置对端主播的UI属性
    MixedStreamLayoutRegionConfig hostRegion = new MixedStreamLayoutRegionConfig();
    hostRegion.setUserID(coHostUserId);
    hostRegion.setIsLocalUser(false);
    hostRegion.setRoomID(selfRoomId);
    hostRegion.setLocationX(0.5);// 设置远端主播画面左上角在整个画布坐标系中的 X 坐标(pixel),即以画布左上角为原点,用户画面左上角相对于原点的横向位移。取值范围为 [0, 整体画布宽度)
    hostRegion.setLocationY(0.25);// 设置远端主播画面左上角在整个画布坐标系中的 Y 坐标(pixel),即以画布左上角为原点,用户画面左上角相对于原点的纵向位移。取值范围为 [0, 整体画布高度)
    localRegion.setWidth((int) (mHostConfig.width * 0.5));//远端主播画面宽度。取值范围为 [0, 整体画布宽度],默认值为 360
    localRegion.setHeight((int) (mHostConfig.height * 0.5));//远端主播画面高度。取值范围为 [0, 整体画布高度],默认值为 640

    hostRegion.setAlpha(1);
    hostRegion.setZOrder(0);

    JsonObject json = new JsonObject();
    json.addProperty(KEY_SEI_KEY_SOURCE, KEY_SEI_VALUE_SOURCE_NONE);
    //设置SEI信息
    layoutConfig.setUserConfigExtraInfo(json.toString());
    layoutConfig.setRegions(new MixedStreamLayoutRegionConfig[]{localRegion});
    config.setLayout(layoutConfig);
    mRTCVideo.updatePushMixedStreamToCDN(taskId, config);
}

核心功能 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