You need to enable JavaScript to run this app.
导航
场景搭建(iOS)
最近更新时间:2023.09.13 18:04:43首次发布时间:2023.07.19 10:32:42

SDK集成

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

alt

整体实现流程

整体业务流程图

alt

核心功能实现

准备通话

时序图

alt

示例代码

- (void) startCallWithAppID:(NSString *)appid BID:(NSString *)bid {
    // 创建 RTC 引擎
    [self createRTCVideoWithAppID:appid BID:bid];
    
    // 设置本地视频画布
    ByteRTCVideoCanvas *canvas = [[ByteRTCVideoCanvas alloc] init];    
    canvas.view = self.localView.RenderView;
    canvas.renderMode = ByteRTCRenderModeHidden;
    [self.rtcEngineKit setLocalVideoCanvas:ByteRTCStreamIndexMain withCanvas:canvas];
    
    //  设置本地视频采集,移动端默认会开启前置摄像头。
    if (userSetting.openCamera) {
        [self.rtcEngineKit startVideoCapture];
    } else {
        [self.rtcEngineKit stopVideoCapture];
    }
    
    //  设置本地音频采集
    if (userSetting.openMic) {
        [self.rtcEngineKit startAudioCapture];
    } else {
        [self.rtcEngineKit stopVideoCapture];
    }
}

- (void)createRTCVideoWithAppID:(NSString *)appId BID:(NSString *)bid {
    // 创建 RTC 引擎
    self.rtcEngineKit = [ByteRTCVideo createRTCVideo:appId delegate:self parameters:@{}];
    
    // 设置视频编码参数
    ByteRTCVideoEncoderConfig *config = [[ByteRTCVideoEncoderConfig alloc] init];
    config.width = 540;
    config.height = 960;
    config.frameRate = 15;
    config.maxBitrate = 1520; // 单位:kbs
    [self.rtcEngineKit setMaxVideoEncoderConfig:config];
        
    // 设置视频帧方向
    [self.rtcEngineKit setVideoOrientation:ByteRTCVideoOrientationPortrait]; 
    
    // 设置默认音频路由
    [self.rtcEngineKit setDefaultAudioRoute:ByteRTCAudioRouteSpeakerphone];    
    
    // 该策略不适用于使用非 RTC SDK 播放音乐/音效的场景,如有背景音乐播放的游戏场景
    [self.rtcEngineKit setRuntimeParameters:@{@"rtc.audio_session_deactive" : @(YES)}];  
}

响铃

时序图

alt

示例代码

- (void)startRinging {
    // 音频场景设置为媒体
    [self.rtcEngineKit setAudioScenario:ByteRTCAudioScenarioMedia];
    // audio file path
    NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"VideoCallDemo" ofType:@"bundle"];
    NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
    NSString *filePath = [bundle pathForResource:@"call_receive" ofType:@"mp3"];
    // 开始响铃
    ByteRTCAudioMixingConfig *config = [[ByteRTCAudioMixingConfig alloc] init];
    config.type = ByteRTCAudioMixingTypePlayout; // 播放响铃
    config.playCount = 0; // 停止混音前一直循环
    [[self.rtcEngineKit getAudioMixingManager] startAudioMixing:0 filePath:filePath config:config];
}

- (void)stopRinging {
    [[self.rtcEngineKit getAudioMixingManager] stopAudioMixing:0];
}

进行通话

时序图

alt

示例代码

// 加入房间
- (void)joinRoomWithToken:(NSString *)token roomID:(NSString *)roomID uid:(NSString *)uid complete:(void(^)(BOOL success))complete {
    // 设置音频场景为 ByteRTCAudioScenarioHighqualityChat
    [self.rtcEngineKit setAudioScenario:ByteRTCAudioScenarioHighqualityChat];
    
    self.joinRoomBlock = complete;
    
    self.rtcRoom = [self.rtcEngineKit createRTCRoom:roomID];
    self.rtcRoom.delegate = self;
    
    ByteRTCUserInfo *info = [[ByteRTCUserInfo alloc] init];
    info.userId = uid;
    ByteRTCRoomConfig *roomConfig = [[ByteRTCRoomConfig alloc] init];
    // room profile使用ByteRTCRoomProfileCommunication
    roomConfig.profile = ByteRTCRoomProfileCommunication;
    // 开启手动发布
    roomConfig.isAutoPublish = NO;
    // 开启自动订阅
    roomConfig.isAutoSubscribeAudio = YES;
    roomConfig.isAutoSubscribeVideo = YES;
    
    [self.rtcRoom joinRoom:token userInfo:info roomConfig:roomConfig];
}

#pragma mark - ByteRTCRoomDelegate
// 进房状态回调通知
- (void)rtcRoom:(ByteRTCRoom *)rtcRoom onRoomStateChanged:(NSString *)roomId withUid:(NSString *)uid state:(NSInteger)state extraInfo:(NSString *)extraInfo {    
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.joinRoomBlock) {
            self.joinRoomBlock(state == 0);
            self.joinRoomBlock = nil;
        }
    });
}

// 远端用户加入房间后设置渲染画布。
- (void)rtcRoom:(ByteRTCRoom *)rtcRoom onUserJoined:(ByteRTCUserInfo *)userInfo elapsed:(NSInteger)elapsed {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self setRemoteVideoCanvas:self.remoteView.renderView userID:userInfo.userId];     
    });
}

// 设置远端渲染画布
- (void)setRemoteVideoCanvas:(UIView *)view userID:(NSString *)userID {
    ByteRTCRemoteStreamKey *streamKey = [[ByteRTCRemoteStreamKey alloc] init];
    streamKey.userId = userID;
    streamKey.roomId = [self.rtcRoom getRoomId];
    streamKey.streamIndex = ByteRTCStreamIndexMain;
    
    ByteRTCVideoCanvas *canvas = [[ByteRTCVideoCanvas alloc] init];
    canvas.view = view;
    canvas.renderMode = ByteRTCRenderModeHidden;
    
    [self.rtcEngineKit setRemoteVideoCanvas:streamKey withCanvas:canvas];
}


// 切换前后置摄像头
- (void)switchToCamera:(ByteRTCCameraID)cameraID {
    if (cameraID == ByteRTCCameraIDFront) { // 前置:ByteRTCMirrorTypeRenderAndEncoder
        [self.rtcEngineKit setLocalVideoMirrorType:ByteRTCMirrorTypeRenderAndEncoder];
    } else { // 后置:ByteRTCMirrorTypeNone
        [self.rtcEngineKit setLocalVideoMirrorType:ByteRTCMirrorTypeNone];
    }
    
    // {zh} 设置采集摄像头ID
    // {en} Set camera ID
    [self.rtcEngineKit switchCamera:cameraID];
    self.currnetCameraID = cameraID;
}

网络状态提示

用户加入 RTC 房间后,onNetworkQuality 每 2 s 回调一次,返回本地用户和已订阅远端用户的上下行网络质量评分。 RTC 根据 NetworkQuality 的数值,对网络状况进行判定,在网络质量不好时进行提示。

  • 在本地断网(如开启飞行模式)时,onNetworkTypeChanged(kNetworkTypeDisconnected) 会立即触发。
  • 连接断开时长达 12s 时,RTC 会触发 onConnectionStateChanged(kConnectionStateDisconnected) 回调通知连接断开。
  • 连接断开后,RTC 内部会不断重连,超过一段时间未重连成功,会进入断联超时状态,建议业务 App 挂断通话。

示例代码

// 网络质量提示
- (void)rtcRoom:(ByteRTCRoom *)rtcRoom onNetworkQuality:(ByteRTCNetworkQualityStats *)localQuality remoteQualities:(NSArray<ByteRTCNetworkQualityStats *> *)remoteQualities {
    ByteRTCNetworkQualityStats *remoteQuality = remoteQualities.firstObject;
    if (!remoteQuality) {
        return;
    }
    
    NSUInteger localQuality = MAX(localQuality.txQuality, localQuality.rxQuality);
    NSUInteger remoteQuality = MAX(remoteQuality.txQuality, remoteQuality.rxQuality);

    // NSLog(@"onNetworkQuality-local:%ld-remote:%ld", localQuality, remoteQuality);
    
    if (localQuality <= ByteRTCNetworkQualityPoor &&
        remoteQuality <= ByteRTCNetworkQualityPoor) {
        dispatch_async(dispatch_get_main_queue(), ^{
            // 网络恢复,清除弱网提示。
        }
        return;
    }
    
    // 优先提示本地弱网状态
    if (localQuality > ByteRTCNetworkQualityPoor) {
        dispatch_async(dispatch_get_main_queue(), ^{
            // 提示本地弱网
            // 若 localQuality == ByteRTCNetworkQualityVeryBad,提示建议用户关闭摄像头。
        }
        return;
    }
    
    // 本地网络正常,对端网络异常,提示对端弱网
    if (remoteQuality > ByteRTCNetworkQualityPoor) {
        dispatch_async(dispatch_get_main_queue(), ^{
            // 提示对端弱网
        }
        return;
    }    
}

结束通话

时序图

alt

示例代码

- (void)onLeaveCall {
    if (self.rtcRoom != nil) {
        [self.rtcRoom leaveRoom];
        [self.rtcRoom destroy];
        self.rtcRoom = nil;
    }
    if (self.rtcVideoKit) {
        [self.rtcVideoKit stopAudioCapture];
        [self.rtcVideoKit stopVideoCapture];
        [ByteRTCVideo destroyRTCVideo];
        self.rtcVideoKit = nil;
    }
}

核心功能 API 与回调参考

API

功能点API
创建 ByteRTCVideo 实例createRTCVideo:delegate:parameters:
设置视频发布参数SetVideoEncoderConfig:
设置默认音频播放路由setDefaultAudioRoute:
设置视频朝向setVideoOrientation:
开启本地音频采集startAudioCapture
开启本地视频采集startVideoCapture
设置本地视频渲染setLocalVideoCanvas:withCanvas:
获取混音管理接口getAudioMixingManager
开启 PCM 音频数据混音startAudioMixing
关闭PCM 混音disableAudioMixingFrame:
创建 RTCRoom 实例createRTCRoom:
设置房间事件处理器setRTCRoomDelegate:
加入 RTC 房间joinRoom:userInfo:roomConfig:
切换前后置摄像头switchCamera
开启镜像setLocalVideoMirrorType:
关闭内部音频采集stopAudioCapture
关闭内部视频采集stopVideoCapture
设置视频渲染视图setRemoteVideoCanvas:withCanvas:
离开房间leaveRoom
销毁引擎实例对象destroyRTCVideo

回调

功能点回调
用户开启音频采集rtcEngine:onUserStartAudioCapture:uid:
用户停止音频采集rtcEngine:onUserStopAudioCapture:uid:
用户开启视频采集rtcEngine:onUserStartVideoCapture:uid:
用户停止视频采集rtcEngine:onUserStopVideoCapture:uid:
用户停止视频采集rtcEngine:onUserStopVideoCapture:uid:
音频混音文件播放状态改变rtcEngine:onAudioMixingStateChanged:state:error:
远端首帧解码rtcEngine:onFirstRemoteVideoFrameDecoded:withFrameInfo:
房间 token 即将失效回调onTokenWillExpire:
本地进房成功回调rtcRoom:onRoomStateChanged:withUid:state:extraInfo:
远端可见用户加入房间rtcRoom:onUserJoined:elapsed: