You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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,提问作者Діма Комар

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:03:33