请求编写PHAsset扩展:从视频PHAsset提取指定时间帧
PHAsset 获取视频帧 Swift 扩展
以下是实现从视频类型PHAsset中提取指定时间帧的Swift扩展,包含异步推荐方案和同步备选方案:
import Photos import AVFoundation import UIKit extension PHAsset { /// 异步获取视频指定时间点的帧(推荐使用,避免阻塞主线程) /// - Parameters: /// - second: 目标时间点(单位:秒) /// - completion: 结果回调,返回UIImage或nil func extractVideoFrame(at second: Float, completion: @escaping (UIImage?) -> Void) { guard mediaType == .video else { completion(nil) return } let requestOptions = PHVideoRequestOptions() requestOptions.isNetworkAccessAllowed = true // 允许从iCloud拉取视频 PHImageManager.default().requestAVAsset(forVideo: self, options: requestOptions) { asset, _, _ in guard let urlAsset = asset as? AVURLAsset else { completion(nil) return } let imageGenerator = AVAssetImageGenerator(asset: urlAsset) imageGenerator.appliesPreferredTrackTransform = true // 保持视频原始方向 let targetTime = CMTimeMakeWithSeconds(Double(second), preferredTimescale: 600) do { let cgImage = try imageGenerator.copyCGImage(at: targetTime, actualTime: nil) completion(UIImage(cgImage: cgImage)) } catch { print("提取视频帧失败: \(error.localizedDescription)") completion(nil) } } } /// 同步获取视频帧(仅建议在后台线程使用,会阻塞当前线程) /// - Parameter second: 目标时间点(单位:秒) /// - Returns: 提取到的UIImage或nil func extractVideoFrameSync(at second: Float) -> UIImage? { guard mediaType == .video else { return nil } let semaphore = DispatchSemaphore(value: 0) var resultImage: UIImage? extractVideoFrame(at: second) { image in resultImage = image semaphore.signal() } semaphore.wait() return resultImage } }
使用示例
异步调用(推荐)
// 假设你已经获取到目标PHAsset实例 let videoAsset: PHAsset = // 你的视频资源 videoAsset.extractVideoFrame(at: 2.0) { frameImage in DispatchQueue.main.async { // 在主线程更新UI self.previewImageView.image = frameImage } }
同步调用(后台线程使用)
DispatchQueue.global(qos: .userInitiated).async { let frameImage = videoAsset.extractVideoFrameSync(at: 2.0) DispatchQueue.main.async { self.previewImageView.image = frameImage } }
关键说明
isNetworkAccessAllowed:开启后可以访问存储在iCloud中的视频资源appliesPreferredTrackTransform:确保生成的图片方向与视频原始方向一致,避免出现旋转错位- 异步方法不会阻塞主线程,适合UI相关操作;同步方法仅适合后台任务,主线程调用会导致UI卡顿
- 需要确保已获取相册访问权限,否则无法正常读取PHAsset
内容的提问来源于stack exchange,提问作者Sanzhar
相关产品推荐
相关产品推荐

