iphone-duo-camera

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Camera on iPhone Duo

iPhone Duo 上的相机

iPhone Duo is the first iPhone with two front cameras. Both are square sensors with an ultra-wide field of view: one on the outer display, and one beneath the inner display — the first under-display camera on iPhone.
That creates a problem no previous iPhone had. "Front" no longer means "pointing at the user."
iPhone Duo 是首款配备双前置摄像头的iPhone。两款摄像头均为超广角视野的方形传感器:一枚位于外屏,另一枚位于内屏下方——这是iPhone上首款屏下摄像头。
这带来了以往iPhone从未有过的问题:“前置”不再意味着“对着用户”。

Pick a strategy first

先选择策略

Everything downstream follows from this choice.
后续所有实现都取决于这个选择。

The virtual front camera — automatic, limited

虚拟前置摄像头——自动切换,能力有限

Discover a front camera the ordinary way — an
AVCaptureDevice.DiscoverySession
requesting position
.front
with a Wide or Ultra Wide device type — and on iPhone Duo you resolve to a new virtual front camera. It switches between the two physical cameras by itself: inner camera when open, outer camera when closed.
It always uses the most relevant camera, and you write no switching code.
The cost is that it exposes only what both physical cameras can do:
  • max 1080p, 60 fps
  • no depth
If the app needs 4K, high frame rates, or any depth-based feature, this is not enough.
通过常规方式查找前置摄像头——使用
AVCaptureDevice.DiscoverySession
请求位置为
.front
、设备类型为广角或超广角的摄像头——在iPhone Duo上,你会得到一个全新的虚拟前置摄像头。它会自动在两个物理摄像头之间切换:设备展开时使用内置摄像头,折叠时使用外置摄像头。
它始终使用最贴合场景的摄像头,你无需编写任何切换代码。
代价是它仅支持两个物理摄像头都能实现的功能:
  • 最高1080p、60 fps
  • 不支持深度信息
如果应用需要4K、高帧率或任何基于深度的功能,这种方式无法满足需求。

The individual cameras — full capability, your responsibility

独立摄像头——完整能力,自行负责

Address each physically, via the built-in outer ultra-wide and built-in inner ultra-wide device types:
Inner (under-display)Outer
Max video1080p @ 60 fps4K @ 120 fps
Depthsupportedsupported
Full capabilities, but now you must switch cameras when the user opens or closes the device. Which brings us to the hard part.
通过系统内置的外置超广角与内置超广角设备类型,分别访问每个物理摄像头:
内置(屏下)外置
最高视频规格1080p @ 60 fps4K @ 120 fps
深度信息支持支持
功能完整,但现在你必须在用户展开或折叠设备时自行切换摄像头。这就引出了最棘手的部分。

Which way is a camera actually facing?

摄像头实际朝向哪个方向?

AVCaptureDevice
has always had a fixed
position
— on iPhone,
.back
or
.front
. Both of iPhone Duo's front cameras report
.front
. That property describes where a camera sits on the hardware, and on a device whose displays can face opposite directions it no longer tells you where the camera points relative to the person looking at your UI.
Three situations make this concrete:
  • The user is looking at the inner display while the app streams the outer front camera — a "front" camera facing away from them.
  • The device closes while that camera is streaming, and the same camera swings around to face them directly.
  • The device is open and flipped, so a rear camera is now the selfie camera.
AVCaptureDevice
一直有一个固定的
position
属性——在iPhone上为
.back
或
.front
。iPhone Duo的两个前置摄像头都会报告
.front
。该属性描述的是摄像头在硬件上的位置,而对于屏幕可以朝向相反方向的设备,它无法告诉你摄像头相对于正在查看你UI的用户的指向。
三种情况可以具体说明这个问题:
  • 用户正在查看内屏,而应用正在流传输外置前置摄像头的画面——这是一个“前置”摄像头,但朝向远离用户的方向。
  • 摄像头正在流传输时设备折叠,同一摄像头会转到正对用户的位置。
  • 设备展开并翻转后,后置摄像头现在变成了自拍摄像头。

AVCaptureDeviceDirectionCoordinator

AVCaptureDeviceDirectionCoordinator

AVCaptureDeviceDirectionCoordinator
(in AVKit) answers the real question: which cameras are forward-facing right now, relative to a given view. Build one from three things — your app's
UIView
, the device types to monitor, and a change handler — and it keeps you current as the device moves.
Because it is anchored to a view, it reports facing relative to the display that view is on. When the view is on the outer display, the outer front cameras are forward-facing and the rear cameras are backward-facing. Open the device, the view moves to the inner display, your handler fires, and now the inner front camera is forward-facing while the outer front and rear cameras are backward-facing.
Driving both displays at once? Create one coordinator per view. Each reports relative to its own display, so the same rear camera is forward-facing to the outer view's coordinator and backward-facing to the inner view's. That is correct, not contradictory — it is the whole point. (Dual-display camera UI comes from the scene accessories API; see
../iphone-duo-hinge-and-scenes/SKILL.md
.)
AVKit中的
AVCaptureDeviceDirectionCoordinator
可以解答这个核心问题:相对于给定视图,哪些摄像头当前是朝前的。你可以通过三个要素创建一个实例:应用的
UIView
、要监控的设备类型,以及一个变更处理闭包——它会在设备移动时实时更新状态。
由于它锚定到一个视图,因此它报告的朝向是相对于视图所在的显示屏的。当视图位于外屏时,外置前置摄像头是朝前的,后置摄像头是朝后的。展开设备后,视图移动到内屏,你的变更处理闭包会触发,此时内置前置摄像头变为朝前,而外置前置摄像头和后置摄像头都变为朝后。
要同时驱动两个显示屏? 请为每个视图创建一个协调器。每个协调器都会相对于自己所在的显示屏报告状态,因此同一个后置摄像头对外屏视图的协调器来说是朝前的,对内屏视图的协调器来说是朝后的。这是正确的,而非矛盾——这正是该设计的意义所在。(双屏相机UI来自场景配件API,参见
../iphone-duo-hinge-and-scenes/SKILL.md
。)

Concurrency

并发

The coordinator is tied to a view, so it is isolated to the main actor. Your change handler must not call AVFoundation APIs directly.
Instead of an
AVCaptureDevice
, it hands you an
AVCaptureDeviceDescriptor
— a sendable, main-actor-safe stand-in carrying everything needed to construct the real device. Pass the descriptor to your camera actor and build the
AVCaptureDevice
there. This is the intended path; don't try to smuggle a device across the boundary.
该协调器与视图绑定,因此它被隔离在主Actor上。你的变更处理闭包不能直接调用AVFoundation API。
它不会直接提供
AVCaptureDevice
实例,而是返回一个**
AVCaptureDeviceDescriptor
**——这是一个可发送、主Actor安全的替代对象,包含了构造实际设备所需的所有信息。将该描述符传递给你的相机Actor,并在那里构建
AVCaptureDevice
。这是推荐的实现方式;不要尝试在Actor边界之间传递设备实例。

What the handler should do

处理闭包应该做什么

  1. Reconfigure the
    AVCaptureSession
    to keep streaming from whichever camera is now forward-facing.
  2. Re-evaluate mirroring. Mirroring should follow the direction, not the position: when a rear camera has become the forward-facing one, mirror the preview so it feels like a normal selfie view.
  3. Apply any UI updates the camera change implies.
  1. 重新配置
    AVCaptureSession
    ,以继续从当前朝前的摄像头流传输画面。
  2. 重新评估镜像设置。镜像应该跟随朝向,而非位置:当后置摄像头变为朝前的摄像头时,应对预览进行镜像,使其看起来像普通的自拍视图。
  3. 应用摄像头变更所涉及的任何UI更新。

Preview polish

预览优化

Streaming the rear camera's full field of view on the inner display leaves extra room around the preview. Two reasonable choices: offset the preview and group controls in the space left over, or let the preview fill the display. Control this with
videoGravity
on
AVCaptureVideoPreviewLayer
.
Streaming an ultra-wide front camera, exploit the square sensor — set
dynamicAspectRatio
on the
AVCaptureDevice
to pick a landscape aspect ratio that fills the inner display.
Rotation. Adopt
AVCaptureDeviceRotationCoordinator
so previews and captures stay upright. On iPhone Duo it updates when the app moves between displays, which is what keeps rotation consistent across both. Once you have adopted it, turn off camera-sensor-orientation compensation — it is enabled on all of iPhone Duo's front cameras and is redundant work once the rotation coordinator is doing the job.
Note that direction and rotation are separate coordinators solving separate problems. Which camera to stream is direction; which way its output is oriented is rotation. Most camera apps on this device want both.
在内屏上流传输后置摄像头的完整视野会在预览周围留下额外空间。有两种合理的选择:偏移预览,将控件分组放在剩余空间中,或者让预览填满整个显示屏。你可以通过
AVCaptureVideoPreviewLayer
的
videoGravity
属性来控制。
流传输超广角前置摄像头时,可以利用方形传感器——设置
AVCaptureDevice
的
dynamicAspectRatio
,选择适合的横向宽高比以填满内屏。
旋转。 采用
AVCaptureDeviceRotationCoordinator
,确保预览和采集画面保持直立。在iPhone Duo上,当应用在显示屏之间移动时它会更新,从而保持跨屏旋转一致性。采用该协调器后,请关闭摄像头传感器方向补偿——iPhone Duo的所有前置摄像头都启用了该功能,而在旋转协调器工作后,这就成了冗余操作。
请注意,方向和旋转是两个独立的协调器,解决不同的问题。该流传输哪个摄像头是方向问题;输出画面的朝向是旋转问题。这款设备上的大多数相机应用都需要同时使用两者。

Checklist

检查清单

  1. Build against the iOS 27.1 SDK.
  2. Decide: virtual front camera (automatic, 1080p60, no depth) or individual cameras (full capability, manual switching).
  3. If individual, adopt
    AVCaptureDeviceDirectionCoordinator
    — one per view.
  4. In the change handler, reconfigure the session, re-decide mirroring, update UI. Move devices across actors as
    AVCaptureDeviceDescriptor
    .
  5. Set
    videoGravity
    , and
    dynamicAspectRatio
    for front-camera capture.
  6. Adopt
    AVCaptureDeviceRotationCoordinator
    , then disable sensor-orientation compensation.
  7. Consider a
    CameraCaptureAccessory
    so the subject sees something on the outer display.
  8. Test opening, closing and flipping the device mid-session in Device Hub.
Apple's related articles: Choosing a Camera by the Direction it Faces and Supporting Device Rotation in Your Camera App. For the square sensor generally, see Support the Center Stage front camera in your iOS app from WWDC26.
  1. 基于iOS 27.1 SDK进行构建。
  2. 做出选择:使用虚拟前置摄像头(自动切换,1080p60,无深度信息)还是独立摄像头(完整能力,手动切换)。
  3. 如果选择独立摄像头,采用
    AVCaptureDeviceDirectionCoordinator
    ——每个视图对应一个实例。
  4. 在变更处理闭包中,重新配置会话、重新决定镜像设置、更新UI。使用
    AVCaptureDeviceDescriptor
    在Actor之间传递设备信息。
  5. 设置
    videoGravity
    ,对于前置摄像头采集,设置
    dynamicAspectRatio
    。
  6. 采用
    AVCaptureDeviceRotationCoordinator
    ,然后禁用传感器方向补偿。
  7. 考虑使用
    CameraCaptureAccessory
    ,让被拍摄者在外屏上能看到画面。
  8. 在Device Hub中测试会话进行中设备展开、折叠和翻转的场景。
Apple相关文章:《根据摄像头朝向选择摄像头》 和 《在你的相机应用中支持设备旋转》。关于方形传感器的更多信息,请参阅WWDC26的*《在iOS应用中支持Center Stage前置摄像头》*。