API REFERENCE · V1

声鉴台接口文档

通过同一套上传流程调用“音频分析”和“Suno 反推提示词”。当前为公开测试接口,返回 JSON,模型为 Qwen3.5 Omni Plus。

BASE URLhttps://audioanalysis.newpmusic.com公开测试环境

01 · QUICK START

接入流程

1上传音频

获得临时 uploadId

2选择任务

analysisreversePrompt

3读取结果

取得内容、耗时、Token 和费用

4删除音频

任务结束后清理临时文件

推荐方式

服务端或同事系统接入时,使用下方“上传音频 → 调用任务 → 删除音频”的流程。网页前端若希望上传更快,可使用后面的浏览器直传流程。

02 · UPLOAD

POST/api/audio
上传音频

使用 multipart/form-data 上传文件,文件字段名固定为 audio。成功后返回一个32位临时编号。

字段类型说明
audioFile · 必填MP3、WAV、AAC、FLAC 或 OGG,文件不超过60MB。
curl -X POST "https://audioanalysis.newpmusic.com/api/audio" \
  -F "audio=@/path/to/song.mp3"

成功响应

{ "uploadId": "f5b82b7d93d94ce7b9b7c0fa2c78f110" }
DELETE/api/audio?id=:uploadId
删除临时音频

分析完成或失败后都应调用。成功返回 204 No Content

curl -X DELETE \
  "https://audioanalysis.newpmusic.com/api/audio?id=上传接口返回的 uploadId"

03 · AUDIO ANALYSIS

POST/api/analyze/qwen
音频分析

先判断音频主体;只有歌曲或纯音乐才生成详细分析。自定义提示词只允许询问当前音频和音乐范围内的内容。

字段类型说明
uploadIdstring · 必填*上传接口返回的临时编号;与 uploadToken 二选一。
uploadTokenstring · 必填*浏览器直传流程返回的凭证;与 uploadId 二选一。
task"analysis"固定为 analysis;不传时也默认执行音频分析。
promptstring · 可选本次分析要求,最多1000字符;为空时使用默认分析提示词。
curl -X POST "https://audioanalysis.newpmusic.com/api/analyze/qwen" \
  -H "Content-Type: application/json" \
  -d '{
    "uploadId": "上传接口返回的 uploadId",
    "task": "analysis",
    "prompt": "请分析曲风、BPM、情绪、人声和编曲"
  }'

成功响应示例

{
  "provider": "qwen",
  "model": "qwen3.5-omni-plus",
  "task": "analysis",
  "prompt": "请分析曲风、BPM、情绪、人声和编曲",
  "elapsedMs": 13651,
  "usage": {
    "audioInputTokens": 1498,
    "textInputTokens": 1081,
    "outputTextTokens": 599,
    "totalTokens": 3178,
    "requests": 1,
    "estimatedCostCny": 0.110921
  },
  "analysis": {
    "audioType": "song",
    "isAnalyzable": true,
    "promptResponse": "针对本次提示词的直接回答",
    "summary": "整首歌曲的概况与听感总结。",
    "estimatedBpm": 76,
    "sections": {
      "style": "曲风、节奏与气质分析。",
      "emotionTheme": "主题、情绪与叙事分析。",
      "vocalFeatures": "人声音色与演唱特点。",
      "arrangement": "乐器、结构与编曲层次。"
    }
  }
}

04 · SUNO REVERSE PROMPT

POST/api/analyze/qwen
反推提示词

先判断是否为歌曲或纯音乐,再提取可确认的曲风、情绪、人声、律动、核心乐器、编曲和混音特征,最后编译成可直接用于 Suno 的英文提示词。不会输出真实歌手名、歌名,也不会照搬歌词。

字段类型说明
uploadIdstring · 必填*上传接口返回的临时编号;与 uploadToken 二选一。
uploadTokenstring · 必填*浏览器直传流程返回的凭证;与 uploadId 二选一。
task"reversePrompt"固定为 reversePrompt。
curl -X POST "https://audioanalysis.newpmusic.com/api/analyze/qwen" \
  -H "Content-Type: application/json" \
  -d '{
    "uploadId": "上传接口返回的 uploadId",
    "task": "reversePrompt"
  }'

成功响应示例

{
  "provider": "qwen",
  "model": "qwen3.5-omni-plus",
  "task": "reversePrompt",
  "audioType": "song",
  "isAnalyzable": true,
  "elapsedMs": 18240,
  "usage": {
    "audioInputTokens": 1498,
    "textInputTokens": 1680,
    "outputTextTokens": 820,
    "totalTokens": 3998,
    "requests": 2,
    "estimatedCostCny": 0.123954
  },
  "reversePrompt": {
    "mainStyle": "Contemporary R&B ballad",
    "moodNarrative": "Intimate, restrained and bittersweet",
    "vocalToneMicro": "Warm male vocal with soft breathiness",
    "vocalControl": "Controlled mid-low register delivery",
    "tempoGroove": "76 BPM, steady 4/4 half-time groove",
    "coreDriver": "Laid-back drum and bass pocket",
    "coreInstrument1": "Clean electric guitar",
    "coreInstrument2": "Warm electric piano",
    "arrangementLayers": "Sparse verse expanding into the chorus",
    "hookChorusEnergy": "Wider vocal layers and stronger drums",
    "mixTexture1": "Warm close vocal",
    "mixTexture2": "Soft stereo ambience",
    "uncertainItems": ["key"],
    "finalSunoPrompt": "可直接复制到 Suno 的英文提示词"
  }
}
两次模型调用

反推提示词先提取音频特征,再编译 Suno Prompt,因此 usage.requests 通常为2,费用字段是两步合计。

05 · BROWSER DIRECT UPLOAD

浏览器直传 Qwen 临时存储

浏览器页面推荐使用此方式,音频不经过业务服务器。先向本站申请15分钟有效的上传凭证,再把文件与返回的全部 fields 上传至 uploadHost,最后用 uploadToken 调用任一任务。

POST/api/analyze/qwen?action=upload-policy
{
  "filename": "song.mp3",
  "mimeType": "audio/mpeg",
  "size": 7340032
}

凭证响应

{
  "uploadHost": "Qwen 返回的临时上传地址",
  "objectName": "临时文件名.mp3",
  "uploadToken": "本站签发的短时分析凭证",
  "fields": {
    "OSSAccessKeyId": "...",
    "Signature": "...",
    "policy": "...",
    "key": "...",
    "x-oss-object-acl": "...",
    "x-oss-forbid-overwrite": "...",
    "success_action_status": "200"
  }
}
  1. 创建 FormData,逐项加入响应中的所有 fields
  2. 最后加入 file,向 uploadHost 发起 multipart POST。
  3. 上传成功后,用 uploadToken 代替 uploadId调用分析接口。
  4. Qwen 临时文件最长约48小时自动清理,无须调用本站删除接口。

06 · COMMON RESPONSE

通用返回字段

字段类型说明
providerstring当前固定为 qwen。
modelstring实际调用的模型ID。
taskstringanalysis 或 reversePrompt。
elapsedMsnumber模型处理耗时,单位毫秒,不包含浏览器上传时间。
usage.audioInputTokensnumber音频输入 Token。
usage.textInputTokensnumber后台提示词与用户提示词输入 Token。
usage.outputTextTokensnumber模型输出文本 Token。
usage.totalTokensnumber所有请求的 Token 总数。
usage.requestsnumber本次任务实际调用模型的次数。
usage.estimatedCostCnynumber按当前国内公开单价估算的人民币费用;免费额度不在此扣减。

音频类型 audioType

song完整歌曲或以演唱为主体
instrumental_music纯音乐或无人声音乐
speech讲话、采访、播客等
ambient_or_noise环境声、噪声或无音乐主体
too_short内容过短,无法可靠分析
unclear主体或音质无法可靠识别

不可分析时,音频分析的 analysis.isAnalyzablefalse;反推接口的 isAnalyzablefalsereversePromptnull

07 · LIMITS & ERRORS

限制与错误处理

文件大小≤ 60MB
提示词≤ 1000字符
结果格式JSON
接口模式同步等待

应用错误通常返回 400

{ "error": "音频不能超过 60MB" }
  • 400:参数、格式、临时凭证、上传文件或模型结果不符合要求。
  • 413:请求体超过代理服务器限制。
  • 5xx:服务器或上游模型暂时不可用,可间隔数秒重试。
  • 模型分析通常需要十几秒到几十秒,调用方建议设置至少120秒超时。
  • 当前是公开测试环境,暂未要求调用方携带业务鉴权;正式提供外部系统使用前建议增加专用 API Key、限流和调用日志。

08 · COMPLETE EXAMPLE

JavaScript 完整示例

适用于浏览器或支持原生 fetchFormData 的 Node.js 运行时。

const baseUrl = "https://audioanalysis.newpmusic.com";
const form = new FormData();
form.append("audio", audioFile);

const upload = await fetch(`${baseUrl}/api/audio`, {
  method: "POST",
  body: form,
}).then(checkResponse);

try {
  const result = await fetch(`${baseUrl}/api/analyze/qwen`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      uploadId: upload.uploadId,
      task: "analysis", // 或 "reversePrompt"
      prompt: "重点分析人声与编曲", // 仅 analysis 使用
    }),
  }).then(checkResponse);

  console.log(result);
} finally {
  await fetch(
    `${baseUrl}/api/audio?id=${encodeURIComponent(upload.uploadId)}`,
    { method: "DELETE" },
  );
}

async function checkResponse(response) {
  const data = await response.json();
  if (!response.ok) throw new Error(data.error || "请求失败");
  return data;
}