Skip to main content
虚拟背景在摄像头采集链路上做人像分割,把人像之外的区域替换成虚化或指定图片。它是自研组件,装载不需要授权密钥
接口挂在 SRTCEngine 上,但状态是整机一份(内部是 SRTCVirtualBackground.shared):一个推理会话几十 MB、装载上百毫秒,多个引擎实例、多个频道共用同一份配置。不存在「只给某一个频道开虚拟背景」的用法。开启后自动作用于所有摄像头轨道,包括开启之后才新建的那些(createLocalCameraTrack 会自动带上)。你不需要往 videoProcessors 里挂任何东西。切前后摄像头、切换摄像头设备后不用做任何事:SDK 内部会清掉帧间状态并继续生效。
1.4.0 起最低系统要求抬到 iOS 16.0 / macOS 14.0(此前为 iOS 13 / macOS 10.15)。低于此下限的工程解析不到 1.4.0 及以后的版本,详见 集成方式推理运行时 onnxruntime静态链入 SRTC.xcframework,你不需要额外声明任何依赖、也不需要 embed 任何东西。

step 1:装载虚拟背景组件

建议在需要用到虚拟背景前装载,例如进入会议页面时。modelPathnil 使用 SDK 内置的人像分割模型。
抛出的错误:

step 2:设置背景效果

背景虚化与背景替换互斥,后调用的生效。两个接口在装载前调用也会被记住,装载完成后自动生效,因此不必关心与 installVirtualBackground() 的先后顺序。
SRTCNativeImage 是平台原生图片类型的别名(iOS 上是 UIImage、macOS 上是 NSImage),另有一个接收 CGImage 的重载。

step 3:开启或关闭虚拟背景

装载后默认不开启,需要显式打开。关闭后是零开销直通:采集链路根本不会调到处理器,不跑推理也不做合成。
组件未装载时调用开关会抛 virtualBackgroundNotInstalled。关闭时会清掉帧间状态,下次开启从首帧重新收敛,不会闪出过期蒙版。

step 4:低端机保帧率(可选)

默认每帧都跑一次人像分割。低端机上可以调大推理间隔,用蒙版复用换帧率;此时再按需打开蒙版对齐消除拖影。
inferenceInterval1 时,setVirtualBackgroundMaskSync(_:) 开与不开没有任何区别——那时每帧都拿当前帧推理并当场合成,本来就是对齐的。它只在调大推理间隔后才起作用。
帧率不稳时按帧数节流管不住实际推理频率,可以改按时间节流(inferenceIntervalMs,两者同时生效):

step 5:卸载虚拟背景组件

不再使用时卸载,释放推理会话与相关缓冲。已设置的效果参数不会被清掉,下次装载后仍然生效。

出错时丢帧,不会闪出真实背景

分割失败或输出缓冲池被耗尽时,SDK 丢掉这一帧,而不是把未处理的摄像头原始画面送出去——那会把真实背景闪给对端,对虚拟背景来说是隐私事故。代价是对端看到画面短暂卡顿。 丢帧计数可以直接读,持续增长说明分割一直失败、或者你的处理器链下游在跨帧扣留输出缓冲:
srtc.virtualBackground 还提供 isInstalledisEnabledeffectblurLevel 等只读状态,用于把 UI 与 SDK 的真实状态对齐(例如面板重新打开时回填控件)。

屏幕共享与自定义视频轨道

虚拟背景只自动作用于摄像头轨道。屏幕共享、自定义视频轨道默认不过虚拟背景——要给它们加效果,把这个实例手动放进那条轨道的 videoProcessors 即可(它本身就是一个 VideoProcessor):
自己接管采集(LocalVideoTrack + 自定义采集器)时,采集链路重建后需要手动清一次帧间状态,否则时域平滑仍压着旧画面的蒙版:
摄像头轨道不需要这一步,SDK 在设备切换里已经调过了。

本地预览与推流的一致性

虚拟背景开启时,本地预览显示的就是处理后的画面,与对端看到的是同一份数据(预览走 track.addRenderer(),渲染的是处理器之后的帧);关闭后本地预览回到摄像头原始画面。

性能开销

人像分割固定走 CPU 推理,不启用 CoreML:模型只有 256×256,算子无法被 CoreML 完整承接,每帧在 CPU 与 CoreML 之间反复搬运数据的开销超过省下的算力,实测是负优化。 算法实现与 Objective-C 版同源(同一份人像分割 + 蒙版后处理),单帧耗时量级可参考 iOS SDK 的虚拟背景实测数据。真机上先按默认参数(每帧分割)测一轮,超出帧预算再按 step 4 调大推理间隔。

相关页面