探索 tvOS 的连续互通相机
Discover Continuity Camera for tvOS
2023年6月5日
一句话判断
tvOS 17 引入了连续互通相机——你的 Apple TV 应用现在可以把 iPhone 或 iPad 当作摄像头和麦克风使用,视频会议、内容创作、直播等全新品类的大门就此打开。
这场 Session 讲了什么
tvOS 团队的 Kevin Tulod 和 Core Audio 团队的 Somesh Ganesh 联合介绍了 tvOS 17 中连续互通相机和麦克风的实现方式。
2022 年 macOS Ventura 首先引入了连续互通相机,让 iPhone 可以作为 Mac 的网络摄像头。现在同样的能力来到了 Apple TV——用户只需将 iPhone 靠近 Apple TV,就能把设备的摄像头和麦克风作为 tvOS 应用的输入源。
从 API 层面看,tvOS 17 现在支持 iOS 上已有的全套 AVFoundation 捕获 API:AVCaptureDevice、AVCaptureDeviceInput、AVCaptureSession、AVCaptureOutput 以及 AVCaptureVideoPreviewLayer。如果你已经有一个使用这些 API 的 iOS 应用,大部分代码可以直接在 tvOS 上运行。
关键差异在于设备发现机制。Apple TV 是共享设备,没有内置摄像头,所以需要通过新的 AVContinuityDevicePickerViewController 来发现和选择可用的连续互通设备。这个控制器会列出所有登录了 Apple TV 的用户的可用设备,还支持访客配对。
Session 还详细讲解了 Core Audio 方面的 API 支持,包括高保真音频捕获、多声道处理等。
值得深挖的点
共享设备的独特挑战:与 iPhone 这种个人设备不同,Apple TV 是多人共享的。任何拥有兼容设备的人——包括访客——都可以将自己的设备作为连续互通相机使用。这意味着相机可能随时出现或消失,你的应用必须能优雅地处理设备的热插拔。
设备发现的两步流程:先用 AVCaptureDevice 检查是否有已连接的捕获设备。如果有,直接使用;如果没有,弹出 AVContinuityDevicePickerViewController 让用户选择。选中后 tvOS 会向用户的其他设备发送确认请求,用户在 iPhone 或 iPad 上接受后连接才建立。
iOS 到 tvOS 的迁移成本极低:Session 用一个已有的 iOS 相机应用做了现场演示。添加 tvOS 支持只需要在 Xcode 中将 Apple TV 添加为目标平台,然后处理设备发现逻辑。所有 AVCapture 相关代码无需修改。
Core Audio 的完整支持:不只是视频,tvOS 17 也完整支持了音频捕获 API。从简单的录音到复杂的多声道音频处理,AVFAudio 和 AudioToolbox 的能力全部可用。
代码片段
// 设备发现流程 - 检查可用设备并展示选择器
func setupCaptureDevices() {
let discoverySession = AVCaptureDevice.DiscoverySession(
deviceTypes: [.builtInWideAngleCamera],
mediaType: .video,
position: .unspecified
)
if let device = discoverySession.devices.first {
// 已有可用设备,直接使用
startCaptureSession(with: device)
} else {
// 没有可用设备,展示设备选择器
presentDevicePicker()
}
}
// 展示连续互通设备选择器
func presentDevicePicker() {
let picker = AVContinuityDevicePickerViewController()
picker.delegate = self
present(picker, animated: true)
}
// 处理用户选择的设备
func continuityDevicePicker(
_ picker: AVContinuityDevicePickerViewController,
didSelect device: AVCaptureDevice
) {
startCaptureSession(with: device)
}
// AVCaptureSession 配置 - 与 iOS 代码完全一致
class CaptureSession {
let session = AVCaptureSession()
func setActiveVideoInput(_ device: AVCaptureDevice) {
session.beginConfiguration()
// 移除旧的输入
session.inputs.forEach { session.removeInput($0) }
// 添加新的输入
guard let input = try? AVCaptureDeviceInput(device: device) else { return }
session.addInput(input)
session.commitConfiguration()
session.startRunning()
}
}
// SwiftUI 中显示相机预览
struct CameraPreview: UIViewRepresentable {
let previewLayer: AVCaptureVideoPreviewLayer
func makeUIView(context: Context) -> UIView {
let view = UIView()
view.layer.addSublayer(previewLayer)
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
previewLayer.frame = uiView.bounds
}
}
最佳实践
- 始终先检查已有设备:在弹出设备选择器之前,先用 DiscoverySession 检查是否已有可用设备。如果用户之前已经配对过,就没必要再展示选择 UI。
- 处理好设备的动态变化:连续互通设备可能随时断开。监听设备可用性变化通知,在设备消失时暂停捕获会话,在设备重新出现时自动恢复。
- Info.plist 中设置权限描述:camera 和 microphone usage description 是必需的。这是用户授权时看到的文案,要清楚说明为什么需要访问这些设备。
- 考虑访客场景:Apple TV 经常出现在共享空间(客厅、度假租赁),访客配对功能让你的应用可以在这些场景下使用。
- 音频捕获注意采样率配置:使用 Core Audio API 时,根据应用需求选择合适的采样率和缓冲区大小,避免不必要的延迟。
还有什么值得关注
- 连续互通相机为 tvOS 开辟了全新的应用品类:视频会议应用、健身应用的实时姿势识别、AR 游戏、社交直播等——这些在以前不可能出现在 Apple TV 上。
- Session 提到 tvOS 上的 AVCapture API 和 iOS 完全一致,这意味着你可以用同一套代码库同时服务两个平台。
- 设备发现的安全设计值得注意——每次连接都需要用户在 iPhone 上主动确认,防止未经授权的设备偷偷使用摄像头。
- 如果你的应用已经在 iOS 上使用了 AVFoundation,迁移到 tvOS 的主要工作量在于设备发现 UI 和设备热插拔处理,核心捕获逻辑无需修改。
- Core Audio 部分提到了低延迟音频处理的能力,这对于实时通信类应用至关重要。