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

如何让AVPlayerItem遵循Codable协议?Mac开发编码解码问题

解决AVPlayerItem无法Codable编码解码的问题

你遇到的核心问题是AVPlayerItem本身并不遵循Codable协议,系统没有为它提供默认的编码解码实现,所以直接对它调用encode或decode方法会报错。要解决这个问题,你需要间接存储可序列化的数据源,再通过这些数据重新生成AVPlayerItem,而非直接存储AVPlayerItem实例。

方案一:存储视频数据源(URL/本地路径)

如果你的AVPlayerItem是从本地文件或远程URL创建的,最直接的方式是存储对应的URL:

class ProjectState2: ObservableObject, Codable {
    enum CodingKeys: CodingKey {
        case videoURL
    }

    // 存储可序列化的URL,而非AVPlayerItem
    private var videoURL: URL
    // 计算属性返回AVPlayerItem,同时通过@Published发布变化
    @Published var video: AVPlayerItem {
        didSet {
            // 当AVPlayerItem变化时,同步更新videoURL
            if let asset = video.asset as? AVURLAsset {
                videoURL = asset.url
            }
        }
    }

    // 用AVMutableComposition初始化的构造方法
    init(composition: AVMutableComposition) {
        // 可根据composition生成对应的标识,比如临时文件路径
        self.videoURL = URL(fileURLWithPath: "")
        self.video = AVPlayerItem(asset: composition)
    }

    // Codable初始化方法
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.videoURL = try container.decode(URL.self, forKey: .videoURL)
        // 从URL重新生成AVPlayerItem
        self.video = AVPlayerItem(url: videoURL)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(videoURL, forKey: .videoURL)
    }
}

方案二:序列化AVMutableComposition

如果你的AVPlayerItem基于AVMutableComposition创建,可以利用AVMutableComposition遵循NSCoding的特性,将其归档为Data存储:

class ProjectState2: ObservableObject, Codable {
    enum CodingKeys: CodingKey {
        case compositionData
    }

    private var compositionData: Data
    @Published var video: AVPlayerItem

    // 用AVMutableComposition初始化
    init(composition: AVMutableComposition) {
        // 将AVMutableComposition归档为Data
        do {
            self.compositionData = try NSKeyedArchiver.archivedData(withRootObject: composition, requiringSecureCoding: false)
        } catch {
            self.compositionData = Data()
            // 这里可添加自定义错误处理逻辑
        }
        self.video = AVPlayerItem(asset: composition)
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.compositionData = try container.decode(Data.self, forKey: .compositionData)
        // 从Data解档回AVMutableComposition,再生成AVPlayerItem
        guard let composition = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(compositionData) as? AVMutableComposition else {
            throw DecodingError.dataCorrupted(.init(codingPath: [CodingKeys.compositionData], debugDescription: "Failed to unarchive AVMutableComposition"))
        }
        self.video = AVPlayerItem(asset: composition)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(compositionData, forKey: .compositionData)
    }
}

注意事项

  • 方案二中的异常处理可根据业务需求优化,避免使用强制解包导致崩溃。
  • 如果AVMutableComposition包含外部视频片段,需确保解码时这些资源的路径仍有效,或同步存储相关资源的标识信息。
  • @Published修饰的video属性会在重新赋值时自动触发视图更新,需保证数据源变化时video能被正确刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 01:05:19