You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Apple Music歌曲播放异常排查:MPMusicPlayerController调用问题

问题排查与解决方案

看起来你遇到的核心问题是使用了错误的队列描述符类型,再加上对用户库歌曲的播放逻辑处理不当,导致播放器无法正确构建播放队列,进而出现超时和命令发送失败的错误。下面一步步拆解问题并给出修复方案:

1. 核心错误:误用Queue Descriptor

你当前使用的MPMusicPlayerStoreQueueDescriptor是专门为Apple Music Store中的非用户库歌曲设计的,但你的歌曲属于用户iCloud媒体库(从返回的isLibrary = 1type = "library-songs"可以确认),这类歌曲需要使用MPMusicPlayerMediaItemQueueDescriptor来构建播放队列——因为它依赖本地/云端同步的MPMediaItem实例,而非Store ID。

你传入的i.B0VN4GGf7Eldk是Apple Music API返回的iCloud库歌曲ID,这个ID对应MPMediaItemMPMediaItemPropertyCloudItemID属性,而不是Store ID,所以用它来初始化MPMusicPlayerStoreQueueDescriptor完全不匹配,这就是播放器无法识别队列、出现超时和错误的根本原因。

2. 修复后的代码实现

首先需要通过iCloud库ID查询对应的MPMediaItem,再用它来构建播放队列:

import MediaPlayer

let musicPlayerController = MPMusicPlayerController.systemMusicPlayer

func beginPlayback(cloudItemID: String) {
    // 1. 创建查询条件,匹配iCloud库歌曲ID
    let predicate = MPMediaPropertyPredicate(value: cloudItemID, forProperty: MPMediaItemPropertyCloudItemID)
    let query = MPMediaQuery(songs: [predicate])
    
    guard let mediaItems = query.items, !mediaItems.isEmpty else {
        print("未找到对应库歌曲")
        return
    }
    
    // 2. 使用媒体项创建队列描述符
    let descriptor = MPMusicPlayerMediaItemQueueDescriptor(mediaItems: mediaItems)
    descriptor.startItem = mediaItems.first // 设置开始播放的歌曲
    
    // 3. 设置队列并准备播放
    musicPlayerController.setQueue(with: descriptor)
    musicPlayerController.prepareToPlay { error in
        if let error = error {
            print("准备播放失败:\(error.localizedDescription)")
            return
        }
        self.musicPlayerController.play()
    }
}

// 调用时传入API返回的id
beginPlayback(cloudItemID: "i.B0VN4GGf7Eldk")

3. 额外注意事项

  • 权限配置:确保在Info.plist中添加NSAppleMusicUsageDescription键,说明你需要访问Apple Music和媒体库的原因,否则会导致权限不足无法查询媒体项。
  • 播放器类型systemMusicPlayer是系统全局播放器,可能会和其他音乐APP的播放状态冲突,如果问题仍存在,可以尝试改用applicationMusicPlayer(仅在你的APP内生效)。
  • 错误处理:在prepareToPlay的回调中一定要处理错误,比如网络问题导致云端歌曲无法加载的情况。

4. 解释你遇到的错误日志

  • [MPMusicPlayerController prepareToPlay] timeout:因为你用了错误的Descriptor,播放器无法解析队列,导致准备播放的操作超时。
  • MPCPlayerRequestErrorDomain Code=1 "No commands provided.":播放队列无效,播放器没有可执行的播放命令。
  • Code=1000 "Failed to send command 0":队列未正确初始化,发送播放命令时失败。

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

火山引擎 最新活动