iPhone Duo 的相机与外屏
两颗前置摄像头、虚拟前置摄像头、方向协调器,以及相机捕捉配件——App 同时使用两块屏幕的唯一途径。
iPhone Duo 是第一台拥有两颗前置摄像头的 iPhone,而且它的两块屏幕可以朝向相反的方向,所以“前置”不再等于“朝向拿着手机的人”。在 iOS 27.1 SDK 中,相机也是 App 同时在两块屏幕上绘制内容的唯一途径。本文根据 Apple 的相机讲座和多屏幕讲座,以及已经基于这些 API 开发过的开发者的经验,介绍这两方面的内容。
要点
- 像往常一样请求前置摄像头,你拿到的是虚拟前置摄像头,它会替你在外侧和内侧摄像头之间切换,规格为 1080p60,没有深度信息。
- 两颗前置摄像头报告的都是
.front。用AVCaptureDeviceDirectionCoordinator来了解哪颗摄像头真正朝向用户。 - 手机展开时,你的 App 只能通过
CameraCaptureAccessory使用外屏,而且只能在全屏状态下、只能在有活跃相机会话时使用。 - 用
AVCaptureDeviceRotationCoordinator保持预览画面方向正确,并让控件避开屏下摄像头的保留区域。 - 这些在模拟器里都跑不起来。请为 10 月 23 日安排一轮真机测试。
两颗前置摄像头,外加一颗虚拟的
背面,Duo 配备了与 iPhone 18 Pro 相同的 4800 万像素融合主摄和 4800 万像素融合超广角摄像头,支持 4K 120 fps 杜比视界拍摄;把展开的手机翻过来时,它们还可以当自拍摄像头用。新的是正面。两颗前置摄像头都是方形传感器,视野为超广角。

| 外侧前置摄像头 | 内侧前置摄像头 | |
|---|---|---|
| 位置 | 在外屏里 | 在内屏下方 |
| 设备类型 | .builtInOuterUltraWideCamera |
.builtInInnerUltraWideCamera |
| 视频 | 最高 4K 120 fps | 最高 1080p 60 fps |
像在任何 iPhone 上一样,通过 discovery session 请求前置广角或超广角摄像头,在 Duo 上你拿到的就是新的虚拟前置摄像头。它会替你在两者之间切换:手机展开时用内侧摄像头,合上时用外侧摄像头。代价是只能取两者的共同规格:1080p 60 fps,而且没有深度信息。深度信息只能从物理摄像头获取。如果直接使用某颗物理摄像头,手机打开或合上时就要由你的 App 来负责切换。
内侧摄像头是 iPhone 上第一颗屏下摄像头,Apple 的指南说它在摄像头启用之前是隐藏的。布局系统把它视为一块保留区域:Blake Crosley 的探测 App 发现,在展开的屏幕上它被报告为一块未激活的遮挡区域。当你的会话使用它时,就要假定这块区域有影响,让控件避开它。如何读取它,见折痕指南。
前置不等于朝向你
AVCaptureDevice.position 一直只有前置和后置两种,两颗前置摄像头报告的都是 .front。在 Duo 上这就不够了。用外侧前置摄像头推流时打开手机,这颗摄像头就背对着你了。合上手机,同一颗摄像头又转回来朝向你。把展开的手机翻过来,后置摄像头就朝向你,Duo 正是这样用后置摄像头自拍的。

AVKit 里的 AVCaptureDeviceDirectionCoordinator 会持续跟踪这一点。把相机界面所在的视图、你关心的设备类型和一个处理程序交给它:
directionCoordinator = AVCaptureDeviceDirectionCoordinator(
view: view,
deviceTypes: [
.builtInOuterUltraWideCamera,
.builtInInnerUltraWideCamera,
.builtInDualWideCamera,
],
changeHandler: { [weak self] map in
self?.updateCameraSession(map)
}
)
方向是相对于那个视图而言的。视图在外屏上时,外侧前置摄像头朝前,后置摄像头朝后。打开手机,视图移到内屏,处理程序就会触发:现在朝前的是内侧前置摄像头。
协调器绑定在一个视图上,所以它运行在主 actor 上,处理程序不应直接调用 AVFoundation。它交给你的是 AVCaptureDeviceDescriptor 值,而不是设备本身。描述符是 sendable 的,携带了创建设备所需的信息,所以把它传给拥有捕捉会话的那个 actor。在处理程序中:
- 重新配置会话,改用现在朝前的那颗摄像头推流。
- 当朝前的是后置摄像头时,把预览镜像,让用后置摄像头自拍也有自拍的感觉。
- 针对切换后的摄像头更新界面。
详情见 Apple 的文章“Choosing a Camera by the Direction it Faces”。
同时使用两块屏幕
Apple 自家的相机功能展示了手机展开时外屏的用途。Duo 预览让被拍的人看到自己的取景;Kid Cue 播放《史努比》动画,让小朋友看向镜头;Duo FaceTime 让你身边的人也能加入通话,FaceTime 中的双路捕捉则同时发送前置和后置画面。你的 App 通过一个场景配件来使用这块屏幕,而目前能做到这一点的只有一种:CameraCaptureAccessory。

struct CameraRootView: View {
@State private var model = TeleprompterModel()
var body: some View {
CameraView(model: model)
.sceneAccessory {
CameraCaptureAccessory(isEnabled: $model.isEnabled) {
TeleprompterView(model: model)
}
.onAvailabilityChange { available in
model.isAvailable = available
}
}
.toolbar {
TeleprompterToggle(isEnabled: $model.isEnabled)
.disabled(!model.isAvailable)
}
}
}
这是 Apple 多屏幕讲座里的提词器示例:台词显示在外屏上,朝向被拍摄的人。随之而来的还有这些规则:
- 只有当你的 App 在内屏上全屏运行、并且有活跃的相机会话时,这个配件才可用。分屏浏览不算,合上手机也会让它消失。
- 把它注册在相机界面所在的同一个视图上,这样它只在那个视图显示时才出现。
- 可用状态会在你不经意间变化。合上手机时,切换开关就是靠
onAvailabilityChange把自己禁用的。 - 配件是第二块屏幕上的第二个视图,所以要给它配一个单独的方向协调器。每个协调器报告的方向都相对于它自己的视图,这意味着对外屏的视图来说,后置摄像头是朝前的。
Anton Gubarenko 对 9 月小组实验室的记录补充说,App 还需要相应的 entitlement,而且光有 entitlement 并不能点亮外屏。没有相机会话,手机展开时就没有外屏可用。
ryo 开发的你比我猜游戏 CharaDUO 展示了一个创意如何遵守这条规则,并把它变成一个功能:描述者在内屏上看词,坐在桌子对面的猜词者从外屏上看到分类、倒计时和一排与答案字数相同的 emoji。因为外屏需要相机会话,游戏就给相机安排了任务:一个反应摄像头把猜词者录下来,在比赛结束时做成精彩集锦。它只在 iPhone Duo 上请求相机(通过外侧超广角摄像头或铰链报告来识别),在任何 iPhone 上用一块屏幕也照样能玩。在桌面姿态下,它还会把外屏内容旋转四分之一圈,让对面的人读到的文字是正的。
如果你的创意需要在手机展开时使用外屏,先确认相机确实是其中合理的一部分,再去做其余的部分。
铺满屏幕,保持方向正确
- 在内屏上以后置摄像头的完整视野推流时,预览周围会留出空间。可以把预览偏移,把控件集中在剩下的空间里,或者让预览铺满屏幕。
AVCaptureVideoPreviewLayer的videoGravity决定预览如何填充它的图层。 - 前置摄像头的方形传感器可以铺满宽阔的内屏。用设备的
dynamicAspectRatio选择一个横向比例。Apple 在 WWDC26 关于人物居中前置摄像头的讲座里介绍了方形传感器。 - 采用
AVCaptureDeviceRotationCoordinator来保持预览和照片的方向正确。在 Duo 上,它会在你的 App 在两块屏幕之间移动时更新。用上它之后,关闭照片输出的isCameraSensorOrientationCompensationEnabled以提升性能。Duo 的每颗前置摄像头都默认开启了这项补偿。
Chad Etzel 的 NeoCam 也处理了折叠。手机平放时,取景器占据尽可能多的空间;手机折起时,它移进一个 ArrangementView,从而始终待在同一个平面上。
a cool iPhone Duo layout I've landed on for NeoCam: when completely open, the viewfinder takes up as much room as possible, but when folded, it switches to an ArrangementView to keep the viewfinder on one plane
安排一轮真机测试
模拟器无法运行捕捉会话,所以在硬件上市之前,这些都看不到实际效果。CharaDUO 的开发者用合成画面和仅限调试的覆盖设置检查了反应摄像头,并列出了尚未得到证实的部分:配件场景中的方向协调器、铰链移动时的输入切换、保持画面水平,以及长时间对局的发热。Ihor Malovanyi 为 Duo 一书写的配套代码,也同样把相机章节标注为需要真机。
把这些都列进 10 月 23 日的待办清单,还要加上外侧摄像头的真实位置。CharaDUO 发现,模拟器在外屏上的安全区域内边距与它绘制摄像头的位置并不一致。
在那之前,你仍然可以检查 App 在合上的手机上绘制了什么。模拟器为每块屏幕都有单独的帧缓冲区,CharaDUO 的 README 是这样截取外屏的:
# 列出屏幕:外屏是 1398 × 2034。
xcrun simctl io booted enumerate
xcrun simctl io booted screenshot --display=<UUID> outer.png
今天就能做的其余测试,见检查清单。
速查表
| API | 说明 | |
|---|---|---|
| 两颗前置摄像头 | .builtInOuterUltraWideCamera、.builtInInnerUltraWideCamera |
方形传感器。外侧最高 4K120,内侧最高 1080p60 |
| 一颗随折叠切换的前置摄像头 | 虚拟前置摄像头,通过普通的前置广角或超广角 discovery 获取 | 1080p60,无深度信息 |
| 哪颗摄像头朝向用户 | AVKit 中的 AVCaptureDeviceDirectionCoordinator |
按视图区分;交给你 AVCaptureDeviceDescriptor 值 |
| 保持预览和照片方向正确 | AVCaptureDeviceRotationCoordinator |
然后关闭 isCameraSensorOrientationCompensationEnabled |
| 铺满宽阔的内屏 | 设备的 dynamicAspectRatio |
从方形传感器得到横向比例 |
| 展开时使用外屏 | sceneAccessory 配合 CameraCaptureAccessory;UIKit 用 registerSceneAccessory 配合 UISceneAccessory.cameraCapture() |
在内屏全屏、会话活跃、具备 entitlement |
| 知道配件何时可以显示 | onAvailabilityChange |
合上手机或进入分屏浏览会让它消失 |
| 屏下摄像头的位置 | reservedRegions(kind: .occlusion) |
在展开的屏幕上未激活,直到有会话使用它 |
继续阅读

iPhone Duo App 创意:开发者正在用折叠屏做的 6 件事
300 多个 iPhone Duo 演示、概念和原型,归纳为反复出现的六种模式,从半折的笔记本电脑形态到把铰链当控制器。如果你正在考虑做点什么,可以从这里开始。

iPhone Duo 能运行 iPad App 吗?iPhone Duo 与 iPad mini
iPhone Duo 的内屏几乎有 iPad mini 那么大,但它运行的是 iOS,不是 iPadOS。这对仅限 iPad 的 App 意味着什么、为什么很多 Duo App 看起来会像它们的 iPad 版,以及 Duo 从 iPad 借来了什么。

iPhone Duo 游戏:即将到来的作品,以及折叠屏给游戏带来了什么
哪些游戏已在 iPhone Duo 上亮相、未更新的游戏在展开的屏幕上是什么样子,以及开发者正在用铰链、半折和两块屏幕做出哪些新玩法。