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

Android

最近更新时间2023.11.29 20:37:03

首次发布时间2022.07.18 21:22:43

本章节介绍 Android 端互动直播场景核心功能的实现方式。

前提条件

版本说明

互动直播功能需要使用互动版 SDK,请您在安装 SDK 时选择正确的版本。

主播端核心功能实现

以下是主播端核心功能实现的时序图和参考接入代码。

主播开播

主播通过 RTC 引擎和推流引擎开始直播推流。

时序图

示例代码

  • 创建 RTC 视频引擎,设置本地预览视图,设置视频编码参数。

    // 初始化 RTCVideo 对象
    mRTCVideo = RTCVideo.createRTCVideo(Env.getApplicationContext(), mAppId, mRTCVideoEventHandler, null, null);
    
    // 设置本地视图
    VideoCanvas videoCanvas = new VideoCanvas();
    videoCanvas.renderView = renderView;
    videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;
    mRTCVideo.setLocalVideoCanvas(StreamIndex.STREAM_INDEX_MAIN, videoCanvas);
    
    // 设置视频编码参数
    VideoEncoderConfig config = new VideoEncoderConfig(
            mConfig.mVideoEncoderWidth, mConfig.mVideoEncoderHeight, mConfig.mVideoEncoderFps, mConfig.mVideoEncoderKBitrate * 1000);
    mRTCVideo.setVideoEncoderConfig(config);  
    
  • 订阅 RTC 本地音视频数据。

    // 订阅本地视频数据
    mRTCVideo.setLocalVideoSink(StreamIndex.STREAM_INDEX_MAIN, mVideoFrameListener, IVideoSink.PixelFormat.I420);
    
    // 订阅本地音频数据
    mRTCVideo.enableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_RECORD,
            new AudioFormat(changeSampleRate(mConfig.mAudioCaptureSampleRate),
                    changeChannel(mConfig.mAudioCaptureChannel)));
    mRTCVideo.registerAudioFrameObserver(mAudioFrameListener);
    
  • 创建推流引擎,设置推流视频编码参数。

    //  创建推流引擎
    //  推流配置  
    VeLivePusherConfiguration config = new VeLivePusherConfiguration();
    //  配置上下文  
    config.setContext(Env.getApplicationContext());
    //  失败重连次数  
    config.setReconnectCount(10);
    //  创建推流器  
    mLivePusher = config.build();
    
    //  配置推流参数
    //  视频编码配置  
    VeLivePusherDef.VeLiveVideoEncoderConfiguration videoEncoderCfg = new VeLivePusherDef.VeLiveVideoEncoderConfiguration();
    //  设置视频分辨率,内部会根据分辨率设置最佳码率参数  
    videoEncoderCfg.setResolution(VeLiveVideoResolution720P);
    //  视频编码初始化码率(仅供参考)  
    videoEncoderCfg.setBitrate(mConfig.mVideoEncoderKBitrate);
    //  视频编码最大码率(仅供参考)  
    videoEncoderCfg.setMaxBitrate(mConfig.mVideoEncoderKBitrate);
    //  视频编码最小码率(仅供参考)  
    videoEncoderCfg.setMinBitrate(mConfig.mVideoEncoderKBitrate);
    //  硬编码  
    videoEncoderCfg.setEnableAccelerate(mConfig.mIsVideoHardwareEncoder);
    //  编码帧率  
    videoEncoderCfg.setFps(mConfig.mVideoEncoderFps);
    
    VeLivePusherDef.VeLiveAudioEncoderConfiguration audioEncoderCfg = new VeLivePusherDef.VeLiveAudioEncoderConfiguration();
    //  音频编码采样率  
    if (mConfig.mAudioEncoderSampleRate == 32000) {
        audioEncoderCfg.setSampleRate(VeLiveAudioSampleRate32000);
    } else if (mConfig.mAudioEncoderSampleRate == 48000) {
        audioEncoderCfg.setSampleRate(VeLiveAudioSampleRate48000);
    } else {
        audioEncoderCfg.setSampleRate(VeLiveAudioSampleRate44100);
    }
    
    //  音频编码通道数  
    if (mConfig.mAudioEncoderChannel == 1) {
        audioEncoderCfg.setChannel(VeLiveAudioChannelMono);
    } else {
        audioEncoderCfg.setChannel(VeLiveAudioChannelStereo);
    }
    
    //  音频编码码率  
    audioEncoderCfg.setBitrate(mConfig.mAudioEncoderKBitrate);
    //  配置视频编码  
    mLivePusher.setVideoEncoderConfiguration(videoEncoderCfg);
    //  配置音频编码  
    mLivePusher.setAudioEncoderConfiguration(audioEncoderCfg);
    
    //  开始视频采集  
    mLivePusher.startVideoCapture(VeLiveVideoCaptureExternal);
    //  开始音频采集  
    mLivePusher.startAudioCapture(VeLiveAudioCaptureExternal);
    
  • 开启 RTC 音视频采集。

    // 开始视频采集
    mRTCVideo.startVideoCapture();
    
    // 开始音频采集
    mRTCVideo.startAudioCapture();
    
  • 开启推流引擎推流。

    // 开始推流,url 为 RTMP 推流地址
    mLivePusher.startPush(url);
    
  • RTC 本地音视频回调数据发送给推流引擎。

    // 视频采集回调, 发送视频数据给推流引擎
    IVideoSink mVideoFrameListener = new IVideoSink() {
        @Override
        public void onFrame(com.ss.bytertc.engine.video.VideoFrame frame) {
            final int width = videoFrame.getWidth();
            final int height = videoFrame.getHeight();
            final int chromaHeight = (height + 1) / 2;
            final int chromaWidth = (width + 1) / 2;
            int bufferSize = width * height + chromaWidth * chromaHeight * 2;
            final ByteBuffer dstBuffer = ByteBuffer.allocateDirect(bufferSize);
    
            YuvHelper.I420Rotate(videoFrame.getPlaneData(0), videoFrame.getPlaneStride(0),
                    videoFrame.getPlaneData(1), videoFrame.getPlaneStride(1),
                    videoFrame.getPlaneData(2), videoFrame.getPlaneStride(2),
                    dstBuffer,width, height,videoFrame.getRotation().value());
    
            dstBuffer.position(0);
            VeLiveVideoFrame videoFrame1 = new VeLiveVideoFrame(width, height, System.currentTimeMillis() * 1000, dstBuffer);
            mLivePusher.pushExternalVideoFrame(videoFrame1);
            videoFrame1.release();
            frame.release();
        }
    };
    
    // 音频采集回调, 发送音频数据给推流引擎
    mAudioFrameListener = new IAudioFrameObserver() {
        @Override
        public void onRecordAudioFrame(IAudioFrame audioFrame) {
            VeLiveAudioFrame audioFrame = new VeLiveAudioFrame(VeLivePusherDef.VeLiveAudioSampleRate.fromValue(sampleRate, VeLiveAudioSampleRate44100),
            VeLivePusherDef.VeLiveAudioChannel.fromValue(channels, VeLiveAudioChannelStereo),
            timestamp,
            byteBuffer);
            mLivePusher.pushExternalAudioFrame(audioFrame);
        }
    
    };
    

主播美颜(可选)

主播美颜功能都是通过 RTC 引擎进行对接,使用方式请参考 美颜特效(CV)

主播上麦

主播停止推流引擎推流,通过 RTC 引擎加入房间连麦,并开启 RTC 服务端合流转推。

时序图

示例代码

  • 停止推流引擎推流。

    // 停止推流引擎推流
    mLivePusher.stopPush();
    
  • 创建 RTC 房间,设置用户信息,加入 RTC 房间。参考使用 Token 完成鉴权了解如何通过业务服务器获取鉴权 token。

    // 创建 RTC 房间
    mRTCRoom = mRTCVideo.createRTCRoom(roomId);
    mRTCRoom.setRTCRoomEventHandler(mIRtcRoomEventHandler);
    
    // 设置用户信息
    mUserId = userId;
    mRoomId = roomId;
    UserInfo userInfo = new UserInfo(userId, null);
    RTCRoomConfig roomConfig = new RTCRoomConfig(ChannelProfile.CHANNEL_PROFILE_COMMUNICATION,
            true, true, true);
            
    // 加入房间,token 信息通过业务服务器申请
    mRTCRoom.joinRoom(token, userInfo, roomConfig);
    
  • 收到加入 RTC 房间成功回调,开启 RTC 服务端合流转推。

    // 加入房间成功通知
    private RtcRoomEventHandlerAdapter mIRtcRoomEventHandler = new RtcRoomEventHandlerAdapter() {
        @Override
        public void onRoomStateChanged(String roomId, String uid, int state, String extraInfo) {
            // 创建 RTC 服务端合流配置
            mMixedStreamConfig = MixedStreamConfig.defaultMixedStreamConfig();
            mMixedStreamConfig.setRoomID(mRoomId);
            mMixedStreamConfig.setUserID(mUserId);
            
            // 服务端合流
            mMixedStreamConfig.setExpectedMixingType(STREAM_MIXING_BY_SERVER);
            
            // 设置推流地址, 这里为主播的 RTMP 推流地址
            mMixedStreamConfig.setPushURL(mPushUrl);
            
            // 设置视频编码参数。该参数需要和推流视频编码参数保持一致
            MixedStreamConfig.MixedStreamVideoConfig videoConfig = mMixedStreamConfig.getVideoConfig();
            // 分辨率宽
            videoConfig.setWidth(mConfig.mVideoEncoderWidth);
            // 分辨率高
            videoConfig.setHeight(mConfig.mVideoEncoderHeight);
            // fps
            videoConfig.setFps(mConfig.mVideoEncoderFps);
            // 比特率
            videoConfig.setBitrate(mConfig.mVideoEncoderKBitrate);
            mMixedStreamConfig.setVideo(videoConfig);
            
            // 设置音频编码参数。该参数需要和推流音频编码参数保持一致
            MixedStreamConfig.MixedStreamAudioConfig audioConfig = mMixedStreamConfig.getAudioConfig();
            // 音频采样率
            audioConfig.setSampleRate(mConfig.mAudioEncoderSampleRate);
            // 通道数
            audioConfig.setChannels(mConfig.mAudioEncoderChannel);
            // 比特率 k
            audioConfig.setBitrate(mConfig.mAudioEncoderKBitrate);
            // 配置音频参数
            mMixedStreamConfig.setAudioConfig(audioConfig);
            
            MixedStreamConfig.MixedStreamLayoutConfig layout = new MixedStreamConfig.MixedStreamLayoutConfig();
            // 主播合流布局
            MixedStreamConfig.MixedStreamLayoutRegionConfig[] regions = new MixedStreamConfig.MixedStreamLayoutRegionConfig[1];
            MixedStreamConfig.MixedStreamLayoutRegionConfig region = new MixedStreamConfig.MixedStreamLayoutRegionConfig();
            region.setUserID(mUserId); // 主播uid
            region.setRoomID(mRoomId);
            region.setIsLocalUser(true);
            region.setLocationX(0.0); // 仅供参考
            region.setLocationY(0.0); // 仅供参考
            region.setWidthProportion(1); // 仅供参考
            region.setHeightProportion(1); // 仅供参考
            region.setZOrder(0); // 仅供参考
            region.setAlpha(1); // 仅供参考
            region.setRenderMode(MixedStreamConfig.MixedStreamRenderMode.MIXED_STREAM_RENDER_MODE_HIDDEN);
            
            regions[0] = region;
            layout.setRegions(regions);
                    
            // 设置合流模版
            mMixedStreamConfig.setLayout(layout);
            
            // 设置合流任务 ID
            String taskId = "";
        
            // 开始合流转推
            mRTCVideo.startPushMixedStreamToCDN(taskId, mMixedStreamConfig, mIMixedStreamObserver);
        }
    }
    
  • 收到房间内连麦用户的音视频流发布通知后,调整用户视图以及合流布局。

    private RtcRoomEventHandlerAdapter mIRtcRoomEventHandler = new RtcRoomEventHandlerAdapter() {
        @Override
        public void onUserPublishStream(String uid, MediaStreamType type) {
            if (type == RTC_MEDIA_STREAM_TYPE_VIDEO || type == RTC_MEDIA_STREAM_TYPE_BOTH) {
                // 添加连麦用户视图
                TextureView renderView = new TextureView(Env.getApplicationContext());
                VideoCanvas canvas = new VideoCanvas();
                canvas.renderView = renderView;
                canvas.renderMode = RENDER_MODE_HIDDEN;
                RemoteStreamKey key = new RemoteStreamKey(mRoomId, uid, StreamIndex.STREAM_INDEX_MAIN);
                mRTCVideo.setRemoteVideoCanvas(key, canvas);
            }
    
            MixedStreamConfig.MixedStreamLayoutRegionConfig[] regions = new MixedStreamConfig.MixedStreamLayoutRegionConfig[2];
            
            // 主播合流布局
            MixedStreamConfig.MixedStreamLayoutRegionConfig region = new MixedStreamConfig.MixedStreamLayoutRegionConfig();
            region.setUserID(mUserId); // 主播uid
            region.setRoomID(mRoomId);
            region.setIsLocalUser(true);
            region.setLocationX(0.0); //仅供参考
            region.setLocationY(0.0); //仅供参考
            region.setWidthProportion(0.5); //仅供参考
            region.setHeightProportion(0.5); //仅供参考
            region.setAlpha(1.0); //仅供参考
            region.setZOrder(0); //仅供参考
            region.setRenderMode(MixedStreamConfig.MixedStreamRenderMode.MIXED_STREAM_RENDER_MODE_HIDDEN);
            regions[0] = region;
            
            // 连麦用户合流布局
            MixedStreamConfig.MixedStreamLayoutRegionConfig regionRemote = new MixedStreamConfig.MixedStreamLayoutRegionConfig();
            regionRemote.setUserID(uid); // 连麦uid
            regionRemote.setRoomID(mRoomId);
            regionRemote.setIsLocalUser(false);
            regionRemote.setLocationX(0.0); //仅供参考
            regionRemote.setLocationY(0.0); //仅供参考
            regionRemote.setWidthProportion(0.5); //仅供参考
            regionRemote.setHeightProportion(0.5); //仅供参考
            regionRemote.setAlpha(1.0); //仅供参考
            regionRemote.setZOrder(0); //仅供参考
            regionRemote.setRenderMode(MixedStreamConfig.MixedStreamRenderMode.MIXED_STREAM_RENDER_MODE_HIDDEN);
            regions[1] = regionRemote;
              
            // 设置合流模版
            MixedStreamConfig.MixedStreamLayoutConfig layout = new MixedStreamConfig.MixedStreamLayoutConfig();
            layout.setRegions(regions);
            
             // 设置合流任务ID,ID 为上一步设置的合流任务 ID
            String taskId = "";
            
            mMixedStreamConfig.setLayout(layout);
            // 更新合流
            mRTCVideo.updatePushMixedStreamToCDN(taskId, mMixedStreamConfig);
        }
    
        @Override
        public void onUserUnpublishStream(String uid, MediaStreamType type, StreamRemoveReason reason) {
            if (type == RTC_MEDIA_STREAM_TYPE_VIDEO || type == RTC_MEDIA_STREAM_TYPE_BOTH) {
                // 移除连麦用户视图
                VideoCanvas canvas = new VideoCanvas();
                canvas.renderView = null;
                canvas.renderMode = RENDER_MODE_HIDDEN;
                RemoteStreamKey key = new RemoteStreamKey(mRoomId, uid, StreamIndex.STREAM_INDEX_MAIN);
                mRTCVideo.setRemoteVideoCanvas(key, canvas);
            }
            MixedStreamConfig.MixedStreamLayoutConfig layout = new MixedStreamConfig.MixedStreamLayoutConfig();
            // 主播合流布局
            MixedStreamConfig.MixedStreamLayoutRegionConfig[] regions = new MixedStreamConfig.MixedStreamLayoutRegionConfig[1];
            MixedStreamConfig.MixedStreamLayoutRegionConfig region = new MixedStreamConfig.MixedStreamLayoutRegionConfig();
            region.setUserID(mUserId); // 主播uid
            region.setRoomID(mRoomId);
            region.setIsLocalUser(true);
            region.setLocationX(0.0); // 仅供参考
            region.setLocationY(0.0); // 仅供参考
            region.setWidthProportion(1); // 仅供参考
            region.setHeightProportion(1); // 仅供参考
            region.setZOrder(0); // 仅供参考
            region.setAlpha(1); // 仅供参考
            region.setRenderMode(MixedStreamConfig.MixedStreamRenderMode.MIXED_STREAM_RENDER_MODE_HIDDEN);
            
            regions[0] = region;
            layout.setRegions(regions);
                    
            // 设置合流模版
            mMixedStreamConfig.setLayout(layout);
            
            // 设置合流任务ID,ID 为上一步设置的合流任务 ID
            String taskId = "";
            
            // 更新合流
            mRTCVideo.updatePushMixedStreamToCDN(taskId, mLiveTranscoding);
        }
    };
    

主播下麦

主播停止 RTC 服务端合流转推,离开 RTC 房间,开启推流引擎推流。

时序图

示例代码

  • 停止 RTC 服务端合流,离开房间,移除连麦用户视图。

    // 停止 RTC 服务端合流转推
    mRTCVideo.stopPushPublicStream(taskId);
    
    // 离开 RTC 房间
    mRTCRoom.leaveRoom();
    
    // 移除连麦用户视图
    VideoCanvas canvas = new VideoCanvas();
    canvas.renderView = null;
    canvas.renderMode = RENDER_MODE_HIDDEN;
    RemoteStreamKey key = new RemoteStreamKey(mRoomId, uid, StreamIndex.STREAM_INDEX_MAIN);
    mRTCVideo.setRemoteVideoCanvas(key, canvas);
    
  • 开启推流引擎推流。

    // 开始推流引擎推流
    mLivePusher.startPush(url);
    

主播停播

主播停止直播,销毁 RTC 引擎和推流引擎。

时序图

示例代码

  • 停止推流引擎推流,销毁 RTC 引擎和推流引擎。

    // 停止推流引擎推流
    mLivePusher.stopPush();
    
    // 销毁推流引擎
    mLivePusher.release();
    mLivePusher = null;
    
  • 停止 RTC 音视频采集,移除本地预览视图。

    // 停止 RTC 视频采集
    mRTCVideo.stopVideoCapture();
    
    // 停止 RTC 音频采集
    mRTCVideo.stopAudioCapture();
    
    // 移除 RTC 本地预览视图
    VideoCanvas videoCanvas = new VideoCanvas();
    videoCanvas.renderView = null;
    videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;
    mRTCVideo.setLocalVideoCanvas(StreamIndex.STREAM_INDEX_MAIN, videoCanvas);
    
  • 销毁 RTC 房间,销毁 RTC 视频引擎。

    // 销毁 RTC 房间
    mRTCRoom.destroy();
    mRTCRoom = null;
    
    // 销毁 RTC 视频引擎
    RTCVideo.destroyRTCVideo();
    mRTCVideo = null;
    

观众端核心功能实现

以下是观众端核心功能实现的时序图和参考接入代码。

观众拉流

观众端通过播放器拉流观看直播。

时序图

示例代码

  • 创建和设置播放器。

    // 创建播放器
    VeLivePlayer mLivePlayer = new VideoLiveManager(Env.getApplicationContext());
    
    // 设置播放器回调
    mLivePlayer.setObserver(mLivePlayerObserver);
    
    // 播放器参数设置
    VeLivePlayerConfiguration config = new VeLivePlayerConfiguration();
    config.enableStatisticsCallback = true;
    config.enableLiveDNS = true;
    mLivePlayer.setConfig(config);
    
  • 设置播放器视图,设置直播地址,开启拉流播放。

    // 设置播放器视图
    mLivePlayer.setSurfaceHolder(holder);
    
    // 设置播放地址
    mLivePlayer.setPlayUrl(mPullUrl);
    
    // 开始播放
    mLivePlayer.play();
    

观众上麦

连麦观众停止播放器拉流播放,通过 RTC 引擎进行连麦。

时序图

示例代码

  • 停止播放,移除播放器视图。

    // 停止播放
    mLivePlayer.stop();
    // 移除播放器视图
    mLocalVideoContainer.removeView(mPlayerView);
    
  • 创建 RTC 视频引擎,设置本地预览视图,设置视频编码参数。

    // 初始化 ByteRTCVideo 对象
    mRTCVideo = RTCVideo.createRTCVideo(Env.getApplicationContext(), mAppId, mRTCVideoEventHandler, null, null);
    
    // 设置本地视图
    VideoCanvas videoCanvas = new VideoCanvas();
    videoCanvas.renderView = renderView;
    videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;
    mRTCVideo.setLocalVideoCanvas(StreamIndex.STREAM_INDEX_MAIN, videoCanvas);
    
    // 设置视频编码参数
    VideoEncoderConfig config = new VideoEncoderConfig(
            mConfig.mVideoEncoderWidth, mConfig.mVideoEncoderHeight, mConfig.mVideoEncoderFps, mConfig.mVideoEncoderKBitrate * 1000);
    mRTCVideo.setVideoEncoderConfig(config);
    
  • 开启 RTC 音视频采集。

    // 开始视频采集
    mRTCVideo.startVideoCapture();
    
    // 开始音频采集
    mRTCVideo.startAudioCapture();
    
  • 创建 RTC 房间,设置用户信息,加入 RTC 房间。

    // 创建 RTC 房间
    mRTCRoom = mRTCVideo.createRTCRoom(roomId);
    mRTCRoom.setRTCRoomEventHandler(mIRtcRoomEventHandler);
    
     // 设置用户信息
    UserInfo userInfo = new UserInfo(userId, null);
    RTCRoomConfig roomConfig = new RTCRoomConfig(ChannelProfile.CHANNEL_PROFILE_COMMUNICATION,
            true, true, true);
        
    // 加入房间,token 信息通过业务服务器申请
    mRTCRoom.joinRoom(token, userInfo, roomConfig);
    
  • 收到房间内连麦用户的音视频流发布通知后,调整用户视图。

    private RtcRoomEventHandlerAdapter mIRtcRoomEventHandler = new RtcRoomEventHandlerAdapter() {
        @Override
        public void onUserPublishStream(String uid, MediaStreamType type) {
            if (type == RTC_MEDIA_STREAM_TYPE_VIDEO || type == RTC_MEDIA_STREAM_TYPE_BOTH) {
                // 添加连麦用户视图
                TextureView renderView = new TextureView(Env.getApplicationContext());
                VideoCanvas canvas = new VideoCanvas();
                canvas.renderView = renderView;
                canvas.renderMode = RENDER_MODE_HIDDEN;
                RemoteStreamKey key = new RemoteStreamKey(mRoomId, uid, StreamIndex.STREAM_INDEX_MAIN);
                mRTCVideo.setRemoteVideoCanvas(key, canvas);
            }          
        }
    
        @Override
        public void onUserUnpublishStream(String uid, MediaStreamType type, StreamRemoveReason reason) {
            if (type == RTC_MEDIA_STREAM_TYPE_VIDEO || type == RTC_MEDIA_STREAM_TYPE_BOTH) {
                // 移除连麦用户视图
                VideoCanvas canvas = new VideoCanvas();
                canvas.renderView = null;
                canvas.renderMode = RENDER_MODE_HIDDEN;
                RemoteStreamKey key = new RemoteStreamKey(mRoomId, uid, StreamIndex.STREAM_INDEX_MAIN);
                mRTCVideo.setRemoteVideoCanvas(key, canvas);
            }
        }
    };
    

观众美颜(可选)

观众连麦美时颜功能都是通过 RTC 引擎进行对接,使用方式请参考 美颜特效(CV)

观众下麦

观众停止 RTC 引擎连麦,恢复拉流观看直播。

时序图

示例代码

  • 离开 RTC 房间,停止 RTC 音视频采集,移除 RTC 本地和远端视图。

    // 离开 RTC 房间
    mRTCRoom.leaveRoom();
    
    // 停止视频采集
    mRTCVideo.stopVideoCapture();
    
    // 停止音频采集
    mRTCVideo.stopAudioCapture();
    
    // 移除本地用户视图
    VideoCanvas canvas = new VideoCanvas(null, RENDER_MODE_HIDDEN, mRoomId, mUserId, false);
    mRTCVideo.setLocalVideoCanvas(mUserId, StreamIndex.STREAM_INDEX_MAIN, canvas);
    
    // 移除连麦用户视图
    VideoCanvas canvas = new VideoCanvas();
    canvas.renderView = null;
    canvas.renderMode = RENDER_MODE_HIDDEN;
    RemoteStreamKey key = new RemoteStreamKey(mRoomId, uid, StreamIndex.STREAM_INDEX_MAIN);
    mRTCVideo.setRemoteVideoCanvas(key, canvas);
    
  • 设置播放器视图,启动拉流播放。

    // 设置播放器视图
    mLivePlayer.setSurfaceHolder(holder);
    // 开始播放
    mLivePlayer.play();
    

观众离开

观众停止观看直播,销毁播放器。

时序图

示例代码

  • 停止播放,移除播放器视图,销毁播放器。

    // 停止播放
    mLivePlayer.stop();
    
    // 移除播放器视图
    mLocalVideoContainer.removeView(mPlayerView);
    
    // 销毁播放器
    mLivePlayer.destroy();
    mLivePlayer = null;
    
  • 销毁 RTC 房间,销毁 RTC 引擎。

    // 销毁 RTC 房间
    mRTCRoom.destroy();
    mRTCRoom = null;
    
    // 销毁 RTC 引擎
    RTCVideo.destroyRTCVideo();
    mRTCVideo = null;