关于 iphone-duo-camera
面向 iPhone Duo 相机应用开发者的技能指南,讲解双前置摄像头的选择、朝向判断与画面处理。重点是利用方向协调器在设备开合和翻转时选择合适摄像头。
主要功能
- 01比较虚拟与独立摄像头方案
- 02按显示视图判断摄像头朝向
- 03跨 Actor 传递摄像头描述符
- 04处理镜像、预览比例与旋转
适用场景
- 01为 iPhone Duo 实现自拍摄像头切换
- 02设备开合时重新配置采集会话
- 03同步双显示器上的摄像头方向
- 04调整预览画面并保持图像正向
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mirzaaghazadeh/ iphone-duo-skills --skill iphone-duo-camera安装后在 Claude Code 中输入/iphone-duo-camera确认已加载。
详细介绍
iPhone Duo 上的相机
iPhone Duo 是第一款配备两颗前置相机的 iPhone。两颗相机都是方形传感器,视场角超广:一颗位于外屏上,另一颗位于内屏下方——这是 iPhone 上首款屏下相机。
这带来了以往任何 iPhone 都没有的问题。“前置”不再意味着“朝向用户”。
先选择策略
后续的一切都取决于这个选择。
虚拟前置相机——自动,但功能有限
按常规方式发现前置相机——创建一个 AVCaptureDevice.DiscoverySession,请求位置为 .front,设备类型为 Wide 或 Ultra Wide——在 iPhone Duo 上会解析为一颗新的虚拟前置相机。它会自动在两颗实体相机之间切换:设备打开时使用内置相机,设备合上时使用外置相机。
它始终使用最合适的相机,你无需编写切换代码。
代价是它只提供两颗实体相机都支持的功能:
- 最高 1080p、60 fps
- 不支持深度
如果应用需要 4K、高帧率或任何基于深度的功能,这就不够了。
单独使用相机——功能完整,切换由你负责
通过内置的外置超广角和内置的内置超广角设备类型,分别指定每颗相机:
| 内置(屏下) | 外置 | |
|---|---|---|
| 最高视频规格 | 1080p @ 60 fps | 4K @ 120 fps |
| 深度 | 支持 | 支持 |
功能完整,但现在设备打开或合上时,必须由你切换相机。这就引出了棘手的问题。
相机实际朝向哪里?
AVCaptureDevice 一直都有固定的 position——在 iPhone 上为 .back 或 .front。iPhone Duo 的两颗前置相机都报告为 .front。这个属性描述相机在硬件上的位置;而在显示屏可以朝向相反方向的设备上,它已无法告诉你相机相对于正在查看界面的用户朝向哪里。
以下三种情况可以说明这一点:
- 用户正在查看内屏,而应用正在串流外置前置相机——这是一颗朝向用户相反方向的“前置”相机。
- 相机正在串流时设备合上,同一颗相机转向,直接朝向用户。
- 设备处于打开状态且已翻转,因此一颗后置相机此时成了自拍相机。
AVCaptureDeviceDirectionCoordinator
AVCaptureDeviceDirectionCoordinator(位于 AVKit)可以回答真正的问题:相对于指定视图,哪些相机此刻朝向前方。使用三项内容创建一个协调器——应用的 UIView、要监控的设备类型,以及变更处理程序——它就会在设备移动时持续更新状态。
由于它锚定到一个视图,因此报告的朝向是相对于该视图所在的显示屏而言的。视图位于外屏时,外置前置相机朝向前方,后置相机朝向后方。打开设备后,视图移至内屏,处理程序会触发;此时内置前置相机朝向前方,而外置前置相机和后置相机都朝向后方。
同时驱动两个显示屏? 每个视图创建一个协调器。每个协调器都相对于自身所在的显示屏进行报告,因此,同一颗后置相机对于外屏视图的协调器而言朝向前方,对于内屏视图的协调器而言则朝向后方。这是正确的,并不矛盾——这正是该 API 的意义所在。(双显示屏相机界面使用场景配件 API;请参阅 ../iphone-duo-hinge-and-scenes/SKILL.md。)
并发
协调器与视图绑定,因此会隔离到主 Actor。你的变更处理程序不得直接调用 AVFoundation API。
它不会将 AVCaptureDevice 交给你。处理程序接收的是**AVCaptureDeviceDirectionMap**,其中将跟踪到的摄像头按顺序分为两个数组:
var forwardFacingDeviceDescriptors: [AVCaptureDeviceDescriptor]
var backwardFacingDeviceDescriptors: [AVCaptureDeviceDescriptor]
你也可以随时通过协调器的 deviceDirections 属性读取同一个映射,因此不必只在处理程序中响应变化。
AVCaptureDeviceDescriptor 是可安全传递的采集设备替代对象,包含 uniqueID、localizedName、deviceType、mediaTypes 和 position。将描述符传给摄像头 Actor,并在那里创建 AVCaptureDevice。这是预期的做法;不要试图将设备跨越隔离边界传递。
请注意,这两种类型都位于 AVKit 中,与协调器相同,而不在 AVFoundation 中——尽管你可能会首先去那里查找。
由于你获得的是数组而不是单个设备,处理程序必须自行选择:通常选择第一个朝前的描述符,其 deviceType 与当前正在进行流传输的设备类型相匹配。不要假设恰好只有一个摄像头朝前。
处理程序应执行的操作
- 重新配置
AVCaptureSession,以继续使用当前朝前的摄像头进行流传输。 - 重新评估镜像效果。镜像应遵循方向而非位置:当后置摄像头变成朝前的摄像头时,应镜像预览,使其呈现常见的自拍视图。
- 应用摄像头变化所需的 UI 更新。
预览优化
在内屏上显示后置摄像头的完整视野会在预览周围留下额外空间。可以考虑两种做法:偏移预览,并将控件放在剩余空间中;或者让预览填满显示屏。通过 AVCaptureVideoPreviewLayer 的 videoGravity 控制此效果。
使用超广角前置摄像头进行流传输时,可充分利用方形传感器——在 AVCaptureDevice 上设置 dynamicAspectRatio,选择能填满内屏的横向宽高比。
**旋转。**采用 AVCaptureDeviceRotationCoordinator,确保预览和拍摄内容保持正向。在 iPhone Duo 上,当应用在不同显示屏之间移动时,它会更新,因此能让两个显示屏上的旋转保持一致。采用它之后,关闭摄像头传感器方向补偿——该功能在 iPhone Duo 的所有前置摄像头上均已启用,而旋转协调器接管工作后,它就成了多余的处理。
请注意,方向协调器和旋转协调器彼此独立,分别解决不同问题。要使用哪台摄像头进行流传输,属于方向问题;其输出的朝向如何,则属于旋转问题。此设备上的大多数摄像头应用都需要同时处理这两者。
检查清单
- 使用 iOS 27.1 SDK 进行构建。
- 决定使用虚拟前置摄像头(自动切换、1080p60、无深度数据)还是单独的摄像头(完整功能、手动切换)。
- 如果使用单独的摄像头,采用
AVCaptureDeviceDirectionCoordinator——每个视图配置一个。 - 在变更处理程序中,读取
AVCaptureDeviceDirectionMap,选择一个朝前的描述符,重新配置会话,重新判断镜像设置,并更新 UI。跨 Actor 传递设备时使用AVCaptureDeviceDescriptor。 - 设置
videoGravity;使用前置摄像头拍摄时,还要设置dynamicAspectRatio。 - 采用
AVCaptureDeviceRotationCoordinator,然后关闭传感器方向补偿。 - 考虑使用
CameraCaptureAccessory,以便拍摄对象能在外屏上看到画面。 - 在 Device Hub 中测试会话期间打开、合上和翻转设备的情况。
Apple 的相关文档:Choosing a Camera by the Direction it Faces 和 Supporting Device Rotation in Your Camera App。关于方形传感器的一般说明,请参阅 WWDC26 的 Support the Center Stage front camera in your iOS app。