如何为PHPickerViewController添加类UIImagePickerController的视频编辑压缩功能
实现PHPickerViewController选视频后的编辑与压缩功能
你说得没错,iOS 14+推出的PHPickerViewController确实砍掉了allowsEditing这个属性,官方也明确不再提供原生的编辑入口,但我们可以借助系统的AVPlayerViewController和AVAssetExportSession来复刻出类似UIImagePickerViewController的视频裁剪+压缩功能,下面是完整的实现方案:
步骤1:修改PHPicker回调,获取视频资源
首先在picker(_:didFinishPicking:)方法里,我们需要从选中的PHPickerResult中提取视频资源,并转换成AVAsset:
extension EditController: PHPickerViewControllerDelegate { @available(iOS 14, *) func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) guard let result = results.first else { return } // 只处理视频类型资源 guard result.itemProvider.canLoadObject(ofClass: AVAsset.self) else { return } result.itemProvider.loadObject(ofClass: AVAsset.self) { [weak self] asset, error in guard let self = self, let videoAsset = asset as? AVAsset else { return } DispatchQueue.main.async { // 打开系统自带的视频编辑控制器 self.presentVideoEditor(for: videoAsset) } } } }
步骤2:用AVPlayerViewController实现视频裁剪
系统的AVPlayerViewController自带视频裁剪功能,只需要开启allowsEditing属性就能唤起和UIImagePicker一致的裁剪界面:
extension EditController: AVPlayerViewControllerDelegate { private func presentVideoEditor(for asset: AVAsset) { let playerItem = AVPlayerItem(asset: asset) let player = AVPlayer(playerItem: playerItem) let playerVC = AVPlayerViewController() playerVC.player = player // 开启编辑(裁剪)功能 playerVC.allowsEditing = true playerVC.delegate = self present(playerVC, animated: true) } // 编辑完成后的回调 func playerViewController(_ playerViewController: AVPlayerViewController, didFinishEditingVideoWithEditedVideoURL editedVideoURL: URL?, duration: TimeInterval) { playerViewController.dismiss(animated: true) guard let editedVideoURL = editedVideoURL else { // 用户取消了编辑操作 return } // 对裁剪后的视频进行压缩处理 compressVideo(at: editedVideoURL) { compressedURL in // 这里拿到压缩后的视频URL,可用于上传、本地保存等后续操作 print("压缩完成,文件路径:\(compressedURL)") } } }
步骤3:实现视频压缩功能
使用AVAssetExportSession对裁剪后的视频进行压缩,你可以根据需求调整导出的预设参数:
private func compressVideo(at inputURL: URL, completion: @escaping (URL) -> Void) { let asset = AVAsset(url: inputURL) // 选择压缩预设,可根据需求替换为AVAssetExportPresetLowQuality/HighQuality等 guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality) else { // 导出会话创建失败,返回原视频 completion(inputURL) return } // 设置导出路径(临时目录,可根据需求改为沙盒其他路径) let outputFileName = "\(UUID().uuidString).mp4" let outputURL = FileManager.default.temporaryDirectory.appendingPathComponent(outputFileName) exportSession.outputURL = outputURL exportSession.outputFileType = .mp4 // 开启网络优化,让导出的视频更适合传输 exportSession.shouldOptimizeForNetworkUse = true exportSession.exportAsynchronously { switch exportSession.status { case .completed: DispatchQueue.main.async { completion(outputURL) } case .failed, .cancelled: // 压缩失败,返回原视频 DispatchQueue.main.async { completion(inputURL) } default: break } } }
补充说明
AVPlayerViewController的编辑功能仅支持裁剪,如果你需要更复杂的编辑(比如添加滤镜、文字),可能需要自行封装或使用第三方库,但对于大部分和allowsEditing=true匹配的场景,这个方案完全够用。- 压缩预设可以根据需求灵活选择:
AVAssetExportPresetLowQuality(最小体积)、AVAssetExportPresetMediumQuality(体积与质量平衡)、AVAssetExportPresetHighestQuality(最高质量)等。 - 记得在
Info.plist中添加NSPhotoLibraryUsageDescription权限描述,确保App能正常访问相册资源。
内容的提问来源于stack exchange,提问作者Діма Комар
相关产品推荐
相关产品推荐

