Highlight
iOS 15 让常用视频格式在保持录制和预览响应的同时拍出更高质量照片,开发者可以用
AVCapturePhotoOutput.QualityPrioritization和AVCaptureDevice.Format.isHighPhotoQualitySupported控制画质与速度的取舍。
核心内容
很多相机 App 都会在同一个画面里做两件事:持续显示视频预览,用户按下按钮时保存一张照片。
这类 App 往往会选择视频格式。视频格式适合录制、直播、实时滤镜和 AR 场景。它的开销低,帧率可以到 60 fps,开发者可以拿到更适合视频处理的分辨率。
问题出在拍照那一刻。过去,视频格式为了保证预览流畅,会使用较轻的照片处理。照片能很快交付,但弱光、噪声和动态范围的表现不如照片格式。
专业拍照 App 可以切到照片格式,拿到最高分辨率,还能使用 Live Photo、ProRAW 等照片能力。社交、直播、AR App 很难这么做。它们要继续处理视频帧,不能让预览掉帧。
Apple 在 iOS 15 改进了常用视频格式的照片处理算法。开发者继续使用视频格式,也能在 .balanced 下得到明显更好的照片,同时不打断视频录制和预览。需要最高质量时,可以选择 .quality,代价是部分设备上可能出现掉帧或预览中断。
这场演讲的关键是两个开关。一个是质量优先级,告诉 AVCapturePhotoOutput 这次拍摄更看重速度还是画质。另一个是格式能力查询,告诉开发者哪些视频格式支持新的高质量照片能力。
详细内容
搭建照片捕获管线
(01:19)AVCapture(音视频采集)拍照的基本结构没有变化。应用创建 AVCaptureSession,把相机作为 AVCaptureDevice,再用 AVCaptureDeviceInput 把相机接入 session,最后添加 AVCapturePhotoOutput 接收照片。
import AVFoundation
final class PhotoCaptureController: NSObject, AVCapturePhotoCaptureDelegate {
private let session = AVCaptureSession()
private let photoOutput = AVCapturePhotoOutput()
func configure() throws {
session.beginConfiguration()
session.sessionPreset = .photo
guard let device = AVCaptureDevice.default(.builtInWideAngleCamera,
for: .video,
position: .back) else {
session.commitConfiguration()
return
}
let input = try AVCaptureDeviceInput(device: device)
if session.canAddInput(input) {
session.addInput(input)
}
if session.canAddOutput(photoOutput) {
session.addOutput(photoOutput)
}
session.commitConfiguration()
}
func capture() {
let settings = AVCapturePhotoSettings()
photoOutput.capturePhoto(with: settings, delegate: self)
}
}
关键点:
AVCaptureSession是采集图的中心,输入和输出都接到它上面。session.sessionPreset = .photo表示这个配置优先服务于照片捕获。AVCaptureDevice.default(..., for: .video, ...)取到后置广角相机。AVCaptureDeviceInput把相机数据送入 session。AVCapturePhotoOutput是照片输出端。AVCapturePhotoSettings()保存单次拍照的设置。capturePhoto(with:delegate:)发起拍摄,结果会通过AVCapturePhotoCaptureDelegate回调交付。
用质量优先级表达取舍
(03:07)过去,开发者常把 isAutoStillImageStabilizationEnabled 设为 true 来追求更高照片质量。这个名字只描述静态图像防抖。现在的照片质量还来自多图像融合技术,例如 Smart HDR 和 Deep Fusion。iOS 13 引入了 AVCapturePhotoOutput.QualityPrioritization,用三个级别表达取舍:.speed、.balanced、.quality。
import AVFoundation
final class PrioritizedPhotoCapture: NSObject, AVCapturePhotoCaptureDelegate {
private let photoOutput = AVCapturePhotoOutput()
func configurePhotoOutput() {
photoOutput.maxPhotoQualityPrioritization = .quality
}
func captureForFastSharing() {
let settings = AVCapturePhotoSettings()
settings.photoQualityPrioritization = .balanced
photoOutput.capturePhoto(with: settings, delegate: self)
}
func captureForBurstLikeSpeed() {
let settings = AVCapturePhotoSettings()
settings.photoQualityPrioritization = .speed
photoOutput.capturePhoto(with: settings, delegate: self)
}
}
关键点:
maxPhotoQualityPrioritization设置这个AVCapturePhotoOutput允许的最高质量级别。- 这个值在配置输出时设置一次即可。
settings.photoQualityPrioritization = .balanced表示单次拍摄在速度和画质之间取平衡。settings.photoQualityPrioritization = .speed表示这次拍摄优先快速交付。- 单次拍摄的优先级不能高于
photoOutput.maxPhotoQualityPrioritization,否则会抛出异常。 - 如果不设置,默认值是
.balanced。
根据处理时间决定 UI 反馈
(04:29)质量优先级只是提示。AVCapturePhotoOutput 会结合设备、场景和光照选择算法。开发者不能直接指定底层算法,但可以读取 AVCaptureResolvedPhotoSettings.photoProcessingTimeRange,判断照片交付大概要多久。
import AVFoundation
func shouldShowProcessingIndicator(
for resolvedSettings: AVCaptureResolvedPhotoSettings
) -> Bool {
let processingRange = resolvedSettings.photoProcessingTimeRange
return processingRange.end.seconds > 0.5
}
关键点:
AVCaptureResolvedPhotoSettings是系统解析后的拍照设置。photoProcessingTimeRange表示照片处理时间范围。processingRange.end.seconds取最慢可能时间。- 超过阈值时,应用可以显示等待指示器。
- 这个判断适合
.quality拍摄,因为高质量处理可能需要更久。
分清照片格式和视频格式
(06:56)照片格式表示应用把静态照片放在第一位。它有最高照片分辨率,支持 Live Photo、ProRAW 等照片能力,帧率限制为 30 fps。视频格式表示应用围绕视频体验设计,适合录制、直播、实时处理和 60 fps。
import AVFoundation
func configureSessionForPhotoFirst(_ session: AVCaptureSession) {
session.beginConfiguration()
session.sessionPreset = .photo
session.commitConfiguration()
}
func selectPhotoFormat(from device: AVCaptureDevice) -> AVCaptureDevice.Format? {
return device.formats.first { format in
format.isHighestPhotoQualitySupported
}
}
func selectVideoFormat(from device: AVCaptureDevice) -> AVCaptureDevice.Format? {
return device.formats.first { format in
!format.isHighestPhotoQualitySupported
}
}
关键点:
.photopreset 会选择照片优先的 session 配置。isHighestPhotoQualitySupported == true表示该格式是照片格式。isHighestPhotoQualitySupported == false的格式属于视频格式。- 照片格式适合追求最高照片质量的 App。
- 视频格式适合需要稳定预览、录制或自定义帧处理的 App。
选择支持高质量照片的视频格式
(11:37)iOS 15 在 AVCaptureDevice.Format 上新增 isHighPhotoQualitySupported。这个属性为 true 的格式支持视频格式下的高质量照片能力,并且一定是视频格式。
import AVFoundation
func selectHighPhotoQualityVideoFormat(
from device: AVCaptureDevice
) -> AVCaptureDevice.Format? {
return device.formats.first { format in
format.isHighPhotoQualitySupported
}
}
func applyHighPhotoQualityVideoFormat(to device: AVCaptureDevice) throws {
guard let format = selectHighPhotoQualityVideoFormat(from: device) else {
return
}
try device.lockForConfiguration()
device.activeFormat = format
device.unlockForConfiguration()
}
关键点:
isHighPhotoQualitySupported是 iOS 15 新增的格式能力查询。- 这个属性表示视频格式是否支持新的高质量照片处理。
device.formats.first { ... }从相机可用格式中选择一个匹配格式。- 修改
activeFormat前必须调用lockForConfiguration()。 - 设置完成后调用
unlockForConfiguration()释放配置锁。 - 演讲中列出的支持范围包括 1280×720 30/60 fps、1920×1080 30/60 fps、1920×1440 30 fps、4K 30 fps,设备支持回溯到 iPhone XS。
在视频格式下选择 .balanced 或 .quality
(10:19)在支持的 video formats(视频格式)下,.speed 仍然交付轻处理的 WYSIWYG(所见即所得)照片。.balanced 会带来明显画质提升,只增加少量处理时间,并且不会造成视频录制掉帧或预览中断。.quality 会运行成本更高的算法,可能在部分设备上导致掉帧或预览中断。
import AVFoundation
final class VideoFormatPhotoCapture: NSObject, AVCapturePhotoCaptureDelegate {
private let photoOutput = AVCapturePhotoOutput()
func configureOutputForVideoFormat() {
photoOutput.maxPhotoQualityPrioritization = .quality
}
func captureSnapshotDuringRecording(needsExactVideoMatch: Bool) {
let settings = AVCapturePhotoSettings()
if needsExactVideoMatch {
settings.photoQualityPrioritization = .speed
} else {
settings.photoQualityPrioritization = .balanced
}
photoOutput.capturePhoto(with: settings, delegate: self)
}
}
关键点:
maxPhotoQualityPrioritization = .quality允许后续拍摄选择最高级别。needsExactVideoMatch表示照片是否必须和同时录制的视频画面完全一致。.speed适合照片需要和视频画面一致的场景。.balanced适合大多数视频格式下的拍照场景,画质提升且不打断录制和预览。- 想使用
.quality获取更高画质时,需要接受部分设备上的掉帧或预览中断风险。
处理兼容性和限制
(12:32)如果应用已经使用 AVCapturePhotoOutput 和 .balanced,在 iOS 15 上会自动得到更好的视频格式照片。使用 .speed 的应用可以改为 .balanced。仍在使用已废弃的 AVCaptureStillImageOutput 的应用需要迁移。
import AVFoundation
func preferredPhotoQualityPrioritization(
prioritizesExactVideoAppearance: Bool,
acceptsPreviewInterruptions: Bool
) -> AVCapturePhotoOutput.QualityPrioritization {
if prioritizesExactVideoAppearance {
return .speed
}
if acceptsPreviewInterruptions {
return .quality
}
return .balanced
}
关键点:
- 照片必须和视频外观一致时,选择
.speed。 - 能接受预览中断或掉帧时,可以选择
.quality。 - 常规视频格式拍照建议从
.balanced开始。 - 新能力只适用于
AVCaptureSession,不适用于AVCaptureMultiCamSession。 AVCaptureStillImageOutput已废弃,也不支持这个新能力。.balanced和.quality可能融合不同曝光的多张图像,照片外观可能和同时录制的视频不同。
核心启发
-
做什么:给短视频 App 加一个“高质量截图”按钮。 为什么值得做:iOS 15 的视频格式可以在
.balanced下提升照片质量,同时不打断录制和预览。 怎么开始:继续使用视频格式,选择isHighPhotoQualitySupported为true的AVCaptureDevice.Format,拍摄时设置settings.photoQualityPrioritization = .balanced。 -
做什么:给直播 App 加一个主播封面快照功能。 为什么值得做:直播链路需要低延迟和稳定预览,视频格式比照片格式更适合实时处理。 怎么开始:用
AVCapturePhotoOutput在直播 session 中捕获照片,默认使用.balanced,在弱网或设备压力大时切到.speed。 -
做什么:给 AR App 加一个保存当前 3D 场景照片的入口。 为什么值得做:AR 场景依赖稳定相机 feed。演讲指出,重算法可能影响核心体验,
.balanced能在画质和流畅度之间取得可控结果。 怎么开始:在现有AVCaptureSession中添加AVCapturePhotoOutput,拍照前读取photoProcessingTimeRange,需要等待时显示轻量提示。 -
做什么:给相机 App 做一个“速度 / 平衡 / 质量”拍摄偏好。 为什么值得做:
AVCapturePhotoOutput.QualityPrioritization本身就是面向质量和速度取舍的 API。 怎么开始:把用户选择映射到.speed、.balanced、.quality,并确保maxPhotoQualityPrioritization不低于单次拍摄设置。 -
做什么:给审核或巡检 App 加一个快速连拍模式和精细留档模式。 为什么值得做:同一个业务里既有快速记录,也有需要更高画质的证据照片。 怎么开始:快速连拍用
.speed,单张留档用.balanced或.quality,用photoProcessingTimeRange决定是否显示处理状态。
关联 Session
- What’s new in camera capture — 了解 iOS 15 相机采集、控制中心视频效果和 AVCapture 新能力。
- Explore low-latency video encoding with VideoToolbox — 面向直播和实时视频场景,学习低延迟编码配置。
- Capture and process ProRAW images — 面向专业摄影场景,学习 ProRAW 捕获和处理。
- Explore HDR rendering with EDR — 学习 Apple 高动态范围显示和 EDR 渲染管线。
评论
GitHub Issues · utterances