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

Swift应用中AVPlayer播放Documents目录MP4视频无显示问题

老哥,我之前也踩过类似的坑!结合你说的情况——视频存相册能正常查看,但存在Documents文件夹里的MP4在自定义UIView用AVPlayer播放时没反应,还能输出FILE AVAILABLE,咱们一步步排查问题:

排查步骤与解决方案

1. 先确认AVPlayerLayer是否正确挂载到自定义View

这是最容易漏的环节!你得把AVPlayer对应的AVPlayerLayer加到自定义View的layer上,还要保证它的尺寸和View匹配:

// 假设你的自定义View叫playerView,AVPlayer实例是player
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = playerView.bounds
playerLayer.masksToBounds = true // 避免视频内容超出View范围
playerView.layer.addSublayer(playerLayer)

// 如果你用AutoLayout布局,记得重写自定义View的layoutSubviews来更新layer尺寸
extension PlayerView {
    override func layoutSubviews() {
        super.layoutSubviews()
        playerLayer?.frame = bounds
    }
}

另外!千万别忘了调用player.play(),很多人配置完所有东西,唯独忘了启动播放😂

2. 检查Documents路径的完整性与文件有效性

你输出的路径是截断的,得先确认是不是拿到了完整的文件URL,还有文件是不是真的写完了:

// 获取Documents目录的正确姿势,别用字符串拼接,容易出错
guard let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
    print("Failed to access documents directory")
    return
}
let videoURL = documentsDir.appendingPathComponent("your_video.mp4")
// 打印完整URL确认
print("Full video path: \(videoURL.path)")

// 检查文件大小,确认不是空文件或者未写完的文件
if let fileSize = try? videoURL.resourceValues(forKeys: [.fileSizeKey]).fileSize {
    print("Video file size: \(fileSize) bytes")
}

注意:AVCaptureMovieFileOutput保存视频是异步的,如果你在保存完成前就初始化AVPlayer,会导致播放损坏的文件。一定要在AVCaptureMovieFileOutput.didFinishRecordingTo回调里再去初始化播放器!

3. 监听AVPlayer的加载状态,抓具体错误

有时候播放器没反应是因为加载失败了,但你没收到错误提示。给AVPlayerItem加个状态监听:

let playerItem = AVPlayerItem(url: videoURL)
// 添加监听
playerItem.addObserver(self, forKeyPath: "status", options: [.old, .new], context: nil)

// 在observeValue里处理状态变化
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    guard keyPath == "status", let item = object as? AVPlayerItem else {
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        return
    }
    
    switch item.status {
    case .readyToPlay:
        print("视频加载完成,可以播放")
        player.play()
    case .failed:
        print("播放器加载失败:\(item.error?.localizedDescription ?? "未知错误")")
    case .unknown:
        print("播放器状态未知,正在加载中")
    @unknown default:
        break
    }
}

// 记得在deinit里移除观察者,避免内存泄漏
deinit {
    playerItem.removeObserver(self, forKeyPath: "status")
}

如果这里输出.failed,就能拿到具体错误信息,比如文件损坏、编码不兼容之类的。

4. 检查视频编码兼容性

虽然你说存相册能看,但AVCaptureMovieFileOutput直接存到Documents的视频,可能编码格式和系统相册自动处理后的有差异?试试用AVAssetExportSession重新导出一次,转成标准MP4:

let asset = AVAsset(url: videoURL)
guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else {
    print("无法创建导出会话")
    return
}

let outputURL = documentsDir.appendingPathComponent("exported_video.mp4")
exportSession.outputURL = outputURL
exportSession.outputFileType = .mp4

exportSession.exportAsynchronously {
    DispatchQueue.main.async {
        switch exportSession.status {
        case .completed:
            print("导出完成,试试播放这个新视频:\(outputURL)")
            let newPlayer = AVPlayer(url: outputURL)
            // 用这个newPlayer去初始化你的播放器试试
        case .failed:
            print("导出失败:\(exportSession.error?.localizedDescription ?? "未知错误")")
        default:
            break
        }
    }
}

如果导出后的视频能正常播放,那就是原视频的编码或容器格式有问题。

5. 快速调试小技巧

  • 把自定义View的背景色改成红色,确认它确实显示在界面上了,不是View本身没渲染导致的“无任何显示”
  • 检查视频轨是否存在:
let asset = AVAsset(url: videoURL)
asset.loadValuesAsynchronously(forKeys: ["tracks"]) {
    DispatchQueue.main.async {
        var error: NSError?
        let status = asset.statusOfValue(forKey: "tracks", error: &error)
        if status == .loaded {
            let videoTracks = asset.tracks(withMediaType: .video)
            print("视频轨数量:\(videoTracks.count)")
        } else {
            print("加载视频轨失败:\(error?.localizedDescription ?? "未知错误")")
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:24:55