通过 Apple Music API 探索音乐目录
Explore the catalog with the Apple Music API
2021年6月10日
一句话判断
Apple Music API 让你不再只是一个音乐播放器——你可以用整个 Apple Music 目录构建推荐引擎、歌单生成器和社交分享功能。
这场 Session 讲了什么
Apple Music API 是一组 RESTful 接口,允许开发者查询 Apple Music 的完整音乐目录(超过 1 亿首歌曲)、管理用户资料库(添加/删除歌曲、创建歌单)、以及获取推荐内容。这个 Session 详细讲解了 API 的认证流程、核心端点和使用模式。
认证方面,你需要通过 MusicKit 框架请求用户授权。用户授权后,你会获得一个 Music User Token,配合你的 Developer Token(JWT 格式)一起使用。Developer Token 由你在 Apple Developer Portal 生成的密钥签名,有效期最长 6 个月。Music User Token 代表特定用户的授权,有过期时间需要定期刷新。
核心端点包括:/catalog/{storefront}/search(搜索歌曲、专辑、艺人)、/me/library/songs(访问用户资料库)、/me/recommendations(获取个性化推荐)、以及 /catalog/{storefront}/playlists/{id}(获取歌单详情)。所有 API 响应都是 JSON 格式,遵循统一的资源模型(每条记录都有 id、type、attributes、relationships)。
值得深挖的点
Storefront 和本地化。 Apple Music 的目录按地区(Storefront)组织——不同地区可用的内容不同,价格不同,排行榜也不同。API 的 storefront 参数决定了查询哪个地区的目录。用户首次授权时,系统会返回他们 Apple Music 订阅所在的 Storefront。如果你做的是全球化的音乐 App,需要为每个用户使用正确的 Storefront。另外,API 返回的字符串内容(歌曲名、艺人名、编辑推荐文案)会根据 l 参数自动本地化——设置 l=zh-Hans 会返回简体中文的内容。
分页和速率限制。 Apple Music API 的列表端点使用基于 offset/limit 的分页,默认每页 25 条,最大 100 条。对于用户的资料库,如果用户有几万首歌,你需要处理大量的分页请求。Session 建议:不要一次性拉取全部数据,而是按需加载——用户滚动到列表底部时再请求下一页。速率限制方面,API 大约允许每秒 20 个请求,超过会返回 429 状态码。你需要实现指数退避重试逻辑。
代码片段
import MusicKit
// 请求 Apple Music 授权
func requestMusicAuthorization() async throws {
let status = await MusicAuthorization.request()
switch status {
case .authorized:
// 可以访问 Apple Music API
try await searchCatalog()
case .denied, .restricted:
print("用户拒绝了 Apple Music 访问权限")
default:
break
}
}
// 使用 MusicKit 搜索音乐目录
func searchCatalog() async throws {
var request = MusicCatalogSearchRequest(term: "Taylor Swift",
types: [Song.self, Artist.self])
request.limit = 20
let response = try await request.response()
for song in response.songs {
print("歌曲: \(song.title) - \(song.artistName)")
print("专辑: \(song.albumTitle ?? "未知")")
print("时长: \(song.duration) 秒")
}
for artist in response.artists {
print("艺人: \(artist.name)")
}
}
// 获取用户资料库中的歌曲
func fetchUserLibrary() async throws {
let request = MusicLibraryRequest<Song>()
let response = try await request.response()
for song in response.items {
print("资料库歌曲: \(song.title)")
}
// 处理分页
if response.items.count == response.items.limit {
var nextRequest = MusicLibraryRequest<Song>()
nextRequest.offset = response.items.count
let nextResponse = try await nextRequest.response()
// 继续处理下一页...
}
}
最佳实践
- 在请求 Music 授权时,给用户一个明确的理由说明为什么需要访问他们的 Apple Music 资料库——笼统的授权请求容易被拒绝
- 搜索建议使用
MusicCatalogSearchSuggestionsRequest而不是直接搜索,它能返回更精准的建议和热门结果 - 缓存频繁访问的数据(比如热门排行榜),避免重复的 API 调用浪费速率限制配额
- 对于用户资料库操作(添加歌曲、创建歌单),提供本地回滚机制——API 调用可能因网络问题失败,你的 UI 应该能优雅降级
还有什么值得关注
- MusicKit for Swift(iOS 15 新增)是苹果推荐的原生 API,比直接调用 RESTful 端点更方便
- Apple Music API 支持获取 ISRC(国际标准录音代码),可以用来与其他音乐服务做曲目匹配
- Web 端的 MusicKit JS 也支持类似的目录查询能力,适合做网页版音乐播放器