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