如何从PHAsset类型的视频资源中提取UIImage格式的预览图
实现方案
你需要使用系统Photos框架提供的PHImageManager即可完成PHAsset到预览UIImage的转换,具体实现如下:
基础通用实现(获取视频默认缩略图)
该方法性能更高,适合列表批量加载视频预览的场景:
import Photos import UIKit /// 从视频PHAsset获取预览图 /// - Parameters: /// - asset: 视频对应的PHAsset资源 /// - targetSize: 期望返回的图片尺寸,传`PHImageManagerMaximumSize`可获取原图尺寸 /// - completion: 结果回调,默认不在主线程,操作UI需自行切到主队列 func getVideoThumbnail(from asset: PHAsset, targetSize: CGSize = CGSize(width: 300, height: 300), completion: @escaping (UIImage?) -> Void) { let options = PHImageRequestOptions() options.isSynchronous = false // 按需调整图片质量策略:.opportunistic先返低清再返高清 / .highQualityFormat仅返高清 / .fastFormat仅返低清 options.deliveryMode = .highQualityFormat // 允许下载iCloud上存储的资源 options.isNetworkAccessAllowed = true PHImageManager.default().requestImage( for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options ) { image, info in // 过滤掉自动返回的低清降级图,不需要过滤可以删掉这行判断 guard let isDegraded = info?[PHImageResultIsDegradedKey] as? Bool, !isDegraded else { return } completion(image) } }
自定义时间点预览实现
如果需要获取视频指定秒数位置的预览图,使用AVAssetImageGenerator实现:
import AVFoundation /// 从视频PHAsset获取指定时间点的预览图 /// - Parameters: /// - asset: 视频对应的PHAsset资源 /// - seconds: 要截取的视频时间点,单位为秒 /// - completion: 结果回调,默认不在主线程,操作UI需自行切到主队列 func getVideoThumbnailAtTime(from asset: PHAsset, seconds: Double = 1, completion: @escaping (UIImage?) -> Void) { let options = PHVideoRequestOptions() options.isNetworkAccessAllowed = true PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { avAsset, _, _ in guard let avAsset = avAsset else { completion(nil) return } let imageGenerator = AVAssetImageGenerator(asset: avAsset) // 自动修正视频方向 imageGenerator.appliesPreferredTrackTransform = true let targetTime = CMTimeMakeWithSeconds(seconds, preferredTimescale: 600) do { let cgImage = try imageGenerator.copyCGImage(at: targetTime, actualTime: nil) completion(UIImage(cgImage: cgImage)) } catch { completion(nil) } } }
注意事项
- 调用前需要确保已经获取了相册访问权限,否则会返回空图片
- 所有回调默认在子线程执行,如果要直接更新UI,需要在completion内手动调用
DispatchQueue.main.async切换到主线程 - 批量加载列表预览时建议把
deliveryMode设为.fastFormat或者.opportunistic,可以提升滚动流畅度
内容的提问来源于stack exchange,提问作者user15916080
相关产品推荐
相关产品推荐

