85 lines
3.4 KiB
Swift
85 lines
3.4 KiB
Swift
import AVFoundation
|
||
import UIKit
|
||
import os.log
|
||
|
||
/// 媒体工具类,提供视频处理相关功能
|
||
enum MediaUtils {
|
||
private static let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.example.app", category: "MediaUtils")
|
||
|
||
/// 从视频URL中提取第一帧
|
||
/// - Parameters:
|
||
/// - videoURL: 视频文件的URL
|
||
/// - completion: 完成回调,返回UIImage或错误
|
||
static func extractFirstFrame(from videoURL: URL, completion: @escaping (Result<UIImage, Error>) -> Void) {
|
||
let asset = AVURLAsset(url: videoURL)
|
||
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
|
||
assetImgGenerate.appliesPreferredTrackTransform = true
|
||
|
||
// 获取视频时长
|
||
let duration = asset.duration
|
||
let durationTime = CMTimeGetSeconds(duration)
|
||
|
||
// 如果视频时长小于等于0,返回错误
|
||
guard durationTime > 0 else {
|
||
let error = NSError(domain: "com.yourapp.media", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid video duration"])
|
||
completion(.failure(error))
|
||
return
|
||
}
|
||
|
||
// 获取第一帧(时间点为0)
|
||
let time = CMTime(seconds: 0, preferredTimescale: 600)
|
||
|
||
// 生成图片
|
||
assetImgGenerate.generateCGImagesAsynchronously(forTimes: [NSValue(time: time)]) { (_, cgImage, _, result, error) in
|
||
if let error = error {
|
||
logger.error("Failed to generate image: \(error.localizedDescription)")
|
||
DispatchQueue.main.async {
|
||
completion(.failure(error))
|
||
}
|
||
return
|
||
}
|
||
|
||
guard result == .succeeded, let cgImage = cgImage else {
|
||
let error = NSError(domain: "com.yourapp.media", code: -2, userInfo: [NSLocalizedDescriptionKey: "Failed to generate image from video"])
|
||
logger.error("Failed to generate image: \(error.localizedDescription)")
|
||
DispatchQueue.main.async {
|
||
completion(.failure(error))
|
||
}
|
||
return
|
||
}
|
||
|
||
// 创建UIImage并返回
|
||
let image = UIImage(cgImage: cgImage)
|
||
DispatchQueue.main.async {
|
||
completion(.success(image))
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 从视频数据中提取第一帧
|
||
/// - Parameters:
|
||
/// - videoData: 视频数据
|
||
/// - completion: 完成回调,返回UIImage或错误
|
||
static func extractFirstFrame(from videoData: Data, completion: @escaping (Result<UIImage, Error>) -> Void) {
|
||
// 创建临时文件URL
|
||
let tempDirectoryURL = FileManager.default.temporaryDirectory
|
||
let fileName = "tempVideo_\(UUID().uuidString).mov"
|
||
let fileURL = tempDirectoryURL.appendingPathComponent(fileName)
|
||
|
||
do {
|
||
// 将数据写入临时文件
|
||
try videoData.write(to: fileURL)
|
||
|
||
// 调用URL版本的方法
|
||
extractFirstFrame(from: fileURL) { result in
|
||
// 清理临时文件
|
||
try? FileManager.default.removeItem(at: fileURL)
|
||
completion(result)
|
||
}
|
||
} catch {
|
||
logger.error("Failed to write video data to temporary file: \(error.localizedDescription)")
|
||
completion(.failure(error))
|
||
}
|
||
}
|
||
}
|