import SwiftUI import PhotosUI import AVFoundation import os.log struct VideoPicker: UIViewControllerRepresentable { @Binding var selectedVideoURL: URL? @Binding var thumbnailImage: UIImage? var onDismiss: (() -> Void)? func makeUIViewController(context: Context) -> PHPickerViewController { var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared()) configuration.filter = .videos configuration.selectionLimit = 1 configuration.preferredAssetRepresentationMode = .current let picker = PHPickerViewController(configuration: configuration) picker.delegate = context.coordinator return picker } func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, PHPickerViewControllerDelegate { let parent: VideoPicker private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.example.app", category: "VideoPicker") init(_ parent: VideoPicker) { self.parent = parent } func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { guard let result = results.first else { parent.onDismiss?() return } // 获取视频URL result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { [weak self] url, error in guard let self = self, let videoURL = url, error == nil else { self?.logger.error("Failed to load video: \(error?.localizedDescription ?? "Unknown error")") DispatchQueue.main.async { self?.parent.onDismiss?() } return } // 创建临时文件URL let tempDirectory = FileManager.default.temporaryDirectory let targetURL = tempDirectory.appendingPathComponent("\(UUID().uuidString).\(videoURL.pathExtension)") do { // 将视频复制到临时目录 if FileManager.default.fileExists(atPath: targetURL.path) { try FileManager.default.removeItem(at: targetURL) } try FileManager.default.copyItem(at: videoURL, to: targetURL) // 提取视频首帧 MediaUtils.extractFirstFrame(from: targetURL) { [weak self] result in switch result { case .success(let image): DispatchQueue.main.async { self?.parent.thumbnailImage = image self?.parent.selectedVideoURL = targetURL self?.parent.onDismiss?() } case .failure(let error): self?.logger.error("Failed to extract video thumbnail: \(error.localizedDescription)") DispatchQueue.main.async { self?.parent.onDismiss?() } } } } catch { self.logger.error("Failed to copy video file: \(error.localizedDescription)") DispatchQueue.main.async { self.parent.onDismiss?() } } } } } }