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

使用MusicKit ApplicationMusicPlayer播放大音乐集合时遇远程调用超时错误

解决MusicKit大播放列表初始化超时问题

方案1:分批初始化队列并追加

一次性传入大量QueueEntry会触发远程调用超时,可先初始化小批量基础队列,再分批追加剩余歌曲:

typealias QueueEntry = ApplicationMusicPlayer.Queue.Entry

let player = ApplicationMusicPlayer.shared
let entries: [QueueEntry] = tracks.compactMap {
    guard let song = $0 as? Song else { return nil }
    return QueueEntry(song)
}

Task(priority: .high) { [player] in
    do {
        // 先初始化前200首作为基础队列
        let initialBatch = Array(entries.prefix(200))
        player.queue = .init(initialBatch, startingAt: nil)
        
        // 分批追加剩余歌曲,每批100首,追加后短暂等待避免服务过载
        let remaining = Array(entries.dropFirst(200))
        for batch in remaining.chunked(into: 100) {
            player.queue.append(batch)
            try await Task.sleep(nanoseconds: 50_000_000) // 等待50ms
        }
        
        try await player.play()
    } catch {
        print(error)
    }
}

// 给Array添加分块扩展
extension Array {
    func chunked(into size: Int) -> [[Element]] {
        return stride(from: 0, to: count, by: size).map {
            Array(self[$0..<Swift.min($0 + size, count)])
        }
    }
}

方案2:MPMusicPlayerController分批处理播放参数

改用MPMusicPlayerController时,同样通过分批设置队列+追加的方式规避超时:

let player = MPMusicPlayerController.systemMusicPlayer
let playParams: [MPMusicPlayerPlayParameters] = tracks.compactMap {
    guard let song = $0 as? Song, let id = song.id else { return nil }
    return MPMusicPlayerPlayParameters(identifier: id.rawValue, kind: .song)
}

Task(priority: .high) { [player] in
    do {
        let initialBatch = Array(playParams.prefix(200))
        player.setQueue(with: initialBatch)
        
        let remaining = Array(playParams.dropFirst(200))
        for batch in remaining.chunked(into: 100) {
            player.append(batch)
            try await Task.sleep(nanoseconds: 50_000_000)
        }
        
        player.play()
    } catch {
        print(error)
    }
}

方案3:优先播放首歌+后台追加队列

如果需要立即响应用户播放操作,可先初始化仅含第一首歌的队列,再在后台分批追加剩余内容:

Task(priority: .high) { [player] in
    do {
        guard let firstEntry = entries.first else { return }
        // 先初始化仅含第一首的队列,立即播放
        player.queue = .init([firstEntry], startingAt: firstEntry)
        try await player.play()
        
        // 后台分批追加剩余歌曲
        let remainingEntries = Array(entries.dropFirst())
        for batch in remainingEntries.chunked(into: 100) {
            player.queue.append(batch)
            try await Task.sleep(nanoseconds: 50_000_000)
        }
    } catch {
        print(error)
    }
}

核心原因说明

MPMusicPlayerControllerErrorDomain Code=9本质是MusicKit远程服务处理大量请求超时,分批操作能减少单次请求的数据量,从根源避免超时触发。分块大小建议在100-200之间,间隔时间可根据设备性能微调,50-100ms即可,完全不影响自定义排序的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 21:46:19