Music API 接入文档#
版本:v1 · 更新:2026-10-20 · 基础地址:https://music.op.wiki
在线阅读 · OpenAPI JSON · Python 下载脚本
应用分流已于 2026-10-20 00:04:35(UTC+8)发布:页面、API、歌词、封面及生成中音频保持 https://music.op.wiki;仅 completed 普通音频和 ALAC packet 使用 https://music.zr.wiki(Cloudflare)。music.op.wiki 的入口方案为中国大陆走 AxisNow、海外走 Cloudflare,DNS 配置尚待迁移侧完成;应用配置保持不变,本次应用发布未修改 DNS/CDN。同源配置仍受支持;始终使用 API 实际返回的完整 URL,不自行换域名。
本接口提供音乐搜索、音频准备与下载、歌词、推荐和歌单解析。最常用的下载流程是:
搜索取得歌曲 ID → 创建播放任务 → 等待 completed → 下载 audio_url。
1. 下载一首歌#
1.1 搜索并确认歌曲#
下面示例使用 Apple Music;可替换平台及搜索词。
curl --fail-with-body --silent --show-error --get \
'https://music.op.wiki/api/v1/search' \
--data-urlencode 'platform=applemusic' \
--data-urlencode 'q=晴天 周杰伦' \
--data-urlencode 'limit=5'
返回数组,每项包含 id、song、singer、cover 和 platform。核对歌名、歌手及版本,把选中项的 id 作为下一步的 selected_id。不要把播放任务 ID 当作平台歌曲 ID。
1.2 创建任务#
将下面两处占位内容替换为上一步确认的歌曲 ID 和歌名:
curl --fail-with-body --silent --show-error \
'https://music.op.wiki/api/v1/playbacks' \
-H 'Content-Type: application/json' \
--data '{
"platform": "applemusic",
"query": "替换为歌曲名",
"selected_id": "替换为搜索结果的id",
"quality": "hires",
"include_cover": false
}'
普通下载省略 streaming_mode。指定了 selected_id,query 仍然必须填写非空字符串。
响应结构示意:
{
"playback": {
"id": "applemusic--示例歌曲ID--hires",
"status": "queued",
"quality": "hires"
},
"status_url": "/api/v1/playbacks/applemusic--示例歌曲ID--hires",
"audio_url": "/api/v1/playbacks/applemusic--示例歌曲ID--hires/audio?rev=example-native-revision",
"cover_url": "/api/v1/playbacks/applemusic--示例歌曲ID--hires/cover",
"lyrics_url": "/api/v1/playbacks/applemusic--示例歌曲ID--hires/lyrics"
}
这里省略了 playback 的其他字段。实际返回的 ID 和 rev 由服务器生成,直接使用响应中的 URL,不要照抄示例值。
200:已经完成,可进入下载步骤。202:任务已接受或正在复用尚未完成的任务,需要继续查询。- 状态以
playback.status为准。命中缓存可能直接得到completed。
1.3 等待 completed#
以 API 基础地址解析响应的 status_url;状态请求始终留在 API 域。例如:
curl --fail-with-body --silent --show-error \
'https://music.op.wiki/api/v1/playbacks/替换为实际任务ID'
查询接口直接返回任务对象,读取顶层 status,没有 playback 包装。
| status | 含义 | 下载客户端的处理 |
|---|---|---|
| queued | 已排队 | 等待后再查询 |
| processing | 准备音频中 | 等待后再查询 |
| streaming | 部分流式内容已可用,整首尚未完成 | 普通文件下载继续等待 |
| completed | 音频准备完成 | 下载 audio_url |
| failed | 准备失败 | 停止轮询,显示 error |
建议每 1–2 秒查询一次,并设置总等待时限,例如 10 分钟。这是客户端建议,不是服务端承诺的准备时长。不要为轮询重复 POST,也不要并行发送相同状态查询。
相同状态 URL 出现多次是正常轮询,不代表重复下载了歌曲。completed 后首次读取文件仍可能需要恢复缓存或生成兼容音频,下载请求的读取超时不宜过短。
1.4 保存文件#
仅在 completed 后,使用最新状态响应中的 audio_url。同源配置返回相对路径,须以 https://music.op.wiki 解析;双 CDN 配置返回 https://music.zr.wiki 的绝对媒体 URL。queued/processing/streaming 阶段的媒体地址仍为 API 域相对路径。不要沿用较早状态的旧地址,也不要自行替换域名或丢弃查询参数:
# 将最新 completed 响应的 audio_url 原样填入,保留查询参数。
AUDIO_PATH='替换为返回的audio_url'
AUDIO_URL="$(python3 -c 'import sys; from urllib.parse import urljoin; print(urljoin("https://music.op.wiki/", sys.argv[1]))' "$AUDIO_PATH")"
curl --fail --show-error --location \
--connect-timeout 15 --max-time 900 \
--remote-name --remote-header-name \
"$AUDIO_URL"
这个响应是音频字节,不是 JSON。保存格式应以这次文件响应的 Content-Type 和 Content-Disposition 为准。
特别是 Apple Music 的 Lossless/Hi-Res:任务中的 format 可能是 m4a,而 audio_url 实际返回兼容的无损 audio/flac。不要硬改成 .mp3,也不要使用任务的 byte_size 校验兼容文件长度。应使用文件响应自身的 Content-Length(若有)。
audio_url 返回无损兼容文件,不提供“保证原始 ALAC 容器字节不变”的下载接口。source_url 是原平台来源链接,不是本服务下载地址。
1.5 用脚本自动完成#
下载本页附带的 download_song.py,仅依赖 Python 3 标准库:
# 用上一步的真实歌曲 ID 替换占位内容。
python3 download_song.py \
--platform applemusic \
--query '歌曲名 歌手' \
--id '搜索结果中的id' \
--quality hires
也可以只传某首歌的公开平台链接,由服务端解析:
python3 download_song.py \
--platform applemusic \
--query '替换为完整的Apple Music单曲链接' \
--quality lossless
不传 --id 而只给搜索词时,平台会自行解析结果,不能保证就是你想要的版本;需要精确下载时先搜索并传 ID。省略 --output 会根据文件响应命名;可用 --output ./指定文件名.flac 自行指定正确扩展名。脚本不会覆盖已有文件,下载失败会清理自己创建的临时文件。
多首兼容 FLAC 的服务端文件名可能同为 browser-lossless.flac;下载第二首时请用 --output 指定不同文件名,或保存到不同目录。
--timeout 控制任务准备总时限,默认 600 秒;--read-timeout 控制音频响应的单次网络等待,默认 120 秒,首次生成兼容文件较慢时可调大,例如 --read-timeout 900。运行 python3 download_song.py --help 查看选项。脚本会串行查询状态、等待整首完成、流式写入文件,保留所选音质;不会一次把整首音频读入内存。
脚本默认以 https://music.op.wiki 解析相对地址,并已信任其返回的 https://music.zr.wiki 完成媒体地址;两种配置均无需修改下载器或额外传入 --media-base-url,脚本不会改写返回的 URL。API 轮询只访问 --base-url。自建服务若使用其他媒体域,显式传入 --base-url https://api.example.com --media-base-url https://media.example.com。所有请求不会携带 Cookie、Authorization 或浏览器会话。脚本使用明确的 MusicAPI-Downloader User-Agent;不需要伪装浏览器,也不要转发个人登录信息。
2. 通用约定#
| 项目 | 约定 |
|---|---|
| 基础地址 | https://music.op.wiki |
| 路径前缀 | /api/v1;健康检查为 /health |
| 请求 / 响应 | JSON 使用 UTF-8;音频和封面接口返回二进制 |
| 认证 | 当前部署不要求 API Key 或调用者登录 |
| 请求头 | JSON POST 需要 Content-Type: application/json |
| 浏览器头 | 不需要复制 Cookie、Referer、sec-ch-ua 或伪装 User-Agent |
| URL | 同时支持相对路径与绝对 URL,使用 new URL(task.audio_url, base) 或 Python urljoin(base, task["audio_url"]);保留全部查询参数 |
| 完成媒体 | 双 CDN 配置下,仅 completed 的 /audio 与 /audio/stream 使用 https://music.zr.wiki;未配置媒体域时保持同源,始终以 API 返回的 URL 为准 |
| 动态请求 | queued/processing/streaming 的媒体地址、页面、API、状态、歌词和封面保持 https://music.op.wiki |
| 时间 / 大小 | API 的 duration 为秒,byte_size 为字节,bitrate 为 bit/s |
| 空值 | 可选元数据可能为 null 或空字符串;调用方应允许将来新增字段 |
媒体使用匿名 GET/HEAD/Range,不需要 Cookie 或 Authorization。独立媒体域的跨域访问须允许浏览器读取 Content-Disposition、Content-Length、Content-Range、Accept-Ranges、Content-Encoding 和 X-Audio-Stream-Id;命令行 curl/Python 不受浏览器 CORS 限制。状态、搜索、推荐和歌词始终请求 API 基础地址;媒体域不是新的 API 入口。
同一平台、歌曲、音质通常复用同一任务;ID 不是用户专属,也不是鉴权凭据。应把它当成不透明字符串保存,不依赖其内部拼接规则。不同音质分别创建任务,播放/下载时提交当前所需音质。
当前没有取消任务、批量下载、账户管理或服务器端私人歌单管理接口。关闭连接不等于取消服务端准备任务。任务不是永久下载凭证;若状态返回 404,可以用原始平台、歌曲 ID、query 和音质重新创建。
3. 平台与音质#
平台#
使用 GET /api/v1/platforms 获取实时列表和别名。当前规范 ID:
| 平台 | platform |
|---|---|
| Apple Music | applemusic |
| Bilibili | bilibili |
| 酷狗音乐 | kugou |
| 网易云音乐 | netease |
| 汽水音乐 | soda |
| QQ 音乐 | tencent |
| YouTube Music | youtubemusic |
平台出现在列表中不表示所有曲目、地区和音质始终可用;平台能力及上游状态可能不同。推荐接口目前仅支持 Apple Music;歌单/专辑解析目前支持 Apple Music、网易云。
音质#
| quality | 建议用途 |
|---|---|
| standard | 标准音质 |
| high | 高品质;默认值 |
| lossless | 无损音质 |
| hires | 高解析无损音质 |
外部接入建议使用上表小写规范值。quality 表示请求档位,并不保证源曲目拥有对应采样率或编码。Apple Music 的 Lossless 优先选择最高 48 kHz 以内的无损变体,Hi-Res 优先选择更高采样率;其他平台按自身能力处理。实际文件格式以下载响应为准,不把 quality 当作扩展名。
4. 接口速查#
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /health | 服务健康检查 |
| GET | /api/v1/platforms | 平台列表 |
| GET | /api/v1/search | 搜索歌曲 |
| POST | /api/v1/playbacks | 创建或复用播放任务 |
| GET | /api/v1/playbacks/{id} | 查询任务状态 |
| GET | /api/v1/playbacks/{id}/audio | 普通播放 / 文件下载 |
| GET | /api/v1/playbacks/{id}/audio/stream | 专用 WASM ALAC 分包流 |
| GET | /api/v1/playbacks/{id}/cover | 封面 |
| GET | /api/v1/lyrics | 通过平台歌曲 ID 获取歌词 |
| GET | /api/v1/playbacks/{id}/lyrics | 通过任务获取歌词 |
| GET | /api/v1/playbacks/{id}/loudness | 响度测量 |
| GET | /api/v1/recommendations | 推荐歌曲 |
| GET | /api/v1/recommendations/home | 推荐首页分区 |
| GET / POST | /api/v1/recommendations/continue | 队列续播候选 |
| GET | /api/v1/collections/resolve | 解析公开歌单 / 专辑 |
| POST | /api/v1/collections/match | 跨平台歌曲匹配 |
机器可读参数与数据模型见 OpenAPI JSON,可导入支持 OpenAPI 3.0 的接口工具。以下为接入时常用说明。
5. 搜索、任务和下载接口#
GET /health#
返回:
{"status":"ok","service":"music-api"}
它确认服务可响应,不代表所有上游平台的下载能力均已通过检查。
GET /api/v1/platforms#
返回数组:[{ "id": "applemusic", "label": "Apple Music", "aliases": ["am", "..."] }]。示例中的省略号仅用于简写;实际 aliases 是完整别名数组。
GET /api/v1/search#
| 参数 | 必填 | 默认 / 限制 | 说明 |
|---|---|---|---|
| platform | 是 | 平台 ID 或别名 | 搜索平台 |
| q | 是 | 建议提供非空关键词 | 歌名、歌手等搜索内容 |
| limit | 否 | 10;按 1–20 裁剪 | 结果数量上限 |
返回 SearchItem[]:
[
{
"platform": "applemusic",
"id": "示例歌曲ID",
"song": "示例歌名",
"singer": "示例歌手",
"cover": "https://example.com/cover.jpg"
}
]
cover 可能为空字符串。搜索不创建播放任务。
POST /api/v1/playbacks#
| JSON 字段 | 必填 | 默认 | 说明 |
|---|---|---|---|
| platform | 是 | 无 | 平台 ID / 别名 |
| query | 是 | 无 | 非空歌曲名、链接或平台 ID |
| selected_id | 否 | null | 精确指定搜索结果 ID,优先于 query 解析 |
| quality | 否 | high | 建议 standard / high / lossless / hires |
| include_cover | 否 | true | 是否请求准备封面;只下载音频建议 false |
| streaming_mode | 否 | null | 仅专业播放器使用 wasm_alac;普通下载省略 |
返回 {playback, status_url, audio_url, cover_url, lyrics_url}。字段 URL 即使在 queued 状态也会出现,URL 存在不代表文件已就绪。同任务复用时,已有任务的封面准备方式等设置不一定被新的请求覆盖。
应用只识别 wasm_alac 作为特殊传输模式,其他值按未指定处理。不要通过未知 mode 请求其他输出格式。
GET /api/v1/playbacks/{id}#
返回 PlaybackTask,核心字段如下。所有可空字段在早期状态可能没有值。
| 字段 | 类型 | 说明 |
|---|---|---|
| id / status | string | 不透明任务 ID / 五种任务状态 |
| platform / query / quality | string | 规范平台、原始查询和请求音质 |
| track_id / selected_id | string 或 null | 解析后的平台歌曲 ID;未手动传 selected_id 时也可能填入解析结果 |
| include_cover | boolean | 任务的封面准备设置 |
| title / artist / album | string 或 null | 歌名 / 歌手 / 专辑 |
| source_url | string 或 null | 平台来源链接,不是音频下载 URL |
| format / content_type | string 或 null | 任务源文件元信息,可能与兼容 audio 响应不同 |
| byte_size / bitrate / duration | number 或 null | 源文件字节数、bit/s、秒 |
| decrypt_elapsed_seconds | number 或 null | 解密耗时,秒;非所有路径都有 |
| error | string 或 null | failed 时的失败信息 |
| streaming_mode | string 或 null | 协商的传输模式 |
| streaming_codec / streaming_protocol | string 或 null | ALAC 时为 alac / splayer-alac-v2 |
| media_revision | string | 不透明的本次媒体生成标识;不是内容哈希,也不表示永久不可变 |
| audio_url | string | 标准音频地址;completed 时可为配置媒体域的绝对 URL,其他状态或同源配置返回 API 域相对路径 |
| cover_url / lyrics_url | string | API 域相对路径 |
| streaming_url | string 或 null | 专用分包地址,不是常规音乐文件;completed 时可为配置媒体域的绝对 URL,生成中或同源配置返回相对路径 |
任务在多个客户端间共享:即使本次创建没有请求 WASM,后续状态查询也可能带回另一客户端协商的 wasm_alac 字段。普通下载客户端仍按 completed → audio_url 处理,不自动改用 streaming_url。
GET /api/v1/playbacks/{id}/audio#
completed:返回可供常规播放器使用的音频。首次访问可能仍需恢复远端缓存或准备无损兼容文件。streaming且是原生 AAC 路径:可以返回持续增长的audio/mp4,供支持它的播放器使用;普通下载仍建议等待 completed。streaming且是 WASM ALAC 路径:该端点返回409,等待 completed;分包播放器使用下一节的专用地址。- queued、processing、failed 等未完成状态:
409。未知任务:404。
常见成功响应:
HTTP/1.1 200 OK
Content-Type: audio/flac
Content-Disposition: inline; filename="browser-lossless.flac"
Content-Length: 12345678
Accept-Ranges: bytes
Cache-Control: public, max-age=86400, no-transform
上面长度仅为示例。接口使用 inline;浏览器直接打开可能播放音频,而非弹出“另存为”。下载程序应主动保存响应体。
完成的本地文件支持单段 Range:
Range: bytes=0-1048575
Range: bytes=1048576-
Range: bytes=-4096
每次只使用其中一种。206 响应通过 Content-Range 表示返回范围。多段、越界或无效范围可能返回 416;仍在增长的流不支持随机 Range。远端缓存路径是否返回 206 取决于上游响应,不能无条件假定续传成功。
需要续传时,可用 curl --continue-at - --output 已有部分文件 "$AUDIO_URL",并确认服务器接受范围请求;不要把返回的 200 完整文件直接拼接到旧内容后。完成成功媒体使用 Cache-Control: public, max-age=86400, no-transform,可按正常浏览器/CDN 缓存语义读取,不要额外发送 Cache-Control: no-store。生成中音频使用 no-store, no-transform;动态 API、未就绪及错误响应使用 no-store。
任务 ID(包括旧客户端的 v=任务ID 参数)不是内容哈希。任务的 media_revision 表示本次媒体生成实例,返回 URL 中的 rev 进一步区分普通音频与 ALAC packet 表示。rev 在同一次生成从 streaming 变为 completed 时保持不变,重新生成后可能改变。它仍不是内容哈希,不能作为无限缓存依据。保留完整 URL;旧 rev 与当前版本不符时,源站返回 409 与 no-store,重新读取任务状态获得当前地址。旧客户端不传 rev 仍兼容,但没有此版本保护。
续传时还须确认 X-Audio-Stream-Id 与旧文件一致,并检查 206、Content-Range、总长度及无内容编码;身份不符时重新下载,不拼接两次生成的文件。缓存中的历史完成版本可能在 24 小时内继续由 CDN 提供,因此应结合版本 URL 和文件身份校验,不仅依赖任务 ID。
GET /api/v1/playbacks/{id}/audio/stream#
高级接口,仅用于明确支持本项目协议的解码器:
- 创建时请求
streaming_mode: "wasm_alac",但最终以服务器返回的 transport 字段为准;不保证每个平台/文件都提供它。 - 返回
application/x-splayer-alac,协议标记SPLALAC1,版本 2,包含 ALAC cookie 和分包长度、时长、数据。 - 可在 streaming 时持续接收并解码;completed 后可读取完整分包文件。
- 未协商该模式返回
406;尚无可用流返回409。 - 这不是 MP3、FLAC、普通 M4A 或标准 HLS。不要将它直接交给普通
<audio>,也不要把保存结果改名为这些格式。 - 完整分包流的 Range 与普通音频文件的 Range 是两种不同表示,不能拼接混用。
- 分包流在生成中使用 API 域;双 CDN 配置下,completed 后的完整分包 URL 使用媒体域,同源配置仍使用 API 域。保留全部参数,缓存及身份校验要求与普通完成音频相同,不能因换域而跳过
rev、X-Audio-Stream-Id或 Range 校验。
下载普通歌曲文件无需调用此接口。
GET /api/v1/playbacks/{id}/cover#
返回图片字节。任务未完成返回 409,没有封面或文件不可用返回 404。include_cover: true 也不能保证每首歌必有封面;搜索结果中的 cover URL 可作为展示来源。
6. 歌词和响度#
GET /api/v1/lyrics#
| 参数 | 必填 | 说明 |
|---|---|---|
| platform | 是 | 平台 ID |
| track_id | 是 | 平台歌曲 ID,非空 |
| title | 否 | 歌名;提供后有助于元数据匹配与补充来源 |
| artist / album | 否 | 歌手 / 专辑 |
| duration | 否 | 时长,非负整数,单位秒 |
无需先创建音频任务,适合与音频准备并行请求。
GET /api/v1/playbacks/{id}/lyrics#
使用已有任务的歌曲信息取歌词,无需重复传入标题、歌手等字段。两种歌词接口都返回:
{
"platform": "applemusic",
"track_id": "示例歌曲ID",
"available": true,
"plain": "[00:00.00]示例歌词",
"translation": ""
}
文本通常为逐行 LRC,不承诺逐字时间或翻译一定存在。找不到歌词通常是 200 配合 available: false、空文本,不能只用 HTTP 状态判断是否有歌词。
GET /api/v1/playbacks/{id}/loudness#
返回响度测量状态:
{"state":"pending","version":1}
就绪示例:
{
"state": "ready",
"version": 1,
"integrated_lufs": -18.5,
"true_peak_dbfs": -2.0,
"gain_db": 1.0
}
state 为 pending / ready / unavailable;非 ready 时数值字段省略。integrated_lufs 单位 LUFS,true_peak_dbfs 虽保留这个字段名,实际测量单位为 dBTP,gain_db 为建议增益 dB。
接口只分析服务端本地已存在的完整音频,不为测量而额外下载源文件;pending 可稍后查询,unavailable 时客户端保持原音量即可。此接口不是下载歌曲的必需步骤。
7. 推荐接口#
推荐目前只支持 applemusic。它使用服务端共享推荐源,不是 API 调用者自己的个人账号推荐,不要求调用者提交 Apple Music Cookie,也没有收听历史回传接口。
GET /api/v1/recommendations#
返回 SearchItem[]。
| 参数 | 默认 | 说明 |
|---|---|---|
| platform | applemusic | 当前仅支持此平台 |
| limit | 20 | 1–50,超出范围会裁剪 |
| refresh | false | 请求刷新推荐来源 |
| exclude | 空字符串 | 逗号分隔的已见歌曲 ID,最多保留 500 个有效 ID |
exclude 仅保留 1–20 位、非全零的数字 ID,去重后忽略无效项。refresh=true 不保证上游立刻变化或所有结果全新;建议持续携带已见 ID,结果数量可能少于 limit。
GET /api/v1/recommendations/home#
参数与上节相同,返回:
{
"source": "applemusic-personal",
"tags": [],
"playlists": [],
"tracks": []
}
tracks:SearchItem[]。tags:每项含id, label, subtitle, playlist_ids[]。playlists:每项含id, resource_type, name, curator, description, cover, url, recommendation_id。limit控制歌曲数量,不是卡片数量。- 歌单/专辑卡片通过
collections/resolve解析其 URL,再逐首创建任务。点击卡片、解析卡片本身不会自动下载整份歌单。
GET / POST /api/v1/recommendations/continue#
根据当前歌曲取得队列续播候选;队列较长时优先使用 POST:
POST /api/v1/recommendations/continue
Content-Type: application/json
{
"platform": "applemusic",
"seed_id": "替换为当前歌曲的数字ID",
"exclude": ["已在队列中的数字ID", "已经播放的数字ID"],
"limit": 10
}
上面 ID 为占位值,需换成实际数字 ID。seed_id 必填且必须是 1–20 位非全零数字 ID;platform 默认 applemusic,limit 默认 10、裁剪到 1–50,exclude 默认空数组、最多保留 10000 个有效 ID。种子歌曲会自动排除。
GET 使用同名查询参数,exclude 改为逗号分隔字符串。返回 { "source": "...", "tracks": [...] },source 可能为 applemusic-related 或 applemusic-personal。候选可能混合相关推荐和共享推荐补充,不能把 source 当成逐首推荐理由。
推荐接口返回 Cache-Control: no-store。它们不创建音频任务、不修改客户端队列;调用方自己决定如何入队和播放。
8. 歌单与跨平台匹配#
GET /api/v1/collections/resolve#
| 参数 | 必填 | 说明 |
|---|---|---|
| platform | 是 | 目前支持 applemusic、netease |
| url | 是 | 公开歌单/专辑链接或平台支持的资源 ID |
| limit | 否 | 1–5000;不传则完整解析,超过 5000 首明确失败 |
返回 {platform,id,title,source_url,items: SearchItem[]}。显式 limit 用于预览;想导入完整歌单时不要无意设置较小 limit。
Apple Music 支持歌单 URL、pl.* ID、专辑 URL 和 album:<数字ID>。带 ?i=歌曲ID 的单曲链接不应作为歌单解析。网易云支持歌单/专辑 URL,以及 playlist:<ID>、album:<ID>。
该接口只返回歌曲元数据,不创建下载任务,也不把歌单保存到服务端。页面“我的歌单”和播放队列属于网页本地数据。
POST /api/v1/collections/match#
{
"source_platform": "netease",
"target_platform": "applemusic",
"items": [
{
"id": "源平台歌曲ID",
"song": "示例歌名",
"singer": "示例歌手",
"cover": ""
}
]
}
单次 1–200 首;cover 可省略,默认空字符串。超过 200 首时客户端分批提交并保持原顺序。
返回字段:source_platform,target_platform,matched_count,review_count,missing_count,items。每项为:
{
"source": {"id":"源平台歌曲ID","song":"示例歌名","singer":"示例歌手","cover":""},
"status": "review",
"confidence": 82,
"candidates": []
}
此处为字段结构示意。status 为 matched / review / missing,confidence 为 0–100,candidates 为目标平台 SearchItem[]。
review 建议让用户确认候选;missing 也可能来自搜索失败或超时,不等于已证明曲目不存在。同平台匹配直接保留输入并返回 matched/100,并不重新验证每个 ID。接口不创建任务、不下载音频、不修改歌单;选定候选后使用其目标平台 ID 创建任务。
9. 错误与重试#
业务错误通常返回:
{"detail":"错误说明"}
但缺少必填字段、JSON 类型错误、错误 Content-Type 等可能由框架直接返回文本,网关错误也可能不是 JSON。客户端先判断 HTTP 状态和 Content-Type,再尝试读取 detail;JSON 解析失败时保留简短文本错误。
| HTTP 状态 | 常见含义 / 建议 |
|---|---|
| 200 | 成功;文件接口为二进制,其他接口通常为 JSON |
| 202 | 创建任务已接受,继续查状态 |
| 206 | 文件 Range 请求成功,按 Content-Range 处理 |
| 400 | 参数、平台能力或业务条件不满足,阅读 detail |
| 404 | 任务或文件不存在;封面缺失也属于此类 |
| 406 | 请求专用 ALAC 流,但任务未协商该模式 |
| 409 | 文件/流尚未就绪,先检查任务状态 |
| 416 | Range 无效、越界或不支持多段 |
| 415 / 422 | 可能的请求类型或 JSON 字段校验错误 |
| 500 / 502 / 503 | 服务或上游暂时异常,适度退避重试 |
HTTP 200 + status: failed 是任务失败,不是音频准备成功。显示 task.error,停止轮询;用户选择重试时可以重新 POST 原请求。同 ID 正在准备时不要通过不断 POST 来“催进度”。
建议对短暂网络/5xx 错误退避重试,例如 2、4、8 秒;避免高并发重复请求同一歌曲。当前文档不承诺固定的并发配额、每秒请求数或下载完成时限。
10. 常见问题#
为什么拿到链接仍下载不了?
任务创建时就返回 URL;等待 completed,再访问 audio_url。409 通常表示尚未准备好。
Hi-Res 只能下载到 FLAC,是降音质了吗?
ALAC 到 FLAC 是无损兼容表示转换,不能仅凭扩展名判断降音质。源曲目实际可用规格决定内容;接口不承诺每首歌都有高采样率版本。
能否直接使用 streaming_url 下载?
可取得专用分包数据,但它不是常规音乐文件。普通下载使用 audio_url。
需要把浏览器复制出来的整串请求头都带上吗?
不需要。正常 GET 无需浏览器伪装头,JSON POST 带 Content-Type 即可。
是否需要调用者提供自己的 Apple Music 账号或会员信息?
当前接入不需要这些凭据;调用服务公开接口即可。上游可用性由服务端配置及平台状态决定。
能不能按 API 一键下载整个歌单?
没有批量下载接口。先解析歌单,再逐首执行下载流程;客户端负责进度、失败记录和并发控制。
状态请求出现了三次,是下载了三遍吗?
不是。状态响应是小型 JSON,音频位于另一条路径。直到任务可用或完成前都可能需要轮询。