Build a great camera experience for iPhone Duo
Use iPhone Duo's virtual and individual front cameras, direction coordination, preview layout, aspect ratio, and rotation APIs for polished capture apps.
TL;DR
- iPhone Duo has inner and outer ultrawide front cameras; the Virtual Front Camera discovered with position
.frontautomatically switches between them as the device opens or closes. - Use individual camera device types when you need each sensor's full capabilities: outer up to 4K/120fps, inner up to 1080p/60fps, and depth only through individual cameras.
- Adopt
AVCaptureDeviceDirectionCoordinatorwhen selecting individual cameras so the app can react to cameras becoming forward- or backward-facing relative to a specificUIView. - Polish previews with
AVCaptureVideoPreviewLayer.videoGravity,AVCaptureDevice.dynamicAspectRatio,AVCaptureDeviceRotationCoordinator, and by disabling camera sensor orientation compensation after adopting rotation coordination.
Camera model on iPhone Duo
iPhone Duo introduces two front cameras: an outer ultrawide camera on the outside display and an inner ultrawide under-display camera. Both use square sensors with an ultrawide field of view.
Existing AVFoundation discovery patterns continue to work. Apps that discover a front wide or ultrawide camera using AVCaptureDeviceDiscoverySession with position .front get the new Virtual Front Camera on iPhone Duo.
- The Virtual Front Camera automatically uses the inner front camera when the device is open and the outer front camera when closed.
- It is the simplest choice when an app does not need to manage camera switching itself.
- Because it abstracts over both physical front cameras, it exposes only capabilities common to both.
Virtual camera vs. individual cameras
For more control, access the physical front cameras using their individual device types: .builtInOuterUltraWideCamera and .builtInInnerUltraWideCamera. This exposes each camera's full capabilities but makes the app responsible for switching as the device opens, closes, or moves between displays.
- Inner ultrawide front camera: 1080p video, up to 60 fps.
- Outer ultrawide front camera: up to 4K video and 120 fps.
- Virtual Front Camera: maximum 1080p and 60 fps because it only exposes shared capabilities.
- Depth is supported only when accessing the individual cameras, not through the Virtual Front Camera.
Track camera direction relative to your UI
AVCaptureDevice.position still reports .front for both front cameras, but on iPhone Duo a front camera is not necessarily facing the person using the current display. Displays can face opposite directions, and the same physical camera can become forward-facing or backward-facing as the device opens, closes, or flips.
Use AVCaptureDeviceDirectionCoordinator to monitor which cameras are forward-facing relative to a specific UIView. The coordinator needs the view, the device types to monitor, and a change handler.
- When a view is on the outer display, outer front cameras are forward-facing and rear cameras are backward-facing.
- When the UI moves to the inner display after opening, the inner front camera becomes forward-facing and outer front/rear cameras are reported accordingly.
- If an app uses both displays at once, create a separate direction coordinator for each display's
UIView; direction is relative to that view. - Camera apps can use
SceneAccessoriesfor both-display experiences; see the related iPhone Duo multiple displays and scenes session.
Initialize a direction coordinator
Create a coordinator for the view whose display-relative camera direction matters, and respond to direction changes in the handler.
directionCoordinator = AVCaptureDeviceDirectionCoordinator(
view: view,
deviceTypes: [
.builtInOuterUltraWideCamera,
.builtInInnerUltraWideCamera,
.builtInDualWideCamera,
],
changeHandler: { [weak self] map in
self?.updateCameraSession(map)
}
)AVCaptureDevice position is not enough on iPhone Duo
Both front cameras report .front, so use direction coordination when you need to know which camera faces the active UI.
enum AVCaptureDevicePosition: Int {
case unspecified
case back
case front
}
extension AVCaptureDevice {
// ...
var position: AVCaptureDevicePosition { get }
}Handle direction changes safely
The direction coordinator is tied to a UIView, so it is main-actor isolated. Its change handler should not use AVFoundation APIs directly. Instead, it provides AVCaptureDeviceDescriptor, a main-actor-safe, sendable representation with enough information to create an AVCaptureDevice on a camera actor or other AVFoundation execution context.
When the handler fires, reconfigure the AVCaptureSession to keep streaming from the forward-facing camera, update preview mirroring decisions, and adjust any UI that depends on camera direction.
- Mirror the preview when the rear camera is forward-facing to preserve a natural selfie-style experience.
- Pass device descriptors out of the main-actor handler rather than passing or creating
AVCaptureDeviceinstances there. - The session points to Apple documentation articles for choosing a camera by direction and supporting device rotation.
Polish preview layout, aspect ratio, and rotation
The rear camera's full field of view may leave extra space around the preview on the inner display. Apps can either offset the preview to leave room for controls or make the preview fill the display, depending on the capture experience.
Use AVCaptureVideoPreviewLayer.videoGravity to control how video fits inside layer bounds. When streaming from the ultrawide front cameras, use the square sensor with AVCaptureDevice.dynamicAspectRatio to select a landscape aspect ratio for the inner display.
Adopt AVCaptureDeviceRotationCoordinator so previews and photos remain upright. On iPhone Duo it updates when the app moves between displays. After adopting it, disable camera sensor orientation compensation on AVCapturePhotoOutput to improve performance; this compensation is enabled on all iPhone Duo front cameras.
- Use the iOS 27.1 SDK to take full advantage of iPhone Duo camera behavior.
- Test open, closed, flipped, and multi-display configurations to validate camera selection, mirroring, preview placement, and rotation.
Configure preview layout
Use videoGravity to decide how the camera image is laid out within the preview layer bounds.
class AVCaptureVideoPreviewLayer {
// ...
var videoGravity: AVLayerVideoGravity { get set }
}Use a dynamic aspect ratio and disable compensation after rotation coordination
Use dynamicAspectRatio for display-filling front camera previews, and disable sensor orientation compensation after adopting AVCaptureDeviceRotationCoordinator.
class AVCaptureDevice {
// ...
var dynamicAspectRatio: AVCaptureDevice.AspectRatio? { get }
}
// Disable for improved performance
class AVCapturePhotoOutput: AVCaptureOutput {
// ...
var isCameraSensorOrientationCompensationEnabled: Bool { get set }
}