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

PHPicker选相册视频后,TrimVideoViewController中AVFoundation无法播放求助

PHPicker选视频后AVFoundation无法播放的解决方案

问题背景

我有两个ViewController:GetStartedViewController(根视图控制器)和TrimVideoViewController。在根控制器中通过PHPicker选取视频后,将URL传入第二个控制器的AVFoundation组件,但视频完全无法播放。尝试过将视频复制到其他目录、寻找第三方框架(大多仅支持HTTP链接)均未解决问题。


具体解决步骤

1. 确保视频URL的访问权限有效

PHPicker返回的是临时沙盒URL,跨ViewController传递时容易丢失访问权限。正确做法是传递PHPickerResult的NSItemProvider,在目标VC中重新加载可访问的本地文件:

// GetStartedViewController中传递数据
if let result = picker.selectedItems.first {
    let trimVC = TrimVideoViewController()
    trimVC.videoItemProvider = result.itemProvider
    navigationController?.pushViewController(trimVC, animated: true)
}

// TrimVideoViewController中加载视频
class TrimVideoViewController: UIViewController {
    var videoItemProvider: NSItemProvider!
    private var player: AVPlayer?
    private var playerLayer: AVPlayerLayer?
    @IBOutlet weak var videoView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        loadVideoFromItemProvider()
    }

    private func loadVideoFromItemProvider() {
        guard videoItemProvider.hasItemConformingToTypeIdentifier(UTType.movie.identifier) else { return }
        videoItemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { [weak self] url, error in
            guard let self = self, let url = url else { return }
            DispatchQueue.main.async {
                self.setupPlayer(with: url)
            }
        }
    }

    private func setupPlayer(with url: URL) {
        self.player = AVPlayer(url: url)
        self.playerLayer = AVPlayerLayer(player: self.player)
        self.playerLayer?.frame = self.videoView.bounds
        self.playerLayer?.videoGravity = .resizeAspectFill
        self.videoView.layer.addSublayer(self.playerLayer!)
        self.player?.play()
    }
}

2. 避免AVPlayer/AVPlayerLayer被提前释放

必须将player和playerLayer声明为ViewController的成员属性,不能用局部变量,否则会被ARC自动释放,导致视频无法播放。

3. 验证视频文件的可用性

可以通过AVAsset检查视频是否能正常加载:

private func validateVideo(url: URL) {
    let asset = AVAsset(url: url)
    asset.loadValuesAsynchronously(forKeys: ["duration"]) {
        var error: NSError?
        switch asset.statusOfValue(forKey: "duration", error: &error) {
        case .loaded:
            print("视频有效,时长:\(asset.duration.seconds)秒")
        case .failed:
            print("视频加载失败:\(error?.localizedDescription ?? "未知错误")")
        default:
            break
        }
    }
}

4. 确认权限配置

在Info.plist中添加相册访问权限描述,避免权限不足导致无法读取视频:

<key>NSPhotoLibraryUsageDescription</key>
<string>需要访问相册以选择和播放视频</string>

内容的提问来源于stack exchange,提问作者SunnySideUp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:00:55