相機SwiftUIiPhone Duo

iPhone Duo 的相機與外螢幕

兩顆前置鏡頭、虛擬前置鏡頭、方向協調器,以及相機捕捉配件——App 同時使用兩塊螢幕的唯一途徑。

2026年10月4日閱讀約 6 分鐘8 個來源

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 杜比視界拍攝;把展開的手機翻過來時,它們還可以當自拍鏡頭用。新的是正面。兩顆前置鏡頭都是方形感測器,視野為超廣角。

四個朋友在戶外對著鏡頭自拍微笑
來自 Apple 發布公告的樣張。朋友們加入畫面時,人物居中前置鏡頭會擴大取景範圍,還可以旋轉畫面,把所有人都框進來。圖片:Apple
外側前置鏡頭 內側前置鏡頭
位置 在外螢幕裡 在內螢幕下方
裝置型別 .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 正是這樣用後置鏡頭自拍的。

雙手握著展開的 iPhone Duo 進行 FaceTime 通話:左半螢幕是後置鏡頭拍到的身邊的人,右半螢幕是通話物件
展開的 Duo 上的 FaceTime:左半螢幕是後置鏡頭拍到的身邊的人,右半螢幕是通話物件。哪顆鏡頭“朝前”,取決於你以哪個檢視為參照來詢問。圖片:Apple

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。

半折的 iPhone Duo 放在屋頂上,立起的半邊螢幕上,相機 App 正框住身後擺姿勢的五個人
筆電式姿態下的相機 App。手機這樣展開時,Duo 預覽會在朝向被拍者的外螢幕上顯示他們的取景。圖片:Apple
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,從而始終待在同一個平面上。

Chad Etzel@jazzychad

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) 在展開的螢幕上未啟用,直到有會話使用它

繼續閱讀

App · 規格閱讀約 4 分鐘

iPhone Duo 能執行 iPad App 嗎?iPhone Duo 與 iPad mini

iPhone Duo 的內螢幕幾乎有 iPad mini 那麼大,但它執行的是 iOS,不是 iPadOS。這對僅限 iPad 的 App 意味著什麼、為什麼很多 Duo App 看起來會像它們的 iPad 版,以及 Duo 從 iPad 借來了什麼。

10月6日閱讀指南