SDK 与源码理解
Agora Rtc

AgoraRTC

一、基础概念与架构

1)Agora RTC 与 RTM/Signaling 的区别?

回答:

  • RTC(Real-Time Communication)负责音视频低延时传输(P2P/多点联机),典型 API:加入频道、推/拉本地音视频流、编解码与网络自适应。
  • RTM(Real-Time Messaging)负责可靠/半可靠数据与信令(文本、状态、呼叫邀请等),补足“上线状态、房间外消息、频道内控制指令”等诉求。
  • 面试点:RTC 不保证消息必达顺序;若要可靠命令/房管踢人/礼物连贯等,用 RTM/业务信令;若要与视频强同步的小数据(弹幕走位同步/歌词逐帧)用 媒体侧 Metadata/SEI 更稳。

2)Channel Profile(通信 vs 直播)与角色(Broadcaster/Audience)

回答:

  • 通信(Communication):所有人对等发言,常见于会议/群聊。
  • 直播(LiveBroadcasting):角色分 主播(Broadcaster)观众(Audience);观众默认不开麦不发流,进房更省带宽。
  • 常见坑:忘记把需要上麦的人设为 Broadcaster,导致推流失败/无画面。

3)UID、Token 与鉴权

回答:

  • UID:频道内用户唯一标识;可由业务分配或让 SDK 随机。
  • Token:由你的 App Server 按 AppID + AppCertificate + Channel + UID + 过期时间 + 权限 生成;客户端只使用,不生成。
  • 常见坑:时区/过期时间导致「加入频道成功后马上被踢」;权限不匹配导致推流失败。

二、iOS 接入流程与关键 API(Swift 示例)

4)最小可用接入流程(创建 → 权限 → 入会 → 预览/推流)

回答:

要点:初始化 → 设置场景 → 申请权限 → 加入频道 → 开启本地音视频 → 处理回调 → 离开销毁。

import AgoraRtcKit
import AVFoundation

final class RTCService: NSObject {
    private var engine: AgoraRtcEngineKit!

    func setup(appId: String) {
        engine = AgoraRtcEngineKit.sharedEngine(withAppId: appId, delegate: self)
        engine.setChannelProfile(.liveBroadcasting)           // 或 .communication
        try? AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: [.defaultToSpeaker, .allowBluetooth])
        try? AVAudioSession.sharedInstance().setActive(true)
    }

    func join(channel: String, token: String?, uid: UInt, role: AgoraClientRole = .broadcaster) {
        engine.setClientRole(role)
        engine.enableVideo()
        let videoCanvas = AgoraRtcVideoCanvas()
        videoCanvas.view = localPreviewView
        videoCanvas.renderMode = .hidden
        videoCanvas.uid = uid
        engine.setupLocalVideo(videoCanvas)
        engine.startPreview()                                 // 先本地预览
        engine.joinChannel(byToken: token, channelId: channel, info: nil, uid: uid) { _, _, _ in }
    }

    func leave() {
        engine.stopPreview()
        engine.leaveChannel(nil)
        AgoraRtcEngineKit.destroy()
    }
}
extension RTCService: AgoraRtcEngineDelegate {
    func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) {
        // 远端首帧:为该 uid 绑定远端 view
    }
}

面试要点

  • 先起 预览 再入会,快速失败可见性更好;
  • iOS 需在 Info.plist 加 NSCameraUsageDescription / NSMicrophoneUsageDescription;
  • 音频路由:用 AVAudioSession 与 SDK 设置保持一致。

5)如何订阅/显示远端视频?

回答:

func setupRemote(uid: UInt, view: UIView) {
    let canvas = AgoraRtcVideoCanvas()
    canvas.uid = uid
    canvas.view = view
    canvas.renderMode = .hidden
    engine.setupRemoteVideo(canvas)
}

面试点:远端首帧解码/渲染回调常用于“占位图 → 实画面”切换;退出时调用 removeFromSuperview() 且 setupRemoteVideo(nil) 释放。

6)如何实现静音/只开麦不开摄像头?

回答:

engine.muteLocalAudioStream(false)    // 发送本地音频
engine.muteLocalVideoStream(true)     // 关闭本地视频上行

面试点:上行静音与下行静音不同;下行可对单个远端 muteRemoteAudioStream(uid, true),或全体 muteAllRemoteAudioStreams(true)。

三、音视频参数与网络自适应

7)分辨率/帧率/码率如何选?(会议 vs 秀场)

回答:

  • 会议:人脸为主,720p@15fps ~ 24fps、码率 600–1200kbps 足够;
  • 秀场/游戏:画面动态多,1080p@24~30fps、码率 1500–3000kbps,视观众网络做降级。
  • API 方向:setVideoEncoderConfiguration(AgoraVideoEncoderConfiguration(size: fps: bitrate: orientationMode:))。
  • 常见坑:推分辨率≠拉分辨率;端到端清晰度取决于编码档位 + 网络 + 对端解码能力

8)双流(Simulcast)与小流优先

回答:

  • 主播上行同时编码大流/小流,观众按自身窗口/网络订阅;弱网或小窗口时订小流省带宽。
  • 面试点:多画面列表订小流,被点开的大卡切大流;切换需考虑延迟/重配瞬断。

9)网络探测与弱网策略

回答:

  • Last-mile Probe:入会前测试上下行带宽与丢包,决定初始档位。
  • On-the-fly 自适应:丢包 > X%、RTT 升高 → 下调码率/帧率/分辨率,必要时音频优先视频降级/关视频
  • 关键回调:网络质量、远端音量提示、冻结统计;UI 要有网络差提示与清晰度档位反馈。

四、常见功能实现

10)美颜/滤镜/水印怎么做?

回答:

  • 三种路线:

    1)内置美颜参数(简单磨皮/锐化);

    2)自定义视频源/处理:拿到本地采集帧,用第三方美颜 SDK(GPUImage/Metal)处理后再送回 Agora;

    3)自定义渲染:让 Agora 只负责传输,你控制渲染链路。

  • 面试点:自定义源需处理 像素格式、对齐、时间戳,以及性能与内存拷贝

11)屏幕共享与采集源切换

回答:

  • iOS 常用 ReplayKit 进行屏幕采集,作为外部视频源喂给 Agora;
  • 切换摄像头/屏幕源时注意编码器重建与分辨率匹配,避免黑屏。

12)音频 3A(AEC/ANS/AGC)、耳返与音频混音

回答:

  • AEC(回声消除)ANS(降噪)、**AGC(自动增益)**由引擎内建;
  • 耳返:主播监听自身人声,注意延迟与啸叫,佩戴耳机优先;
  • 音频混音:BGM + MIC 混合,上下行可分路;BGM 音量与 Ducking(压低人声或音乐)要明确。

13)跨房连麦、CDN 旁路推流

回答:

  • 跨房连麦:两个房间的主播互通,常用于 PK;
  • 旁路推流(CDN):RTC → 转推到 RTMP/HLS;结合延迟/成本/规模选择 CDN 观看。
  • 常见坑:版权合规旁路推流失败往往是鉴权/码率超限/目标地址策略导致。

14)端到端加密与合规

回答:

  • SDK 支持多种加密算法与密钥配置;
  • 题点:加密会增加编解码负荷与时延,在跨境合规时需要评估法务与落地。

五、iOS 平台细节与坑位

15)AVAudioSession 与蓝牙/扬声器路由

回答:

  • 设置 playAndRecord 并启用 .allowBluetooth/.allowBluetoothA2DP;外放用 .defaultToSpeaker;
  • 切换听筒/扬声器:SDK 路由与 AVAudioSession 保持一致,且在中断(来电/闹钟)恢复后重新激活会话。

16)前后台与锁屏

回答:

  • 需要在 Capabilities → Background Modes 勾选 Audio, AirPlay, and Picture in Picture(音频持续)或相应模式;
  • 进后台可保留音频、暂停视频编码以省电;回来后恢复预览与推流。

17)权限与隐私

回答:

  • NSCameraUsageDescription、NSMicrophoneUsageDescription 必填;首次被拒提供再次引导到系统设置
  • 隐私弹窗时机:只在功能确实需要前再弹,提升转化。

18)CallKit 与系统通话打断

回答:

  • 若与系统通话交互(VoIP/呼叫界面),接入 CallKit 管理音频路由与中断回退;
  • 面试点:通话接入/挂断回调中暂停/恢复 SDK 推流与音频路由。

六、统计、质量监控与调优

19)如何判定“可用”和“体验好”?

回答:

  • 可用:入会成功率、首帧时间(本地/远端)、掉线率;
  • 体验好:端到端延时、卡顿率(冻结时长占比)、视频清晰度切换次数、音量均衡度。
  • 落地:启用 SDK 的 onRtcStats / onLocal/RemoteVideoStats / onNetworkQuality,埋点 → 后台时序图。

20)弱网降级策略示例

回答:

1)丢包 > 15% → 降帧到 15fps;

2)RTT > 250ms → 降码率一级;

3)持续 10s 弱网 → 关闭视频仅保音;

4)恢复 5s 稳定 → 逐级升档。

要点:前端 UI 给出档位提示重试

七、常见面试追问(高频 Q&A 速记)

21)自定义视频源与自定义渲染的区别?

回答:

  • 自定义源:你采集→你处理→交 SDK 发送(编码仍可交给 SDK)。
  • 自定义渲染:SDK 仅解码给你,你自己在 Metal/OpenGL 渲染到屏。
  • 场景:贴纸/美颜/防黄光;或和游戏引擎合流。

22)如何做“礼物飘屏与音视频同步”?

回答:

  • 不追求帧级 → RTM/业务 TCP;
  • 追求帧级 → 媒体 Metadata/SEI 打时间戳与事件码,在解码时回调触发动画。

23)大班课/多人九宫格卡顿怎么破?

回答:

  • 列表画面订小流,大卡订大流
  • 预排版避免频繁 setupRemoteVideo 重建视图;
  • 滚动列表惰性订阅,只订可见窗口内用户。

24)遇到“只能听到声音没有画面”怎么排查?

回答:

  • 本地:相机权限/预览是否开启、编码档位过低、机型硬编不支持 → 切软编试试;
  • 远端:是否订阅大流/小流不匹配、setupRemoteVideo 绑定错误 view、被 muteLocalVideoStream(true)。
  • 网络:丢包过高触发视频降级。

25)iOS 耳返延迟大?

回答:

  • 检查是否走了 A2DP(高延迟),改走 Hands-Free
  • 关闭不必要的音效链/第三方处理,启用低延时会话;
  • 优先有线耳机或低延迟蓝牙编解码。

八、典型场景题(带回答要点)

26)“观众点开某个主播卡片要秒开大画面,弱网也要可看”,怎么设计?

回答(要点):

  • 主播端启用双流;客户端列表订小流、大卡切大流
  • 切流时先保持现有小流画面,待大流解码首帧后无缝替换
  • 弱网时保留小流并限制最大帧率/码率,必要时仅音频
  • 订阅策略与网络质量回调联动,做平滑升降档

27)“跨房 PK,双方各自房间都能看到对方主播”,如何落地?

回答(要点):

  • 两位主播各自推本房间,同时通过跨房连麦把对方音视频拉入本房;
  • 混音与音量平衡,避免回声与双重混流
  • PK 结果与倒计时用 RTM/频道消息 保证可靠到达。

28)“入会失败或成功后立刻被踢”,可能原因?

回答(要点):

  • Token 过期/权限不含推流UID 冲突/复用
  • 服务器时间不同步(NTP)导致签名失效;
  • 频道名/大小写/非法字符问题。

九、答题速背清单(面试一分钟背诵版)

  • RTC 传音视频;RTM 传可靠信令;媒体强同步用 Metadata/SEI。
  • 直播场景:LiveBroadcasting + Broadcaster/Audience,上麦前切角色。
  • iOS:AVAudioSession 路由、权限文案、后台音频、前后台恢复要对齐。
  • 清晰度:编码配置 + 自适应 + 订阅策略三件套。
  • 双流:列表小流,大卡大流,弱网优先音频。
  • 统计:首帧、卡顿率、端到端延时、掉线率四核心。
  • 排障:权限、路由、订阅绑定、Token/UID、弱网降级路径。

十、补充:常见 API 名称速记(方向性,避免版本细节依赖)

  • 初始化与角色:sharedEngine / setChannelProfile / setClientRole
  • 加入/退出:joinChannel / leaveChannel / destroy
  • 视频:enableVideo / startPreview / setupLocalVideo / setupRemoteVideo / setVideoEncoderConfiguration
  • 音频:enableAudio / setAudioProfile / muteLocalAudioStream / muteRemoteAudioStream
  • 统计/回调:onRtcStats / onLocalVideoStats / onRemoteVideoStats / onNetworkQuality
  • 其他:屏幕共享(ReplayKit 外部源)、跨房连麦、旁路推流、加密、Metadata