• 从已有音频反推音符数据,异步任务
  • 结果为结构化的乐器与音符,不一定是 .mid 文件
  • 适合二次编曲与音色替换
POST/v1/music/generations/midi

认证

string必填

所有接口均使用 Bearer Token 进行认证。

获取 API Key:访问控制台 创建。

请求时在请求头中添加:

Authorization: Bearer YOUR_OAIRoute_KEY

请求参数

string可选

音频模型,默认 suno,目前只有这一个取值。

string必填

生成源音轨的那次任务的 task_id。缺失或无法定位源音轨时,提交时直接返回 400。

integer可选

指定引用源任务结果 data.result.music[] 中的第几首,默认 1,从 1 起始。

一次生成一般产出 2 首,索引 1 与 2。

本端点无版本维度,传 version 会被丢弃,也不影响计费。

响应

integer

响应状态码,成功为 200。

data[] 的元素字段 · 2 项
string

任务状态,取值 submitted。

string

任务唯一标识,用于轮询 GET /v1/music/tasks/{task_id}。

结果结构

完成结果通常包含:

result 的元素字段 · 2 项
string

解析状态。

array

识别出的乐器数组。每个元素含 notes[],提供音符数据。

当前不保证直接返回 .mid 文件 URL。拿到的是结构化的音符数据,需要自己转换成 MIDI 文件。这一点与多数人的预期不同,先确认返回结构再决定怎么用。

怎么把音符数据转成 MIDI

拿到 result.instruments[].notes[] 后,可以用任意 MIDI 库写出文件。Python 下 mido 最简单:

import mido
from mido import Message, MidiFile, MidiTrack

def to_midi(instruments, path="out.mid", ticks_per_beat=480):
    mid = MidiFile(ticks_per_beat=ticks_per_beat)

    for inst in instruments:
        track = MidiTrack()
        mid.tracks.append(track)

        channel = inst.get("channel", 0) % 16
        program = inst.get("program", 0)

        track.append(Message("program_change", program=program, channel=channel, time=0))

        for note in inst.get("notes", []):
            pitch = int(note["pitch"])
            start = int(note["start"] * ticks_per_beat)
            dur = max(1, int(note.get("duration", 0.25) * ticks_per_beat))

            track.append(Message("note_on", note=pitch, velocity=80,
                                 channel=channel, time=start))
            track.append(Message("note_off", note=pitch, velocity=0,
                                 channel=channel, time=dur))

    mid.save(path)
    return path

字段名(pitch、start、duration)以实际返回为准,第一次接的时候先打印一条音符看结构。

用途

用途说明
换音色保留旋律,改用自己音源库里的钢琴或弦乐
二次编曲在 DAW 里调整配器与和声
乐谱导出转成 MusicXML 后生成五线谱
旋律分析提取音高序列做统计或检索

从音频反推音符本身就是有损的。和弦密集、失真严重的段落,识别结果会有偏差。想要精确的 MIDI,最好从干净的乐器独奏开始。

错误码

错误响应的格式、状态码与重试建议见错误码与限流,常见报错的排查步骤见常见问题。

使用示例

提交一个任务并拿到 task_id:

提交成功只表示任务已受理。真正的产物要拿返回的 task_id 去任务查询接口轮询,status 变成 completed 之后才有结果。