iPhone SE中PHAssetChangeRequest导入高帧率视频失败求助
从你给出的测试结果和排查细节来看,这个问题的核心应该和初代iPhone SE的硬件视频处理限制以及QuickTime视频的clean aperture参数与系统相册的兼容性有关,尤其是特定帧率+宽高比+分辨率的组合触发了系统的隐性限制。以下是具体分析和建议:
可能的问题原因
1. 初代iPhone SE的硬件处理能力限制
初代iPhone SE搭载的A9芯片,虽然性能强于iPhone 6的A8,但苹果对不同机型的慢动作视频兼容性设置可能存在差异。从你的测试数据可以看出:
- 1080p分辨率下,无论帧率120fps还是240fps,非1:1宽高比的视频全部失败
- 720p分辨率下,120fps的非1:1宽高比视频成功,但240fps的16:9失败、2.35:1成功,200fps的16:9失败、其余成功
这种差异化的结果说明,SE的硬件或系统相册导入逻辑,对高分辨率+高帧率+非标准宽高比的组合存在隐性限制,无法正确处理这类视频的解码或元数据解析。
2. Clean Aperture元数据的兼容性问题
你提到通过clean aperture参数设置视频宽高比,而系统相册(Photos框架)对QuickTime视频的元数据格式有严格要求:
- 非1:1宽高比的视频,如果clean aperture参数与视频实际像素宽高比不匹配,或者缺少对应的display aperture等辅助元数据,会导致Photos框架无法正确识别视频的有效显示区域,从而抛出模糊的
NSCocoaErrorDomain Code=-1错误。 - 成功的视频(比如1:1宽高比的所有组合)可能刚好符合Photos框架对元数据的预期,而失败的组合则触发了元数据解析的异常。
3. 慢动作视频的特殊元数据缺失
iPhone的原生慢动作视频会携带Apple专属的元数据标记(比如com.apple.quicktime.slowmo),用于告知系统相册这是慢动作视频。如果你的自定义录制视频只设置了高帧率,但未添加这类专属元数据,Photos框架在SE上可能无法正确归类和处理视频,尤其是非标准宽高比的情况。
建议的排查与解决方向
1. 验证并修正Clean Aperture元数据
使用工具(如ffmpeg)对比成功和失败视频的元数据差异,确保clean aperture的宽高比与视频实际像素宽高比严格一致:
ffmpeg -i your_failed_video.mov ffmpeg -i your_success_video.mov
重点查看Stream #0:0中的clean aperture和display aperture参数,确保失败视频的这些参数与成功视频格式一致。
2. 添加Apple专属慢动作元数据
尝试在生成视频时添加苹果专属的慢动作元数据标记,比如通过AVFoundation的AVMutableMetadataItem添加:
let asset = AVAsset(url: yourVideoURL) let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough)! let slowmoMetadata = AVMutableMetadataItem() slowmoMetadata.key = AVMetadataKey(rawValue: "com.apple.quicktime.slowmo") slowmoMetadata.value = Data([0x01, 0x00, 0x00, 0x00]) // 示例值,可参考原生慢动作视频的元数据 exportSession.metadata = [slowmoMetadata] // 执行导出逻辑,之后再尝试导入相册
3. 为iPhone SE单独适配视频参数
根据测试结果,为SE机型单独调整视频参数:
- 避免使用1080p+120/240fps+非1:1宽高比的组合
- 优先选择720p+120fps+任意宽高比,或720p+200/240fps+1:1/2.35:1的组合
4. 捕获更详细的错误信息
默认的错误信息过于模糊,在performChanges的回调中打印完整的错误userInfo,获取更多细节:
PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url) }) { success, error in if let error = error { print("完整错误信息: \(error)") print("错误用户信息: \(error.userInfo)") } }
有时候userInfo中会包含具体的失败原因,比如“视频格式不支持”或“元数据无效”。
5. 用AVAssetExportSession重新导出视频
借助系统的导出会话修正视频的编码和元数据问题,再尝试导入相册:
let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent("fixed_slowmo.mov") let asset = AVAsset(url: yourOriginalVideoURL) let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)! exportSession.outputURL = tempURL exportSession.outputFileType = .mov exportSession.shouldOptimizeForNetworkUse = true exportSession.exportAsynchronously(completionHandler: { DispatchQueue.main.async { // 导出完成后,尝试导入tempURL的视频到相册 PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: tempURL) }) { success, error in // 处理结果 } } })
内容的提问来源于stack exchange,提问作者Oyvindkg

