在 App 中构建空间照片和空间视频体验
Build compelling spatial photo and video experiences
2024年6月10日
一句话判断
visionOS 2 和 iOS 18 让空间视频的录制、检测和播放全部融入现有框架(AVFoundation、PhotoKit、QuickLook),iPhone 15 Pro 上只需三行代码改动就能录制空间视频。
这场 Session 讲了什么
空间媒体(Spatial Media)在 Vision Pro 上有三种形态:3D Video(在平面屏幕上有深度效果)、Spatial Video(通过窗口播放,沉浸模式时与真实世界融合)、Apple Immersive Video(180 度 8K + Spatial Audio 的专业级内容)。三种形态各有适用场景——3D 适合电影,Spatial Video 适合日常记录,Immersive 适合专业制作。
今年最大的变化是把空间媒体能力开放给了开发者,而且没有引入新框架。所有 API 都集成在 AVFoundation、PhotoKit、QuickLook 等已有框架中。
录制方面,iPhone 15 Pro 的广角和超广角摄像头在横屏时处于同一水平基线,类似人眼布局。API 现在公开了空间视频录制能力——切换摄像头、选择支持空间视频的格式、开启录制标志,三步完成。播放方面,Vision Pro 上的窗口模式和沉浸模式可以自由切换。检测方面,可以通过文件元数据判断是否为空间内容。
值得深挖的点
空间视频录制的三个关键改动
从普通视频录制迁移到空间视频录制只需要改三处。第一处是把摄像头从 systemPreferredCamera 改为 builtInDualWideCamera,因为空间视频需要广角和超广角同时工作。第二处是遍历 videoDevice.formats 找到 isSpatialVideoCaptureSupported == true 的格式并设为活跃格式。第三处是在输出上设置 isSpatialVideoCaptureEnabled = true。
看似简单,但背后的含义值得注意。广角和超广角同时工作意味着更高的功耗和发热。Apple 选择在 iPhone 15 Pro 上开放这个能力,是因为它的摄像头物理布局经过专门调整。如果你需要在不同设备上做兼容处理,一定要检查 isSpatialVideoCaptureSupported 而不是硬编码设备型号。
空间视频播放的窗口模式与沉浸模式
空间视频在 Vision Pro 上有两种呈现方式。窗口模式下通过一个带柔和光晕的窗口播放,用户可以同时操作其他 App。点击沉浸按钮后,内容扩展到与真实物体等大的尺寸,画面边缘消失,与真实世界无缝融合——不是”看视频”,而是”身处其中”。
对于开发者来说,QuickLook 框架可以直接预览空间照片和视频,WebKit 也可以渲染空间内容。你不需要自己实现沉浸模式的切换逻辑,系统提供了标准的交互方式。
代码片段
在 iPhone 上录制空间视频
import AVFoundation
let session = AVCaptureSession()
// 改动 1:使用双广角摄像头(广角+超广角同时工作)
guard let videoDevice = AVCaptureDevice.default(.builtInDualWideCamera, for: .video, position: .back) else {
print("设备不支持双广角摄像头")
return
}
let deviceInput = try AVCaptureDeviceInput(device: videoDevice)
session.addInput(deviceInput)
// 改动 2:找到支持空间视频的格式
var spatialFormatFound = false
do {
try videoDevice.lockForConfiguration()
for format in videoDevice.formats {
if format.isSpatialVideoCaptureSupported {
videoDevice.activeFormat = format
spatialFormatFound = true
break
}
}
videoDevice.unlockForConfiguration()
} catch {
print("配置格式失败: \(error)")
}
guard spatialFormatFound else {
print("未找到支持空间视频的格式")
return
}
let movieOutput = AVCaptureMovieFileOutput()
session.addOutput(movieOutput)
// 改动 3:开启空间视频录制
if movieOutput.isSpatialVideoCaptureSupported {
movieOutput.isSpatialVideoCaptureEnabled = true
}
session.commitConfiguration()
session.startRunning()
场景:社交类 App 想让用户拍摄空间视频并分享。三处改动从普通视频录制切换到空间视频。
坑点:isSpatialVideoCaptureSupported 在非 iPhone 15 Pro 设备上返回 false,需要做好降级处理。录制过程中广角和超广角同时工作会增加发热,长时间录制需要注意。
使用 QuickLook 预览空间照片
import QuickLook
class SpatialPreviewController: QLPreviewControllerDataSource {
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
return 1
}
func previewController(_ controller: QLPreviewController,
previewItemAt index: Int) -> QLPreviewItem {
// 空间照片/视频文件 URL
return spatialMediaURL as QLPreviewItem
}
}
// QuickLook 自动识别空间媒体并以正确方式呈现
let previewController = QLPreviewController()
previewController.dataSource = dataSource
present(previewController, animated: true)
场景:用户从相册选择了一张空间照片,用 QuickLook 在 Vision Pro 上预览。系统自动处理窗口/沉浸模式切换。
最佳实践
- 录制空间视频时,为获得最佳防抖效果,设置
preferredVideoStabilizationMode - 不要硬编码设备型号检查,始终使用
isSpatialVideoCaptureSupported做兼容判断 - QuickLook 是最简单的空间媒体预览方案,优先考虑而非自己实现播放器
- 空间视频的同步、校准、编码和元数据写入都由系统处理,不要尝试手动操作这些步骤
还有什么值得关注
- Vision 框架提供了检测文件是否为空间媒体的 API,可用于内容过滤
- AVFoundation 也支持构建自定义的空间视频播放体验,适合需要特殊 UI 的场景
- 实时 3D 内容在 Vision Pro 上也可以呈现立体效果,参考 “Bring your iOS or iPadOS game to visionOS”