Browse API endpoints
post/transcribe

Convert songs and instrument stems to MIDI

Send a full song or an isolated instrument stem. Your app or agent gets editable MIDI notes for arranging, practice, playback, analysis, or sound replacement.

How this endpoint works

Use this API to build an audio-to-MIDI converter, transcription tool, practice app, arrangement assistant, or DAW feature. Split a full song into stems first when users need separate bass, drum, vocal, and instrument MIDI. MuScriptor supports automatic or selected instruments and optional note quantization.

  1. 1

    Choose the song or stem

    Pass the audio ID and optionally select one isolated stem or the instruments to detect.

  2. 2

    Wait for transcription

    Save id and poll the MIDI transcription job until it finishes or fails.

  3. 3

    Download the MIDI

    Download the .mid file and open it in your app, DAW, piano roll, or notation workflow.

Common use cases

Choose this operation when it matches the source and result your workflow needs.

Learn an instrument part

Turn an isolated bass, drum, vocal, or instrument stem into notes users can inspect and practice.

Reorchestrate a song

Import the MIDI into a DAW, change instruments, correct notes, and reshape the arrangement.

Replace sounds with a VST

Use the detected notes to trigger drums, synths, samplers, or another instrument in your software.

Processing used by 40,000+ music makers

Results people rely on

Love it! Makes everything crisp!
TG

The Grim Tower

Sensacional
F

Francisco

Highend services!
TS

Tommi, Studionet

Easy to use and high quality results.
B

Bjark

Hear audio-to-MIDI results

These MIDI transcriptions were shared by users of the same processing system exposed through the API.

Choose how the MIDI tracks are created

MuScriptor large

model="muscriptor-large"

Transcribes polyphonic audio into instrument-colored MIDI notes.

Parameters
instrument_modeInstrument track modestring | null

Controls how instrument tracks are created. auto detects instruments, select uses the instruments list as guidance, and combine_melodic combines melodic parts. Omit it to infer the mode from instruments.

Allowed values

  • auto
  • select
  • combine_melodic
instrumentsInstrument guidanceArray<string>

Guides which instrument tracks MuScriptor should transcribe. Leave the list empty to detect instruments automatically. Accepts up to 128 names, each between 1 and 64 characters.

Supported instruments

  • electric_bassBass
  • acoustic_bassAcoustic Bass
  • drumsDrums
  • acoustic_guitarAcoustic Guitar
  • clean_electric_guitarClean Electric Guitar
  • distorted_electric_guitarDistorted Electric Guitar
  • acoustic_pianoAcoustic Piano
  • electric_pianoElectric Piano
  • organOrgan
  • synth_leadSynth Lead
  • synth_padSynth Pad
  • synth_stringsSynth Strings
  • orchestra_hitOrchestra Hit
  • string_ensembleString Ensemble
  • violinViolin
  • violaViola
  • celloCello
  • contrabassContrabass
  • orchestral_harpOrchestral Harp
  • voiceVoice
  • chromatic_percussionXylophone
  • timpaniTimpani
  • brass_sectionBrass Section
  • trumpetTrumpet
  • tromboneTrombone
  • french_hornFrench Horn
  • tubaTuba
  • soprano_and_alto_saxSoprano & Alto Saxophone
  • tenor_saxTenor Saxophone
  • baritone_saxBaritone Saxophone
  • flutesFlutes
  • clarinetClarinet
  • oboeOboe
  • english_hornEnglish Horn
  • bassoonBassoon
quantize_precisionNote quantizationstring | null

Sets the timing grid for MIDI note starts and releases. Use null to preserve the timing detected by the transcription model.

Allowed values

  • 1/4
  • 1/8
  • 1/8T
  • 1/16
  • 1/16T
  • 1/32
  • 1/32T
selectionSource time range{ start: number; end: number } | null

Limits transcription to a start and end time in seconds. Omit it to transcribe the full selected source.

Code examples

Server-side example

JavaScript (Node.js)
import { writeFile } from "node:fs/promises";

const API_URL = "https://api.neuralanalog.com";
const API_KEY = process.env.NEURALANALOG_API_KEY;

async function waitForCompletion(objectType, objectId) {
  while (true) {
    const response = await fetch(`${API_URL}/status/${objectType}/${objectId}`, {
      headers: { "X-API-Key": API_KEY },
    });
    if (!response.ok) {
      throw new Error(`Status check failed with ${response.status}`);
    }

    const status = await response.json();
    if (status.is_failed) {
      throw new Error(status.error_message || `${objectType} processing failed`);
    }
    if (status.is_complete) {
      return status;
    }
    await new Promise((resolve) => setTimeout(resolve, 5000));
  }
}

const requestResponse = await fetch(`${API_URL}/transcribe`, {
  method: "POST",
  headers: {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "audio_id": "6c62f8e7-02a3-48c0-a5b5-5de87ed9c31a",
  "model": "muscriptor-large",
  "instrument_mode": "auto",
  "quantize_precision": "1/16"
}),
});
if (!requestResponse.ok) {
  throw new Error(`Transcription request failed with ${requestResponse.status}`);
}

const result = await requestResponse.json();
const jobId = result["id"];
const status = await waitForCompletion("transcription", jobId);

const downloadResponse = await fetch(
  `${API_URL}/download/transcription/${jobId}`,
  { headers: { "X-API-Key": API_KEY }, redirect: "follow" },
);
if (!downloadResponse.ok) {
  throw new Error(`Download failed with ${downloadResponse.status}`);
}
await writeFile("transcription.mid", Buffer.from(await downloadResponse.arrayBuffer()));

Parameters

Send the API key from a trusted server. Never expose it in client-side JavaScript.

JSON request body

audio_id
requiredstring

Identifies the parent audio to transcribe.

stem_id
optionalstring | null

Selects one stem from the parent audio as the transcription source.

upscaled_id
optionalstring | null

Selects a restored version of the parent audio as the source.

mastered_id
optionalstring | null

Selects a mastered version of the parent audio as the source.

temporary_mix_key
optionalstring | null

Short-lived Current Main Mix or Current All Stems Mix R2 source key.

selection
optionalobject | null

Limits transcription to a start and end time in seconds. Omit it to transcribe the full selected source.

model
optionalstring

Selects the MuScriptor large audio-to-MIDI model.

Default: "muscriptor-large"

instrument_mode
optionalstring | null

Controls how instrument tracks are created. auto detects instruments, select uses the instruments list as guidance, and combine_melodic combines melodic parts. Omit it to infer the mode from instruments.

"auto""select""combine_melodic"
instruments
optionalarray<string>

Guides which instrument tracks MuScriptor should transcribe. Leave the list empty to detect instruments automatically. Accepts up to 128 names, each between 1 and 64 characters.

Example: ["piano","bass"]

quantize_precision
optionalstring | null

Sets the timing grid for MIDI note starts and releases. Use null to preserve the timing detected by the transcription model.

"1/4""1/8""1/8T""1/16""1/16T""1/32""1/32T"

Successful response

200Successful Response
id
requiredstring

ID of the queued transcription.

Example: "d66cf940-bf26-45bb-80f7-332f26b6859a"

status
requiredstring

Queueing status for the transcription job.

Example: "starting"

message
requiredstring

Human-readable queueing result.

Example: "MIDI transcription started successfully"

Errors

A missing or invalid X-API-Key returns an authentication error. Validation errors use the declared 422 response below.
422Validation Error
detail
optionalarray<object>

No description provided.

Next steps