用视频格式拍摄高质量照片
Capture high-quality photos using video formats
2021年6月10日
一句话判断
AVFoundation 的新 API 让你可以从视频流中提取高质量静态帧——这意味着拍照不再需要切换到照片模式,“边录像边拍照”的体验可以做到零延迟。
这场 Session 讲了什么
Session 介绍了 iOS 15 中 AVFoundation 的新能力:从视频流中提取高质量静态图片。传统的拍照流程需要切换到照片捕获模式,完成对焦和曝光后拍摄一张照片。新 API 允许你在视频录制过程中随时提取一帧作为高质量照片,不需要停止录制或切换模式。
关键技术是 AVCapturePhotoOutput 的 isFastCaptureEnabled 和从 AVCaptureVideoDataOutput 的样本缓冲区(Sample Buffer)中提取照片质量图像。后者结合了视频流的实时性和照片的分辨率和动态范围。
还介绍了 Apple 的计算摄影(Computational Photography)技术如何在提取帧时发挥作用——Smart HDR、Deep Fusion 和夜间模式都可以应用到从视频帧提取的照片上。
值得深挖的点
视频帧到照片质量的差距
普通视频帧的分辨率是 1920x1080(Full HD)或 3840x2160(4K),而照片模式可以输出 12MP(4032x3024)或更高。但通过多帧合成技术,从视频流中提取的照片质量可以接近专用照片模式——系统会在你按下快门的前后各取几帧,用多帧降噪和超分辨率算法合成一张高质量照片。这意味着”在 4K 视频中截图”和”在照片模式中拍照”的质量差距在缩小。
零快门延迟的实现
传统照片捕获从按下快门到实际拍摄有约 200-300ms 延迟。从视频流提取帧则不同——视频一直在录,你按下快门的那一刻对应的帧就是你要的帧,延迟接近零。对于抓拍场景(体育、儿童、宠物),这个差异意味着能不能拍到决定性瞬间。
代码片段
从视频流中提取高质量照片帧
import AVFoundation
class VideoPhotoCapture: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate {
let session = AVCaptureSession()
let videoOutput = AVCaptureVideoDataOutput()
func setup() {
session.sessionPreset = .photo // 使用照片质量预设
let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)!
let videoInput = try! AVCaptureDeviceInput(device: videoDevice)
session.addInput(videoInput)
videoOutput.setSampleBufferDelegate(self, queue: captureQueue)
session.addOutput(videoOutput)
session.startRunning()
}
// 视频帧回调
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
// 保存最近几帧用于后续提取
recentBuffers.append(sampleBuffer)
if recentBuffers.count > 10 {
recentBuffers.removeFirst()
}
}
// 从缓冲区提取高质量照片
func capturePhoto() {
guard let buffer = recentBuffers.last else { return }
// 将视频帧转换为照片质量图像
let pixelBuffer = CMSampleBufferGetImageBuffer(buffer)!
let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
let context = CIContext()
let cgImage = context.createCGImage(ciImage, from: ciImage.extent)!
let image = UIImage(cgImage: cgImage)
// 保存照片
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}
}
使用 AVCapturePhotoOutput 的快速捕获
// 配置快速照片捕获
let photoOutput = AVCapturePhotoOutput()
photoOutput.isFastCaptureEnabled = true
photoOutput.isHighResolutionCaptureEnabled = true
// 拍照
let settings = AVCapturePhotoSettings()
settings.isHighResolutionPhotoEnabled = true
settings.photoQualityPrioritization = .balanced // 速度和质量的折中
photoOutput.capturePhoto(with: settings, delegate: self)
// 在 delegate 中获取照片
func photoOutput(_ output: AVCapturePhotoOutput,
didFinishProcessingPhoto photo: AVCapturePhoto,
error: Error?) {
guard let data = photo.fileDataRepresentation() else { return }
let image = UIImage(data: data)
// 这张照片经过 Smart HDR 和 Deep Fusion 处理
}
同时录制视频和拍照
// 同时添加视频和照片输出
let session = AVCaptureSession()
session.addOutput(videoDataOutput)
session.addOutput(photoOutput)
// 录制视频的同时可以随时拍照
// 不需要停止录制
func startRecording() {
movieFileOutput.startRecording(to: outputURL, recordingDelegate: self)
}
// 在录制过程中随时调用
func takePhotoWhileRecording() {
let settings = AVCapturePhotoSettings()
photoOutput.capturePhoto(with: settings, delegate: self)
// 视频继续录制,不受影响
}
最佳实践
拍照 App: 如果你做的是拍照 App,考虑用视频流提取帧的方式替代传统拍照流程。零快门延迟 + 计算摄影的组合让用户体验大幅提升。注意处理高分辨率帧的内存压力——不要在内存中保存太多帧缓冲区。
视频 App: 在视频录制界面提供”拍照”按钮,让用户在录视频时随时截图。提取的帧质量比传统截图好得多(经过了降噪和 HDR 处理)。
还有什么值得关注
- ProRes 视频格式在 iPhone 13 Pro 上支持,可以用于专业视频拍摄。
- Cinematic 视频模式支持拍摄后的焦点调整。
- 从视频帧提取的照片会保留 EXIF 元数据,包括时间戳和相机参数。