Doseedo Film Score MCP
An official MCP server by Doseedo that enables AI agents to score video content. It spots video cuts, generates cue sheets with SMPTE hit points, renders MIDI scores using 50+ AI instrument models, mixes audio, and lays the final score onto the picture with dialogue ducking and loudness normalization.
Endpoint and access
No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.
https://api.doseedo.com/mcp/filmWhat you can do with it
- Spot video cuts and generate frame-exact cue sheets
- Render MIDI scores using AI instrument models
- Mix cues and normalize loudness for delivery
- Lay scored audio onto video with dialogue ducking
Source and maintenance
Protocol and capabilities
- Server
- doseedo-film-score 0.21.0
- MCP protocol
- 2025-06-18
- Tools
- 24 advertised
- Resources
- Not advertised
- Resource templates
- Not advertised
- Prompts
- Not advertised
{
"tools": {}
}Server-provided instructions
Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.
Tools
24 advertised
doseedo_generate_sound — Generate sound effects (SFX & foley)
SOUND EFFECTS (SFX) from words with Stable Audio Open — SOUND DESIGN and FOLEY for game audio, apps and video: impacts, whooshes, door slams, footsteps, UI blips, creature and sci-fi sounds, ambiences ("rain on a tin roof", "busy café"), risers, drum one-shots. A one-shot hit ("punchy house kick", "snare with a short room", "a riser into the drop"), a loop on the tempo grid ("glitchy percussion"), or a texture ("vinyl crackle", "rain"). kind picks which (hit | loop | texture); omitted, the server reads it off the words. Don't put a tempo in a hit's prompt — tempo words make it write a loop. Wrong tool for a part with notes (doseedo_render_midi) or a piece of music (you write it; doseedo_render_score plays it). Async: job_id → doseedo_wait_task (typically 15–40 s) → audio URLs (pre-signed: curl -OJ <url>, no auth header, valid 24 h). Cancel: a render that has not reached the GPU yet is stopped and its credits refunded; one already rendering finishes on the GPU (its credits are spent), the job ends as canceled and the output is discarded.
{
"type": "object",
"required": [
"prompt"
],
"properties": {
"bpm": {
"type": "number",
"description": "Tempo a loop is cut to (default 120)."
},
"kind": {
"enum": [
"hit",
"loop",
"texture"
],
"type": "string",
"description": "hit = one sound (0.5–10 s), loop = 1–4 bars tiled at bpm, texture = a bed. Default: read off the prompt."
},
"seed": {
"type": "number",
"description": "Optional random seed for reproducibility."
},
"prompt": {
"type": "string",
"description": "What it sounds like, e.g. \"punchy house kick drum, single hit\" or \"dusty vinyl crackle\". ≤ 300 characters."
},
"time_signature": {
"type": "string",
"description": "Meter a loop is cut to, e.g. \"4/4\" (default)."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
},
"duration_seconds": {
"type": "number",
"description": "Length in seconds. Default: 2 s for a hit, 4 bars at bpm for a loop, 8 s for a texture."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_render_midi — Render MIDI on AI instruments (MIDI to audio)
MIDI TO AUDIO, the virtual instrument for agents — THE tool for "I wrote the part, now play it": an AI instrument model (orchestral strings, brass, woodwinds, piano, guitar, bass, drums, World) performs your exact notes, in your key, at your bpm, and returns audio takes (doseedo_generate_music takes no notes or key). Input ONE of: notes[] ({pitch, start_beats, duration_beats, velocity} — beats from bar 1, the same rows as doseedo_edit_session set_midi_notes), midi_url (a .mid ≤2 MiB: a doseedo result link or a public https URL), or session_id + track_id (that track's notes, read from the session). Required: instrument (an entry's `call` from doseedo_instruments, no key — stay inside its range) and bpm. The notes are sent AS GIVEN — no pitch snapping, no quantizing. One voice per part: a chord part is rendered one voice per output with voice_split:true (result.voices maps each voice to its files and notes). Takes come back best-first (takes[0] = the scorer's winner). Async: job_id → doseedo_wait_task (~1–3 min). Result: takes[{url, rank, score}] (pre-signed: curl -OJ, no auth header, 24 h), seed, duration, voices?, refine?, chain. A take may miss or change a note — read takes[].check (measured against your notes) or listen; offer the takes, never promise note-perfection. Free harmony check first: doseedo_analyze_midi. DRUMS (GM notes): drum_engine:"oneshot" = a sampler kit made for drum_genre (default for "electronic"/"808"), every hit as written — use it on ANY kit when every hit must land; the drum model PERFORMS a kit and can drop hits (takes[].fit.missing). "synth" = a one-shot patch (synth_role, synth_genre; "performed" = played, less 1-shot); result.oneshots = the samples. SOUND: a preset (timbre_preset), a recording's tone (timbre_audio_url = timbre transfer), or YOUR OWN instrument (lora_id from doseedo_train_instrument; result.lora.applied). Cancel: a render that has not reached the GPU yet is stopped and its credits refunded; one already rendering finishes on the GPU (its credits are spent), the job ends as canceled and the output is discarded.
{
"type": "object",
"required": [
"instrument"
],
"properties": {
"bpm": {
"type": "number",
"description": "REQUIRED (or tempo_map). Tempo of the notes (10–400). Written into the MIDI's tempo meta, so start_beats/duration_beats land at exactly this tempo."
},
"seed": {
"type": "number",
"description": "Random seed (−1 or 0–4294967295). Reuse a result's seed to re-render close to the same take."
},
"tune": {
"type": "boolean",
"description": "Light intonation (default true): a held, clearly pitched note the model rendered 15–85 cents off its written pitch is moved toward it, to a small natural residual — attack and vibrato as played, fast notes left. Winds, brass and strings. false = the take exactly as rendered."
},
"notes": {
"type": "array",
"items": {
"type": "object",
"required": [
"pitch",
"start_beats",
"duration_beats"
],
"properties": {
"pitch": {
"type": "number",
"description": "MIDI note number 0–127 (60 = middle C)."
},
"velocity": {
"type": "number",
"description": "1–127 (default 96)."
},
"start_beats": {
"type": "number",
"description": "Onset in beats from bar 1."
},
"duration_beats": {
"type": "number",
"description": "Length in beats (> 0)."
}
},
"additionalProperties": false
},
"description": "The part, as note rows in beats from bar 1 (beat 0 = bar 1 beat 1, quarter-note beats at `bpm`). Monophonic for one voice; chords need voice_split:true. Up to 4096 notes."
},
"takes": {
"type": "number",
"description": "How many takes to render, 1–4 (one GPU batch; no extra credits). Omit to let the server choose best-of-N for the part length."
},
"prompt": {
"type": "string",
"description": "Optional caption override (default: the instrument id). Style words help a little; the notes are the control."
},
"refine": {
"enum": [
"light",
"shred"
],
"type": "string",
"description": "Opt-in post-render correction. \"light\": attacks re-timed onto the score, exposed wrong pitch classes re-pitched inside the played octave, misfires muted (winds/brass/strings). \"shred\": play exactly the written line, octave included, mute anything the score never wrote (any pitched mono part). The raw render stays downloadable (result.refine.raw_url)."
},
"vaefix": {
"type": "boolean",
"description": "VAE spectral corrector (default true): trims the low-mid fog the decoder adds under the instrument's register and removes mic hiss only when the take carries it. Winds, brass and strings. Receipt: vaefix. false = the decode exactly as rendered."
},
"lora_id": {
"type": "string",
"description": "A CUSTOM INSTRUMENT: the lora_id doseedo_train_instrument returned (16 hex). The render is played by that trained instrument; pass the same instrument it was trained as. Owner-only."
},
"dynamics": {
"type": "string",
"description": "One target dynamic for the whole part's tone: \"pp\", \"p\", \"mp\", \"mf\", \"f\", \"ff\", \"fff\", a 0–1 number, or a MIDI velocity as text. Omit it to let the notes' velocities shape the tone (dynamics_curve)."
},
"midi_url": {
"type": "string",
"description": "Alternative to notes: https URL of a Standard MIDI File (≤2 MiB) — a doseedo result link (a stem's MIDI) or a public URL. Its own tempo map is used by the model; bpm still tags the caption and sizes the default duration."
},
"track_id": {
"type": "string",
"description": "With session_id: the t_… id of the MIDI/instrument track to render."
},
"tempo_map": {
"type": "array",
"items": {
"type": "object",
"required": [
"beat",
"bpm"
],
"properties": {
"bpm": {
"type": "number"
},
"beat": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Tempo CHANGES for the notes: [{beat, bpm}] — each point holds from its beat (beats from bar 1) until the next; the first point is beat 0 (or bpm covers the beats before it). Written into the MIDI, so a ritardando or a tempo that lands a cue on a film hit plays exactly. doseedo_tempo_map builds one from hit times."
},
"drum_genre": {
"type": "string",
"description": "Electronic drums (instrument \"electronic\" or \"808\"): the genre whose one-shot kit plays the part — \"house\", \"techno\", \"trap\", \"drill\", \"lo-fi\", \"dnb\", \"amapiano\", \"synthwave\"… or free words. Default: the instrument."
},
"instrument": {
"type": "string",
"description": "REQUIRED. The instrument from doseedo_instruments — its `call.instrument` (e.g. \"violin\", \"tenor_sax\", \"electric_guitar\", \"piano\"; a World name such as \"koto\" is resolved to its call). Keep the notes inside its range. An unknown name close to a catalog one is refused with did_you_mean before anything is spent."
},
"session_id": {
"type": "string",
"description": "Alternative to notes: with track_id, render THAT session track's notes (read from doseedo_get_session's summary)."
},
"synth_role": {
"enum": [
"bass",
"808",
"pad",
"lead",
"pluck"
],
"type": "string",
"description": "instrument \"synth\": the patch Stable Audio Open makes for the part — bass (an 808 where the genre's bass is one), 808, pad, lead, pluck. Default: from the notes (chords = pad, a low line = bass, else lead)."
},
"drum_engine": {
"enum": [
"oneshot",
"model"
],
"type": "string",
"description": "Who plays a drum part: \"oneshot\" = a sampler kit made for drum_genre (the default for electronic / 808; congas and bongos are recordings of the skins) — every note lands exactly as written; use it on ANY kit when every hit must land. \"model\" = the drum model (the default for every other kit): a performance, which can drop or smear hits — read takes[].fit. Its pads (GM): kick 35/36, snare 38/40, rim 37, clap 39, hats 42/44/46, toms 41–50, crash 49/57, ride 51/59, tambourine 54, cowbell 56, bongos 60/61, congas 62–64, shaker 69/70/82, guiro 73/74, claves 75, woodblock 76/77, triangle 80/81."
},
"synth_genre": {
"type": "string",
"description": "instrument \"synth\": the genre the patch is made for — \"house\", \"techno\", \"trap\", \"synthwave\", \"lo-fi\", \"dnb\"… or free words."
},
"synth_words": {
"type": "string",
"description": "instrument \"synth\": extra sound words for the patch (\"reese\", \"warm analog\", \"acid\"), ≤80 chars."
},
"voice_split": {
"type": "boolean",
"description": "true = the notes hold chords: split them into the voices one player of this instrument can hold and render every voice (result.voices). Default false (a chord in a mono part is an error the model will fudge)."
},
"synth_engine": {
"enum": [
"oneshot",
"performed",
"model"
],
"type": "string",
"description": "Who plays a synth part: \"oneshot\" = a patch of one-shots made for it (the default for \"synth\"; every note the same sample), \"performed\" = that same patch (synth_role / synth_genre / synth_words pick it) played by the synth model trained on real synth loops — each note its own, the tone moving, the written notes kept (lora_strength 0.5 default; seed = another performance), \"model\" = the instrument model alone."
},
"lora_strength": {
"type": "number",
"description": "With lora_id (or synth_engine \"performed\"): how strongly the custom instrument applies, 0–2 (default 1.0, or a tuned per-adapter default; ~0.6 when a small training set overshoots; performed synth 0.5 — up to ~0.75 plays it looser, past that it starts leaving the notes)."
},
"timbre_preset": {
"type": "string",
"description": "A preset from doseedo_instruments — an entry's call.timbre_preset or presets[].call.timbre_preset (e.g. \"violin:pizz\", \"sax:alto\", \"koto:preset1\"). Omit for the instrument default."
},
"dynamics_curve": {
"type": "string",
"description": "What colours the TONE over time: omitted/\"auto\" = the note velocities when they vary (soft notes darker, loud brighter — every instrument but drums, LoRAs included); \"off\" = one colour; \"cc11\"/\"cc1\" = that CC lane of a midi_url; or \"pos:level,…\" (pos and level 0–1, e.g. \"0:0.1,1:0.9\" = a crescendo). Receipt: result.dynamics."
},
"time_signature": {
"type": "string",
"description": "Meter of the part, e.g. \"4/4\", \"3/4\", \"6/8\" (default 4/4). Written into the MIDI and the caption."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
},
"revise_take_url": {
"type": "string",
"description": "REVISE an earlier take instead of rendering a new one: the take's URL (as a render returned it). Only [revise_start_beats, revise_end_beats) is regenerated — steered by `notes` (send the whole part, with your corrections) — and spliced back with short crossfades; the rest of the take is kept as it was."
},
"duration_seconds": {
"type": "number",
"description": "Length of the render in seconds (0.01–600). Default: the last note's end + 2 s of release. Each 30 s window costs 10 credits."
},
"revise_end_beats": {
"type": "number",
"description": "With revise_take_url: end of the region to redo (exclusive), beats from bar 1."
},
"timbre_audio_url": {
"type": "string",
"description": "TIMBRE TRANSFER: https URL of a short recording (≤24 MB; its first 30 s are used) whose SOUND the render should take on — a doseedo result link or a public URL. The notes stay yours; the tone comes from the recording."
},
"revise_start_beats": {
"type": "number",
"description": "With revise_take_url: start of the region to redo, beats from bar 1."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_train_instrument — Train a custom instrument
Make a CUSTOM INSTRUMENT in your own sound: upload 30 s–3 min of ONE instrument playing (your own player, a rare or folk instrument, a prepared/invented instrument, a vintage synth) and doseedo trains a private adapter (LoRA) on its serving instrument model in about 1–2 minutes. After that, doseedo_render_midi {instrument: <the same instrument>, lora_id} plays ANY notes you write in that sound. Several takes help (up to 8 files; the first 3 min are used, ≥8 s required); a clean, solo, dry recording works best. instrument = the closest catalog instrument — it picks the model voice the adapter trains on (a shamisen trains as acoustic_guitar, a whistle as flute: doseedo_instruments lists each one's call.instrument). The notes are transcribed for you (pass notes to skip that). 20 credits. Result: lora_id, name, the windows it trained on, loss first→last, and `use` (the render args). Earlier ones: doseedo_list_jobs {kind:"train_instrument"}. Owner-only: no one else can render with it. Async: job_id → doseedo_wait_task (~1–2 min). Cancel: the plane has no stop for a running training — it runs to completion (credits spent), the job ends as canceled and its output is discarded. Only a job still queued at the plane is refunded by the plane's own failure refund.
{
"type": "object",
"required": [
"instrument"
],
"properties": {
"bpm": {
"type": "number",
"description": "Optional tempo of the recording (30–300)."
},
"name": {
"type": "string",
"description": "A name for it, e.g. \"Grandpa's banjo\" (≤80 chars)."
},
"seed": {
"type": "number",
"description": "Random seed."
},
"notes": {
"type": "array",
"description": "Optional: the notes played, one list per file — [[{pitch, start, end, velocity?}…]] in SECONDS. Omitted, they are transcribed."
},
"steps": {
"type": "number",
"description": "Training steps 50–800. Default 300 for ≤60 s of audio, 400 above."
},
"audio_key": {
"type": "string",
"description": "R2 ingest key of an uploaded audio file (from doseedo_get_upload_url / POST /api/upload/r2/ingest-url; starts with \"ingest/\"). One recording; or audio_keys for several."
},
"audio_url": {
"type": "string",
"description": "https URL of a recording (a doseedo result link — a separated stem works — or any public URL). Alternative to audio_key."
},
"drum_mode": {
"type": "boolean",
"description": "true for an unpitched percussion recording."
},
"audio_keys": {
"type": "array",
"items": {
"type": "string"
},
"description": "Several uploaded takes of the SAME instrument (≤8)."
},
"audio_urls": {
"type": "array",
"items": {
"type": "string"
},
"description": "Several recording URLs of the same instrument (≤8)."
},
"instrument": {
"type": "string",
"description": "REQUIRED. The catalog instrument it is closest to (call.instrument from doseedo_instruments, e.g. \"violin\", \"acoustic_guitar\", \"flute\", \"percussion\")."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_render_score — Render a whole score
FILM SCORING, orchestral arrangement, background music, a song or an instrumental YOU wrote: a WHOLE ARRANGEMENT in one call (a film cue, a string quartet, a big-band chart): every part played by its doseedo instrument, one stem per part from bar 1 at your tempo, plus a summed mix. Input ONE of: parts[] ({name, instrument, timbre_preset?, lora_id?, players?, notes[]} — doseedo_instruments calls), midi_url (multi-track SMF), or musicxml_url (notation played as marked, at concert pitch; what isn't: prepared.score.warnings). A file's parts are matched by name, then GM program; name any part with instruments {"<part name or index>": {instrument, timbre_preset?, players?}}. A chord on a one-line instrument is split into voices (one stem each). ★ SECTIONS: an instrument is ONE player; give a part players: N (2–8) and its line is played by N different players (each its own performance), summed into ONE section stem — that is how you write an orchestra: violins I / violins II / violas / cellos / basses as five parts with players 6 / 6 / 4 / 4 / 3, horns 2–4 in unison, a woodwind or brass line doubled; leave players out for a solo. The WHOLE orchestra in one call: ≤ 32 lines and ≤ 96 player rows (players: N = N rows), plain, sampled and World / LoRA instruments together (~1 min groups), ≤ 600 s. Drums where every hit must land: parts[].drum_engine "oneshot" (+ drum_genre). Synth parts: doseedo_render_midi. Timing: bpm and/or tempo_map ([{beat, bpm}]; doseedo_tempo_map lands film hits on downbeats). Result: parts[{name, instrument, url, fit, timbre, lora, players}] — fit.verdict / coverage = did it PLAY its notes (a failed part is re-rolled once; fit.rolls.missed = a roll not played as one), lora.applied = its adapter played — plus mix_url. Next: doseedo_mix {from_job}, then doseedo_session_from_stems {from_job, mix_job}. Async: job_id → doseedo_wait_task (~1–4 min). Cancel: a render that has not reached the GPU yet is stopped and its credits refunded; one already rendering finishes on the GPU (its credits are spent), the job ends as canceled and the output is discarded.
{
"type": "object",
"properties": {
"bpm": {
"type": "number",
"description": "Tempo of the parts (10–400). Required with parts[] unless tempo_map is given; on a file it sets the speed and keeps the score's fermatas / rit. / tempo changes."
},
"mix": {
"type": "boolean",
"description": "Also bounce a summed mix of the stems (default true)."
},
"seed": {
"type": "number",
"description": "Random seed (reuse to re-render close to the same performance)."
},
"tune": {
"type": "boolean",
"description": "Light intonation on every winds / brass / strings part (default true): held, clearly pitched notes the model rendered 15–85 cents off are moved toward their written pitch, to a small natural residual — attacks, vibrato and fast notes as played. Receipt: parts[].tune. false = every part as rendered (or parts[].tune false for one)."
},
"parts": {
"type": "array",
"items": {
"type": "object",
"required": [
"notes"
],
"properties": {
"name": {
"type": "string"
},
"tune": {
"type": "boolean",
"description": "false = this part exactly as rendered (no light intonation pass; default true)."
},
"notes": {
"type": "array",
"items": {
"type": "object",
"required": [
"pitch",
"start_beats",
"duration_beats"
],
"properties": {
"pitch": {
"type": "number"
},
"velocity": {
"type": "number"
},
"start_beats": {
"type": "number"
},
"duration_beats": {
"type": "number"
}
},
"additionalProperties": false
}
},
"vaefix": {
"type": "boolean",
"description": "false = this part's decode exactly as rendered (no VAE spectral corrector; default true)."
},
"lora_id": {
"type": "string"
},
"players": {
"type": "number",
"description": "How many players play this line: 1 (default) = a soloist; 2–8 = a SECTION — the line played by that many different players (each its own recording and performance), summed into ONE section stem. A string section = violins I, violins II, violas, cellos, basses with players 4–8 each. Each player renders (and costs) like a part."
},
"dynamics": {
"type": "array",
"items": {
"type": "object",
"required": [
"beat",
"velocity"
],
"properties": {
"beat": {
"type": "number"
},
"velocity": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "The part's written LEVEL over time, as a DAW automation lane: [{beat, velocity 1–127}] in beat order, linear between points, a step = two points on one beat, held after the last (p 52, mf 80, f 96, ff 112). A velocity says how a note STARTS; this says how it goes on — a crescendo on a held note: [{beat: 0, velocity: 52}, {beat: 8, velocity: 96}]. Its tone follows it, through a held note too, and doseedo_mix {from_job} rides the level to it. A MusicXML score's dynamics + hairpins arrive as this lane on their own."
},
"drum_genre": {
"type": "string",
"description": "With drum_engine \"oneshot\": the kit's genre / words, e.g. \"country rock, acoustic kit\", \"jazz brushes\", \"house\", \"trap\". An acoustic genre gets an acoustic kit in a small room; an electronic one a dry drum-machine kit. Default: the instrument."
},
"instrument": {
"type": "string"
},
"drum_engine": {
"enum": [
"model",
"oneshot"
],
"type": "string",
"description": "A drum / percussion part: \"oneshot\" = played through a one-shot kit generated for drum_genre — every written hit lands exactly as written (a half-time bar stays half-time, a stop-time hit stays a hit); \"model\" (default) = the drum model, a live performance that may drop or add hits (check parts[].fit.voices: missing / extra). Its pads (GM): kick 35/36, snare 38/40, rim 37, clap 39, hats 42/44/46, toms 41–50, crash 49/57, ride 51/59, tambourine 54, cowbell 56, bongos 60/61, congas 62–64, shaker 69/70/82, guiro 73/74, claves 75, woodblock 76/77, triangle 80/81."
},
"timbre_preset": {
"type": "string"
},
"dynamics_curve": {
"enum": [
"auto",
"off",
"velocity",
"cc11",
"cc1"
],
"type": "string",
"description": "What colours this part's TONE over time: auto (default) = its dynamics lane when that moves, else its note velocities when they vary — soft darker, loud brighter, on every instrument but drums; off = one colour throughout; velocity = the velocities even with a lane; cc11/cc1 = that MIDI CC lane (a midi_url part). Receipt: parts[].dynamics."
}
},
"additionalProperties": false
},
"description": "The parts you wrote: [{name?, instrument, timbre_preset?, lora_id?, players?, notes:[{pitch, start_beats, duration_beats, velocity?}], dynamics?}] — beats from bar 1, concert pitch. instrument/timbre_preset = a doseedo_instruments call. players = how many play the line: 1 (default) a soloist, 2–8 a SECTION (e.g. Violins I players 6)."
},
"vaefix": {
"type": "boolean",
"description": "VAE spectral corrector on every winds / brass / strings part (default true): the decoder's low-mid fog under each instrument's register is trimmed, mic hiss removed only where present. Receipt: parts[].vaefix. false = every decode as rendered (or parts[].vaefix false for one)."
},
"midi_url": {
"type": "string",
"description": "Alternative to parts: a multi-track Standard MIDI File (≤ 2 MiB) — a doseedo result link or a public https URL. Channel 10 = drums: the kit, or the one percussion instrument a part is named for (Bass Drum, Cymbals, Bass Drum & Cymbals, Triangle…). A track's CC11 lane (CC1 on a wind / brass / string / bass part) is its written dynamics: a held note swells as it says."
},
"score_key": {
"type": "string",
"description": "Alternative to parts: a score file on YOUR machine — doseedo_get_upload_url {filename: \"cue.mid\" | \"cue.musicxml\"} → PUT the file → its score_key (kept 24 h). A big score sent as a file, not as notes in this call."
},
"score_url": {
"type": "string",
"description": "Alternative to parts: a score file URL — MIDI or MusicXML, told apart by its content."
},
"tempo_map": {
"type": "array",
"items": {
"type": "object",
"required": [
"beat",
"bpm"
],
"properties": {
"bpm": {
"type": "number"
},
"beat": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Tempo changes [{beat, bpm}] (first point at beat 0). Overrides a file's own tempo."
},
"instruments": {
"type": "object",
"description": "Name the instrument for any part: {\"Violin I\": {\"instrument\": \"violin\", \"players\": 6}, \"2\": {\"instrument\": \"acoustic_guitar\", \"timbre_preset\": \"koto:preset1\"}} — key = the part name or its 0-based index; players makes a MIDI / MusicXML part a section, drum_engine \"oneshot\" (+ drum_genre) plays a file's drum part on a one-shot kit ({\"Drums\": {\"drum_engine\": \"oneshot\"}} — no instrument keeps the part's own). Wins over the name/program match."
},
"musicxml_url": {
"type": "string",
"description": "Alternative to parts: a MusicXML score (.musicxml / .xml / .mxl, ≤ 8 MiB) exported from Dorico, Sibelius, Finale, MuseScore, or written by you."
},
"time_signature": {
"type": "string",
"description": "Meter, e.g. \"4/4\" (default, or the file's)."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
},
"duration_seconds": {
"type": "number",
"description": "Render length (default: the last note + 2 s; ≤ 600)."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_mix — Mix and master stems
MIXING and MASTERING: each part levelled, panned, high-passed, given its depth on a shared reverb, and mastered to a loudness target — a WAV AND `mixgraph`, the mix as a document you edit. After doseedo_render_score pass from_job (its parts and the instruments they play are the stems); or stems: [{name, audio_url, instrument?}] (result links work as-is). An orchestra (strings / winds / brass / timpani / harp…) is SEATED by default (film-orchestral: violins left, low strings right, brass behind, each seat at its depth in a 2.3 s hall, written dynamics riding the faders); other stems get the blind default. style: film-orchestral, film-scoring-stage, concert-hall, film-epic-hybrid, cathedral-choral, classical-chamber, cartoon-studio, golden-age-cartoon, jazz-combo, ambient, country-pop, metal-modern, 1950s-mono, 1960s-lcr-pop, 1970s-analog-rock, 1970s-dub, 1980s-pop-gated, 1990s-rock-dry, 1990s-hiphop, 2000s-loudness-rock, 2010s-edm, 2010s-trap, 2020s-pop, 2020s-hyperpop — an id or words ("dry 90s rock"). balance {part: dB} moves parts on top of the levelling (+3 brings a melody forward). Change the mix: edit the returned mixgraph — strips[] {stem, gain_db, pan, seat, chain, sends}, buses[] (verb = the hall), master.chain, automation [{target: "strips.<stem>.gain_db", points: [[seconds, dB]…]}] for rides (dB off the strip's gain_db: 0 = as set, -60 mutes) — and call again with mix_job (this job_id) + only your edits (or the whole mixgraph + the same stems): rendered as written, rails reported, no credits. Then doseedo_session_from_stems {from_job, mix_job: <this job_id>} → the DAW project at this mix's levels and pans. TO PICTURE: dialogue (the VO; the music ducks under each line), music_offset_s (bar 1 on the picture), length_s (cut + end fade). Async: job_id → doseedo_wait_task (~15–90 s). Cancel: the plane has no stop for a running mix — it runs to completion (credits spent), the job ends as canceled and its output is discarded. Only a job still queued at the plane is refunded by the plane's own failure refund.
{
"type": "object",
"properties": {
"duck": {
"type": "object",
"properties": {
"max_db": {
"type": "number"
},
"include": {
"type": "boolean"
},
"carve_db": {
"type": "number"
},
"vo_over_db": {
"type": "number"
}
},
"description": "How the music sits under the dialogue: {vo_over_db (default 7 dB — a broadcast mix's 6–10), carve_db (default 3, at 1–4 kHz), max_db (default 12), include (default true; false = the music bed alone, ducked as if the voice played)}.",
"additionalProperties": false
},
"room": {
"anyOf": [
{
"enum": [
"studio",
"stage",
"hall",
"cathedral"
],
"type": "string"
},
{
"type": "number",
"maximum": 1,
"minimum": 0
}
],
"description": "An orchestra's room: \"studio\" (intimate scoring stage, ~1.2 s, close), \"stage\" (~1.8 s), \"hall\" (the default scoring hall, ~2.3 s), \"cathedral\" (~4 s, wet) — or 0..1 between them. Sets the decay, size and how wet every seat sits."
},
"stems": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"audio_url"
],
"properties": {
"name": {
"type": "string"
},
"audio_url": {
"type": "string"
},
"instrument": {
"type": "string"
}
},
"additionalProperties": false
},
"description": "[{name, audio_url, instrument?}] — the stems (≤ 32). instrument = the sound it plays (a doseedo_instruments id: \"violin\", \"timpani\", \"harp\"), which decides how it is mixed; without it the name decides."
},
"style": {
"type": "string",
"description": "A mix style: an id or words (\"dry 90s rock\"). Pick it for the picture — the default (film-orchestral, a 2.3 s scoring hall) suits film drama, not every orchestra: cartoon-studio = a cartoon / animation orchestra (a close, dry, wide scoring stage, punchy rides); golden-age-cartoon = a 1940s–50s cartoon (mono, small studio, tape); film-scoring-stage = intimate TV / documentary; concert-hall; film-epic-hybrid = trailer / action; cathedral-choral; classical-chamber; or jazz-combo, ambient, 1970s-analog-rock, 2020s-pop …"
},
"balance": {
"type": "object",
"description": "{part name: dB in -12..12} — your balance on top of the levelling (and of the written dynamics a from_job reads).",
"additionalProperties": {
"type": "number"
}
},
"mix_job": {
"type": "string",
"description": "MCP: a doseedo_mix job_id to edit — its whole stored mix (every ride) is the base, mixgraph is applied on top, and its stems are reused when you pass no from_job / stems."
},
"vintage": {
"enum": [
"tape",
"shellac",
"none"
],
"type": "string",
"description": "A period medium over any style, after the mix: \"tape\" = 7.5 ips tape (saturation, wow and flutter, a low hiss); \"shellac\" = a 78 played back (mono, ~90 Hz–5.5 kHz with the reproducer's presence, a 1.3 Hz wow, surface noise that swishes once a turn, crackle). \"none\" takes a style's own medium off (golden-age-cartoon carries tape). Its node (master.chain type vintage: noise_db, crackle, hi_hz …) is editable in the returned mixgraph."
},
"dialogue": {
"type": "array",
"items": {
"type": "object",
"required": [
"audio_url"
],
"properties": {
"name": {
"type": "string"
},
"audio_url": {
"type": "string"
}
},
"additionalProperties": false
},
"description": "The VO / dialogue on the picture's timeline (≤ 4): [{name?, audio_url}]. The music ducks under each line until the voice sits duck.vo_over_db over it, with a 1–4 kHz carve while it talks; the voice joins after the music's master chain. Report: output.dialogue.lines [{start_s, end_s, duck_db, vo_over_music_db}] as mixed."
},
"dynamics": {
"type": "object",
"description": "Fader rides from written dynamics: {part name: [[onset_seconds, velocity 0-127], …]}. from_job fills it from the score (pp to ff ≈ 17 dB); pass {} for no rides.",
"additionalProperties": {
"type": "array"
}
},
"from_job": {
"type": "string",
"description": "MCP: a doseedo_render_score job_id — its parts are the stems, each with the instrument it plays, and each part's written dynamics (its mean velocity) set its balance."
},
"length_s": {
"type": "number",
"maximum": 600,
"minimum": 0.5,
"description": "The program's length (a :30 = 30; ≤ 600 s): the mix is cut there with end_fade_s (default 0.5 s); the room's tail never runs past it."
},
"mixgraph": {
"type": "object",
"description": "An edited mix — the mixgraph a doseedo_mix returned, changed — rendered against the same stems (from_job or stems). With mix_job: ONLY what you change (strips[] by stem, automation[] rides by target — points: [] removes one, buses[] by id, master) — the rest is that mix as stored. A mixgraph marked `partial` (its rides summarized) is refused without mix_job. Omit for a fresh mix."
},
"end_fade_s": {
"type": "number",
"description": "With length_s: the fade at the program's end (0–10 s, default 0.5)."
},
"target_lufs": {
"type": "number",
"description": "Master loudness, -24..-6 LUFS (default: the style's — -18 for film-orchestral, -14 for the blind default). Met within ~0.3 LU (a loud target clips the shortest transients first); output.loudness says what landed, and why when short. With mix_job it re-masters the stored mix."
},
"tonal_match": {
"type": "boolean",
"description": "Nudge the master toward professionally mixed orchestral references (default on for the orchestral styles). Its presence and air are judged only where the score is written loud (written_level), so a pp passage keeps its darkness."
},
"dynamics_ride": {
"type": "number",
"description": "How hard the written dynamics move the faders: 1 = default (pp to ff ≈ 17 dB), 0 = no rides, up to 1.5."
},
"written_level": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "number"
},
"maxItems": 2,
"minItems": 2
},
"maxItems": 4096,
"description": "[[seconds, velocity], …] — the whole score's written level, the loudest part sounding, held until the next row (0 = nothing plays). The tonal match reads only the passages it writes loud (f and louder), so a pp passage keeps its darkness. from_job fills it."
},
"music_offset_s": {
"type": "number",
"maximum": 600,
"minimum": 0,
"description": "Where bar 1 of the music sits on the picture (seconds, ≤ 600; the program ≤ 600 s): every music stem — and its rides — starts this late; the dialogue does not move."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
},
"dynamics_carried": {
"type": "object",
"description": "{part name: top velocity} — parts whose stems already play their written level (a render part's dynamics_level receipt, up to its top_vel). Their rides count it: no doubled swing. from_job fills it.",
"additionalProperties": {
"type": "number"
}
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_session_from_stems — Stems → a DAW session
Build a native DAW PROJECT from stems: each stem on its own audio track from bar 1, optional MIDI tracks (the written parts) beside them, on your tempo (bpm or tempo_map) — Logic Pro (.logicx) or Ableton Live (.als), zipped. The deliverable after doseedo_render_score (pass from_job: its job_id and the stems, MIDI and tempo come from that job) or after any renders / separations you made (stems: [{name, audio_url}] — result links work as-is). After doseedo_mix add mix_job: each track at that mix's level and pan, the mix as a muted reference track. Async: job_id → doseedo_wait_task (~30–90 s) → file (pre-signed zip, curl -o session.zip <url>, 24 h). Cancel: the plane has no stop for a running session build — it runs to completion (credits spent), the job ends as canceled and its output is discarded. Only a job still queued at the plane is refunded by the plane's own failure refund.
{
"type": "object",
"properties": {
"bpm": {
"type": "number",
"description": "Project tempo (default 120)."
},
"name": {
"type": "string",
"description": "Project name."
},
"stems": {
"type": "array",
"items": {
"type": "object",
"properties": {
"pan": {
"type": "number"
},
"mute": {
"type": "boolean"
},
"name": {
"type": "string"
},
"gain_db": {
"type": "number"
},
"audio_key": {
"type": "string"
},
"audio_url": {
"type": "string"
},
"position_beats": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "[{name, audio_url | audio_key, gain_db?, pan?, mute?, position_beats?}] — the audio tracks, in order."
},
"target": {
"enum": [
"logic",
"ableton"
],
"type": "string",
"description": "Which DAW (default logic)."
},
"mix_job": {
"type": "string",
"description": "MCP: a doseedo_mix job_id — every track takes that mix's level and pan, and the mix itself rides along as a muted reference track \"Mix (doseedo)\"."
},
"from_job": {
"type": "string",
"description": "MCP: a doseedo_render_score job_id — its stems, parts' MIDI and tempo are used (no other input needed)."
},
"mixgraph": {
"type": "object",
"description": "A mix document (doseedo_mix → mixgraph): each stem named in it takes its strip's gain_db and pan. The EQ, compression, reverb and rides are not written into the project."
},
"tempo_map": {
"type": "array",
"items": {
"type": "object",
"required": [
"beat",
"bpm"
],
"properties": {
"bpm": {
"type": "number"
},
"beat": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Tempo changes [{beat, bpm}] for the project."
},
"midi_tracks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"notes": {
"type": "array",
"items": {
"type": "object"
}
}
},
"additionalProperties": false
},
"description": "Optional MIDI tracks: [{name, notes:[{pitch, start_beats, duration_beats, velocity?}]}]."
},
"time_signature": {
"type": "string",
"description": "Meter (default 4/4)."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_spot_video — Spot a video → cue sheet
SPOT A FILM: a video in, the music editor's cue sheet out — the first step of scoring to picture. Scene detection on EVERY frame, and it listens to the soundtrack (CPU, no credits): hard cuts frame-exact (dark, low-contrast footage included), fades, flashes and visual impacts; each shot's brightness, colour, warmth, contrast, motion and mood, with a keyframe JPEG per shot so you can SEE what it shows; where dialogue is (Silero VAD) and loud audio hits; then cues placed where the picture wants music and the dialogue lets it (1M1, 1M2 …: start/end SMPTE timecode, emotion, energy, tension arc, hit points ranked by strength, a suggested bpm that lands them, and tempo_map_input — pass it to doseedo_tempo_map as is). It sees light, movement and editing, not meaning: read the keyframes for what each scene is about. Input: video_key (doseedo_get_upload_url accepts mp4/mov/m4v/webm/mkv) or video_url (public https), ≤ 2 GB and ≤ 3 h. Optional start_timecode (the first frame's, e.g. 01:00:00:00; default the file's own), coverage (0.05–0.98, default 0.55: how much of the film gets music), reel (cue ids <reel>M<n>), keyframes (0–60). Async: job_id → doseedo_wait_task (~1 min for a 10-min 1080p reel). Next: doseedo_tempo_map per cue → write the notes → doseedo_render_score → doseedo_mix → doseedo_score_to_picture. Cancel: the plane has no stop for a running spotting pass — it runs to completion (credits spent), the job ends as canceled and its output is discarded. Only a job still queued at the plane is refunded by the plane's own failure refund.
{
"type": "object",
"properties": {
"reel": {
"type": "integer",
"maximum": 99,
"minimum": 1,
"description": "Reel number for the cue ids (default 1 → 1M1, 1M2 …)."
},
"coverage": {
"type": "number",
"maximum": 0.98,
"minimum": 0.05,
"description": "How much of the film gets music (default 0.55). Raise it for wall-to-wall scoring (a trailer, an animation), lower it for a dialogue drama."
},
"keyframes": {
"type": "integer",
"maximum": 60,
"minimum": 0,
"description": "How many shots get a keyframe JPEG (default 24; the longest shots first)."
},
"video_key": {
"type": "string",
"description": "R2 ingest key of the uploaded video (doseedo_get_upload_url with the file name, e.g. reel1.mp4; starts with \"ingest/\")."
},
"video_url": {
"type": "string",
"description": "https URL of the video, as an alternative to video_key (a public file URL, fetched directly; ≤ 2 GB)."
},
"cut_threshold": {
"type": "number",
"maximum": 0.9,
"minimum": 0.05,
"description": "Scene-change threshold at full contrast (default 0.3). Lower finds softer cuts, higher only the hardest."
},
"start_timecode": {
"type": "string",
"description": "SMPTE timecode of the first frame, HH:MM:SS:FF (\";\" before the frames = drop-frame at 29.97/59.94). Default: the file's embedded timecode, else 00:00:00:00."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_score_to_picture — Lay the score on the picture
SCORE TO PICTURE: the last step of scoring a film. Lays each mixed cue (and any sound effect) on the video at its SMPTE timecode, with dialogue ducking (the lines found on the video's own soundtrack by VAD, or the spans you pass; the music dips ahead of each line and comes back after it), normalises the program to a delivery loudness (web −16, streaming −14, broadcast/ebu −23, atsc −24 LUFS, or a number; true peak under the ceiling) and muxes it onto the picture untouched (no re-encode). Returns the scored video, the printmaster WAV and the music-and-effects stem, plus a report of what it MEASURED: where each track landed (and what was cut at the film's edges), how far the music sits under the lines, and the final loudness and true peak. CPU, no credits. tracks: [{audio_url (a doseedo_mix mix_url as returned, or any public https URL) | audio_key, start_timecode (in the film's timecode) | start_s, gain_db?, role?: music|dialogue|effects, duck?, name?}], ≤ 64. Keep the production audio (default) or drop it (production_audio:"drop"). A FILM THAT ALREADY HAS MUSIC: keeping its audio mixes the old music under yours — split it first (doseedo_split_soundtrack) and lay its dialogue and effects stems back (start_s 0, role dialogue / effects) with production_audio:"drop": the old music is gone, the lines are kept, and the duck reads the lines off the dialogue stem; lay the old music stem back too with duck:false to keep it (or a part of it). With dialogue tracks the delivery also returns the dialogue / music / effects stems. Up to 25 minutes of film per call (a reel). Async: job_id → doseedo_wait_task. Cancel: the plane has no stop for a running delivery — it runs to completion (credits spent), the job ends as canceled and its output is discarded. Only a job still queued at the plane is refunded by the plane's own failure refund.
{
"type": "object",
"required": [
"tracks"
],
"properties": {
"duck": {
"type": "object",
"properties": {
"sfx": {
"type": "boolean"
},
"enabled": {
"type": "boolean"
},
"depth_db": {
"type": "number",
"maximum": 40,
"minimum": 0
},
"attack_ms": {
"type": "number",
"maximum": 3000,
"minimum": 0
},
"release_ms": {
"type": "number",
"maximum": 5000,
"minimum": 0
}
},
"description": "Dialogue ducking (on by default): depth_db (default 10), attack_ms (250: how early before a line the music is down), release_ms (700), sfx (false: duck effects too), enabled.",
"additionalProperties": false
},
"tracks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"duck": {
"type": "boolean",
"description": "false = this music track is not ducked (the film's own music laid back from doseedo_split_soundtrack was mixed under its lines already). Default true."
},
"name": {
"type": "string",
"description": "A label for the report, e.g. 1M3."
},
"role": {
"enum": [
"music",
"dialogue",
"effects",
"sfx"
],
"type": "string",
"description": "music (default; ducked under the dialogue), dialogue (never ducked — the lines the rest ducks under; a split soundtrack's dialogue stem), effects / sfx (not ducked unless duck.sfx)."
},
"gain_db": {
"type": "number",
"maximum": 24,
"minimum": -60,
"description": "Level trim (default 0)."
},
"start_s": {
"type": "number",
"description": "Or where it starts in seconds from the first frame."
},
"audio_key": {
"type": "string",
"description": "An ingest key instead of audio_url."
},
"audio_url": {
"type": "string",
"description": "The cue's mixed audio (doseedo_mix mix_url as returned) or any public https URL."
},
"start_timecode": {
"type": "string",
"description": "Where it starts, in the film's timecode (HH:MM:SS:FF) — the cue sheet's start_timecode."
}
},
"additionalProperties": false
},
"maxItems": 64,
"minItems": 1,
"description": "What to lay on the film, in any order."
},
"dialogue": {
"type": "array",
"items": {
"type": "object",
"required": [
"start_s",
"end_s"
],
"properties": {
"end_s": {
"type": "number"
},
"start_s": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Dialogue spans [{start_s, end_s}] to duck under, instead of detecting them (use the cue sheet's dialogue, or your own)."
},
"loudness": {
"anyOf": [
{
"enum": [
"web",
"streaming",
"broadcast",
"ebu",
"atsc"
],
"type": "string"
},
{
"type": "number"
}
],
"description": "Delivery loudness: \"web\" (−16 LUFS, default), \"streaming\" (−14), \"broadcast\" / \"ebu\" (−23), \"atsc\" (−24), or a LUFS number (−36…−8)."
},
"video_key": {
"type": "string",
"description": "R2 ingest key of the video (the same upload doseedo_spot_video used)."
},
"video_url": {
"type": "string",
"description": "https URL of the video, as an alternative to video_key."
},
"start_timecode": {
"type": "string",
"description": "SMPTE timecode of the film's first frame (default: the file's own, else 00:00:00:00) — the clock the tracks' start_timecode is read on."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
},
"production_audio": {
"enum": [
"keep",
"drop"
],
"type": "string",
"description": "keep (default) mixes the video's own soundtrack — all of it, its music included — under the score; drop replaces it (lay a doseedo_split_soundtrack's dialogue + effects stems to keep the lines)."
},
"production_gain_db": {
"type": "number",
"maximum": 12,
"minimum": -60,
"description": "Trim on the production audio when kept (default 0)."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_separate_stems — Separate stems (vocal remover)
STEM SEPARATION and VOCAL REMOVER: split an uploaded mix into stems (vocals, drums, bass, guitar, piano, other — or orchestral/auto-detected instruments) to isolate vocals (the vocals stem is the acapella; the other stems are the karaoke backing), with optional per-stem MIDI transcription and DAW-session export. Async: returns a job_id — poll with doseedo_wait_task (~2 minutes). Result: stems{name: url}, midi{name: url}, drum_substems{kick, snare, …} (drum_split), vocals_lyrics / vocals_notes, session_tracks + session_tempo_bpm when session_id was given, models_effective (what the auto family gate actually ran), other_classification (what the "other" stem was heard as), guitar_split (outcome). Cancel: the plane has no stop for a running separation — it runs to completion (credits spent), the job ends as canceled and its output is discarded. Only a job still queued at the plane is refunded by the plane's own failure refund.
{
"type": "object",
"properties": {
"export": {
"enum": [
"logic",
"ableton"
],
"type": "string",
"description": "Optionally also build a DAW session from the stems."
},
"models": {
"enum": [
"6stem",
"auto",
"orchestra",
"detect"
],
"type": "string",
"description": "Separation model set. Default 6stem (vocals/drums/bass/guitar/piano/other); auto/orchestra/detect for wider instrument sets."
},
"audio_key": {
"type": "string",
"description": "R2 ingest key of an uploaded audio file (from doseedo_get_upload_url / POST /api/upload/r2/ingest-url; starts with \"ingest/\"). Provide this or audio_url."
},
"audio_url": {
"type": "string",
"description": "https URL of the audio, as an alternative to audio_key: a doseedo result URL exactly as a job returned it (a stem, a take, a bounce), or any public URL. The gateway fetches it (≤256 MB) into your account's ingest storage before the job starts. Pass audio_key OR audio_url."
},
"drum_split": {
"type": "boolean",
"description": "true = also split the drum stem into isolated kick / snare / hi-hat / toms / ride / crash (+ perc) sub-stems (result.drum_substems)."
},
"session_id": {
"type": "string",
"description": "Register the stems INTO this doseedo session (from doseedo_list_sessions) as audio tracks — result.session_tracks lists them. Needs parent_track_id."
},
"stems_only": {
"type": "boolean",
"description": "true = the stems and NOTHING derived from them (no MIDI, no lyrics, no latents) — the fastest, cheapest separation. Implies include_midi:false."
},
"instruments": {
"type": "string",
"description": "models=orchestra only: comma-separated extractor targets, e.g. \"saxophone,trumpet,trombone\". Available: drums, percussion, bass, double_bass, guitar, electric_guitar, acoustic_guitar, piano, organ, harp, brass, trumpet, trombone, french_horn, tuba, saxophone, clarinet, oboe, bassoon, flute, woodwind, strings, violin, viola, cello. Omit for the curated default set."
},
"guitar_split": {
"type": "string",
"description": "Deal the guitar stem into N players (same-instrument separation): \"2\"–\"4\", or \"auto\" (a one-vs-two probe decides; no split when it hears one). Outcome in result.guitar_split."
},
"include_midi": {
"type": "boolean",
"description": "Also transcribe each stem to MIDI (default true)."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
},
"parent_track_id": {
"type": "string",
"description": "With session_id: the t_… track the mix sits on; the stems are added as its children."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_split_soundtrack — Split a film's soundtrack (dialogue / music / effects)
SPLIT A FILM'S SOUNDTRACK (dialogue / music / effects — "DME" — separation): the film's own audio into three stems that sum back to it, plus a report of what it holds: whether there is music already, where it plays (spans in seconds) and how much of the film it covers, where the dialogue is (cleaner than VAD on the full mix: a song's singer stays in the music stem), each part's level, and how far the music sits under the lines. Use it before scoring a film that already has music (soundtrack.stems.music.present): to REPLACE that music, lay the dialogue and effects stems under your score with doseedo_score_to_picture (production_audio:"drop", tracks role "dialogue" / "effects"); to REMIX or RE-ORCHESTRATE it, the music stem goes to doseedo_separate_stems / doseedo_transcribe / doseedo_analyze_song; to KEEP it, score where the report shows no music. Input: video_key (the upload doseedo_spot_video read) or video_url; audio_key / audio_url for a soundtrack already on its own. One reel per call (≤ 30 min). The split is good, not perfect: the dialogue comes out clean, while some of the old music (its percussion most) reads as effects — about −10 dB of it stays in the dialogue + effects bed, which the new score masks. Async: job_id → doseedo_wait_task (about a third of the soundtrack's length: a 3-min scene ≈ 1 min, a 20-min reel ≈ 6 min). Cancel: the plane has no stop for a running split — it runs to completion (credits spent), the job ends as canceled and its output is discarded. Only a job still queued at the plane is refunded by the plane's own failure refund.
{
"type": "object",
"properties": {
"audio_key": {
"type": "string",
"description": "An ingest key of the soundtrack on its own (WAV/FLAC/MP3/M4A), instead of the film."
},
"audio_url": {
"type": "string",
"description": "https URL of the soundtrack on its own, instead of the film."
},
"video_key": {
"type": "string",
"description": "R2 ingest key of the film (the same upload doseedo_spot_video read; starts with \"ingest/\")."
},
"video_url": {
"type": "string",
"description": "https URL of the film, as an alternative to video_key (fetched through the URL up to 256 MB; upload a bigger film)."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_transcribe — Audio to MIDI (transcribe notes)
AUDIO TO MIDI transcription: a melody, a bass line or a part as notes (pitch, onset/offset seconds, velocity, confidence as JSON — not a MIDI file; for .mid files per stem use doseedo_separate_stems with transcription or doseedo_audio_to_session). Works from an uploaded audio_key or an audio_url — any public https URL, including a result URL from another doseedo job (a generate take, a stem) as it was returned. Async: returns a job_id — poll with doseedo_wait_task (usually ~15–60s). For the KEY / tempo / chords of a whole mix use doseedo_analyze_song instead. Cancel: the plane has no stop for a running transcription — it runs to completion (credits spent), the job ends as canceled and its output is discarded. Only a job still queued at the plane is refunded by the plane's own failure refund.
{
"type": "object",
"properties": {
"want": {
"enum": [
"notes",
"f0",
"notes,f0"
],
"type": "string",
"description": "What to return: \"notes\" (default), \"f0\" (the continuous pitch contour — frame-rate Hz values, for glides/vibrato/intonation), or both."
},
"chairs": {
"type": "string",
"description": "polyphony=\"section\": register codes per chair, as an alternative to roster."
},
"family": {
"type": "string",
"description": "Optional instrument family (e.g. \"brass\", \"reeds\", \"strings\") when the exact instrument is unknown."
},
"roster": {
"type": "string",
"description": "polyphony=\"section\": the chairs on the stem, e.g. \"trumpet,trumpet,trombone,tenor_sax\". Omit for the family default."
},
"backend": {
"type": "string",
"description": "Advanced: force a transcription backend. Omit — the server routes by instrument."
},
"strikes": {
"type": "boolean",
"description": "With tempo_bpm: also return the harmony_strikes attack grid."
},
"register": {
"type": "string",
"description": "Optional register hint for the instrument (e.g. \"soprano\", \"tenor\", \"bass\")."
},
"audio_key": {
"type": "string",
"description": "R2 ingest key of an uploaded audio file (from doseedo_get_upload_url / POST /api/upload/r2/ingest-url; starts with \"ingest/\"). Provide this or audio_url."
},
"audio_url": {
"type": "string",
"description": "https URL of the audio to transcribe (alternative to audio_key): any public URL, or a doseedo result URL exactly as a job returned it — no key needed."
},
"polyphony": {
"type": "string",
"description": "Optional: \"solo\" (monophonic line), \"poly\", or \"section\" (a horn section — see roster/chairs)."
},
"tempo_bpm": {
"type": "number",
"description": "Optional known tempo — enables beat-aligned note times."
},
"instrument": {
"type": "string",
"description": "Optional instrument hint, e.g. \"piano\", \"sax\", \"vocals\", \"bass\"."
},
"beats_per_bar": {
"type": "number",
"description": "With tempo_bpm: beats per bar for the beat-domain times (default 4)."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_analyze_song — Analyze a song
Key detection, BPM/tempo detection, song structure and chords — musical analysis of a recording in one call: key (e.g. "D minor"), bpm + per-beat tempo_map, meter / beats_per_bar, downbeats (seconds), sections (intro/verse/chorus… with times), chords (a progression on the beat grid), dynamics. USE THIS to learn the key and tempo of a reference before writing a part — never guess or ask the user for what the audio already says. Pass audio_key (an upload) or audio_url (a result URL from another job as returned, or any public https URL). Up to 10 minutes of audio is analyzed. Synchronous (~5–20 s): the result is in this response. No separation, so a dense mix's chords are a draft — for a chord chart from stems use doseedo_detect_chords on the separated stems. Cancel: not applicable — the result is returned in the submit response; the job is already finished.
{
"type": "object",
"properties": {
"audio_key": {
"type": "string",
"description": "R2 ingest key of an uploaded audio file (from doseedo_get_upload_url / POST /api/upload/r2/ingest-url; starts with \"ingest/\"). Provide this or audio_url."
},
"audio_url": {
"type": "string",
"description": "https URL of the audio (a doseedo result URL as returned, or any public URL). Alternative to audio_key."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_check_take — Check a take against its notes
MEASURE a take instead of guessing: give the audio (a render_midi take URL, any recording) and the notes it should play — notes[] + bpm (and tempo_map) or a midi_url — and get back how many written notes were heard at the right pitch and time (recall / precision / f1, octave errors, the first missed notes with their beats), the timing error in ms, loudness (integrated LUFS, peak dBFS, clipped share), any stretch where a note was written but nothing sounds, and a verdict (good / check / bad) with reasons in plain words. doseedo_render_midi results already carry this per take (takes[].check) when the part was given as notes. Method: an independent note transcriber (basic-pitch) — dense chords and very fast runs read less reliably; use it as a screen, and listen to anything marked check. Synchronous (~3–15 s), CPU, no credits. Cancel: not applicable — the result is returned in the submit response; the job is already finished.
{
"type": "object",
"properties": {
"bpm": {
"type": "number",
"description": "Tempo of the notes (or tempo_map)."
},
"notes": {
"type": "array",
"items": {
"type": "object",
"required": [
"pitch",
"start_beats",
"duration_beats"
],
"properties": {
"pitch": {
"type": "number"
},
"velocity": {
"type": "number"
},
"start_beats": {
"type": "number"
},
"duration_beats": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "The notes the take should play, in beats from bar 1 (the rows you sent doseedo_render_midi)."
},
"midi_url": {
"type": "string",
"description": "Alternative to notes: the part as a Standard MIDI File (≤ 2 MiB)."
},
"audio_key": {
"type": "string",
"description": "R2 ingest key of an uploaded audio file (from doseedo_get_upload_url / POST /api/upload/r2/ingest-url; starts with \"ingest/\"). Alternative to audio_url."
},
"audio_url": {
"type": "string",
"description": "The take: a doseedo result URL as returned, or any public https URL."
},
"tempo_map": {
"type": "array",
"items": {
"type": "object",
"required": [
"beat",
"bpm"
],
"properties": {
"bpm": {
"type": "number"
},
"beat": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Tempo changes [{beat, bpm}]."
},
"instrument": {
"type": "string",
"description": "The instrument (a drum/percussion name switches to onset-only matching)."
},
"time_signature": {
"type": "string",
"description": "Meter (default 4/4)."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
},
"onset_tolerance_ms": {
"type": "number",
"description": "How far a heard onset may be from the written one and still count (default 50)."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_analyze_midi — Analyze MIDI harmony
Check the HARMONY of notes before rendering or placing them: factor a MIDI progression into its sonorities (mode "midi", default — chord-detection-free: each segment of simultaneously sounding pitches reduced to an anchor pitch class + register-exact shape, covered with recurring shape cells) or into chord symbols (mode "chord": one estimated chord per ~2 beats + a corpus-grammar cell cover with a schedule). Input: notes[] (the rows you would give doseedo_render_midi / set_midi_notes) with bpm, or midi_url (a .mid ≤2 MiB: a doseedo result link such as a stem's MIDI, or a public URL). Synchronous (~2–10 s), CPU, no credits. Returns sonorities[] or chords[], cover, cells, compression — read chords[].chord / sonorities[].anchor to confirm the key and progression you intended. Cancel: not applicable — the result is returned in the submit response; the job is already finished.
{
"type": "object",
"properties": {
"bpm": {
"type": "number",
"description": "Tempo of the notes (needed with notes; default 120)."
},
"mode": {
"enum": [
"midi",
"chord"
],
"type": "string",
"description": "\"midi\" (default): sonority / shape factoring. \"chord\": chord symbols per segment + cell cover."
},
"notes": {
"type": "array",
"items": {
"type": "object",
"required": [
"pitch",
"start_beats",
"duration_beats"
],
"properties": {
"pitch": {
"type": "number"
},
"velocity": {
"type": "number"
},
"start_beats": {
"type": "number"
},
"duration_beats": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "The notes to analyze, in beats from bar 1 (same rows as doseedo_render_midi). Needs bpm."
},
"midi_url": {
"type": "string",
"description": "Alternative to notes: https URL of a Standard MIDI File (≤2 MiB)."
},
"min_seg_beats": {
"type": "number",
"description": "mode midi: shortest sonority segment in beats (default 0.25)."
},
"time_signature": {
"type": "string",
"description": "Meter of the notes, e.g. \"4/4\" (default)."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
},
"beats_per_segment": {
"type": "number",
"description": "mode chord: segment length in beats (0.25–8, default 2)."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}doseedo_instruments — Instrument catalog (the sound palette)
The instrument list — the sound palette: every instrument doseedo can PLAY YOUR NOTES on (doseedo_render_midi) — orchestral strings, brass and winds, guitars, basses, keys, drums and percussion, and World instruments (koto, sitar, banjo, pedal steel, tabla, congas…). Each entry gives the EXACT render call (`call`: instrument, plus timbre_preset where one is needed — a koto is the acoustic_guitar model with the koto timbre), its playable range in concert MIDI pitch, whether it plays chords, its presets (pizz, muted, sax registers…) and a demo render. No args → the whole catalog; query:"warm low brass" / family / pitches:[…] (instruments whose range holds them) / chords:true narrow it; id:"cello" → one instrument in full. Read-only, free, no key needed — read it before writing a part.
{
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "One instrument (id, alias or label, e.g. \"cello\", \"upright bass\", \"koto\") → its full entry: every preset with its own call and range, transposition, aliases, demo, page."
},
"query": {
"type": "string",
"description": "What the part needs, in words: an instrument (\"trumpet\"), a family (\"woodwinds\"), a technique (\"pizzicato\", \"muted\") or a register (\"low\", \"bright\"). Ranked best-first."
},
"chords": {
"type": "boolean",
"description": "true = only instruments one player can play chords on."
},
"family": {
"enum": [
"strings",
"brass",
"winds",
"piano",
"guitar",
"bass",
"drums",
"world",
"pitched_percussion",
"unpitched_percussion",
"synth"
],
"type": "string",
"description": "Only this family."
},
"pitches": {
"type": "array",
"items": {
"type": "number"
},
"description": "MIDI pitches the part uses (concert, 60 = C4) — only instruments whose range holds every one."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}doseedo_tempo_map — Tempo map from hit points
Scoring to picture: turn HIT POINTS (a cut, an impact, the title card — as seconds from the cue start or SMPTE timecodes) into a TEMPO MAP that lands each hit exactly on a downbeat (or a beat / an eighth — per hit with hits[].land), staying near your tempo and inside bpm_range. An AD or any cue that must hold ONE tempo: fixed_bpm: true (+ max_deviation_bpm, tolerance_ms) finds the tempo and the bar-1 offset (music_offset_s) landing the most hits, and says which ones it could not. Returns tempo_map [{beat, bpm}] to pass unchanged to doseedo_render_midi / doseedo_render_score / doseedo_session_from_stems, and hits[] with the beat, bar and beat-in-bar each hit lands on — write the accent, stinger or change there. Handles 23.976 / 24 / 25 / 29.97 (";" = drop-frame) / 30 / 50 / 59.94 / 60 fps timecode. Pure math: free, instant, no key needed.
{
"type": "object",
"required": [
"hits",
"bpm"
],
"properties": {
"bpm": {
"type": "number",
"description": "The cue's tempo (20–300) — the map stays as close to it as the hits allow."
},
"fps": {
"type": "number",
"description": "Frame rate of the timecodes: 23.976, 24, 25, 29.97, 30, 50, 59.94, 60."
},
"hits": {
"type": "array",
"items": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"land": {
"enum": [
"downbeat",
"beat",
"eighth"
],
"type": "string"
},
"label": {
"type": "string"
},
"time_s": {
"type": "number"
},
"timecode": {
"type": "string"
}
},
"additionalProperties": false
}
]
},
"description": "The moments the music must land on: [{time_s} (seconds from the cue start) or {timecode: \"01:00:12:08\"} (film timecode, with fps and start_timecode), label?, land?}] — land = THIS hit's landing (\"downbeat\", \"beat\" or \"eighth\"; default: the request's land), e.g. the big cuts on bar lines and a quick accent on an eighth. A bare number = {time_s}."
},
"land": {
"enum": [
"downbeat",
"beat",
"eighth"
],
"type": "string",
"description": "Land hits on bar lines (default), on any beat, or on any eighth — the default for every hit without its own land."
},
"start_s": {
"type": "number",
"description": "Alternative: the cue start in seconds of film time (informational when hits are time_s)."
},
"bpm_range": {
"type": "array",
"items": {
"type": "number"
},
"description": "Allowed tempo range [min, max] (default ±12 % of bpm)."
},
"fixed_bpm": {
"type": "boolean",
"description": "ONE tempo for the whole cue (an ad, a song-form cue): the solver picks the tempo (within max_deviation_bpm of bpm; default exactly bpm) and where bar 1 sits (music_offset_s, default within the first bar; offset_range_s) so the most hits land within tolerance_ms (default 40). Hits it cannot land come back landed:false with nearest_beat — never an error."
},
"tolerance_ms": {
"type": "number",
"description": "SOFT hits (0–250 ms): a hit within this of the grid counts as landed, and one the grid can't reach is reported (landed:false), never refused. Every hit then carries error_ms; hit_rate = landed / all."
},
"offset_range_s": {
"type": "array",
"items": {
"type": "number"
},
"description": "fixed_bpm: where bar 1 may sit on the cue, [min, max] seconds (default [0, one bar])."
},
"start_timecode": {
"type": "string",
"description": "Film timecode of the cue's first downbeat (bar 1); hit timecodes are measured from it."
},
"time_signature": {
"type": "string",
"description": "Meter (default 4/4)."
},
"max_deviation_bpm": {
"type": "number",
"description": "How far the tempo may move from bpm (both modes; in place of bpm_range). A variable map at 124 ±12 % can swing 11+ bpm between hits — 3 keeps it a steady groove."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}doseedo_get_upload_url — Get an audio upload URL
Get a presigned upload for your own audio file — or a SCORE (.mid / .midi / .musicxml / .xml / .mxl → a score_key for doseedo_render_score: send a big score as a file, not as notes in the call). Returns an upload_url (PUT the raw file bytes there, e.g. `curl -X PUT -H "Content-Type: <content_type>" --data-binary @song.wav "<upload_url>"`) and an audio_key to pass to doseedo_separate_stems / doseedo_transcribe / doseedo_cover_song / doseedo_audio_to_session, or to doseedo_add_audio_to_session. A FILM (mp4, mov, m4v, webm, mkv; ≤ 2 GB) uploads the same way: pass the key as video_key to doseedo_spot_video / doseedo_score_to_picture. Formats: WAV, AIFF, FLAC, MP3, M4A/AAC, Ogg/Opus, WebM — all accepted for processing on every plan. Storing audio IN A SESSION (doseedo_add_audio_to_session) keeps WAV/AIFF/FLAC lossless only on Pro+; below Pro+ lossless is not kept there, so send Opus (audio/ogg). Samples/regions for a session that are on this machine need NO upload: use load_quick_sampler_sample sample_path / attach_audio local_path / set_track_clips audio_ref.local_path and run place_local_files after the download.
{
"type": "object",
"required": [
"filename"
],
"properties": {
"filename": {
"type": "string",
"description": "File name including extension, e.g. \"song.wav\", \"film.mp4\", or \"cue.mid\" / \"cue.musicxml\" for a score."
},
"content_type": {
"type": "string",
"description": "MIME type; inferred from the extension when omitted (wav, aif/aiff, flac, mp3, m4a/aac, ogg/opus, webm; a film: mp4, mov, m4v, mkv). Required for any other extension."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}doseedo_check_task — Check a job
Check an async doseedo task once. Returns current status, and the result (file URLs / notes) when finished. A big result comes back as a brief (each row cut to its deciding fields): parts: ["<name>" or index, …] returns those rows of the job record IN FULL — a render_score part's every receipt, a mix part's strip, rides (every point) and loudness.
{
"type": "object",
"properties": {
"kind": {
"enum": [
"generate_music",
"generate_sound",
"cover_stem",
"fill_gap",
"render_midi",
"train_instrument",
"render_score",
"mix",
"session_from_stems",
"spot_video",
"score_to_picture",
"cover_song",
"separate_stems",
"split_soundtrack",
"transcribe",
"audio_to_session",
"convert_project",
"bounce_session",
"analyze_song",
"detect_chords",
"beat_grid",
"check_take",
"analyze_midi",
"generate",
"sound",
"coverstem",
"fillgap",
"render",
"train",
"score",
"stemsess",
"spot",
"picture",
"cover",
"separate",
"soundtrack",
"session",
"convert",
"bounce",
"analyze",
"chords",
"beats",
"check",
"harmony"
],
"type": "string",
"description": "Which job kind created the task — the registry name the submit reply carried (generate_music, generate_sound, cover_stem, fill_gap, render_midi, train_instrument, render_score, mix, session_from_stems, spot_video, score_to_picture, cover_song, separate_stems, split_soundtrack, transcribe, audio_to_session, convert_project, bounce_session, analyze_song, detect_chords, beat_grid, check_take, analyze_midi); the short codes (generate, sound, coverstem, fillgap, render, train, score, stemsess, spot, picture, cover, separate, soundtrack, session, convert, bounce, analyze, chords, beats, check, harmony) are accepted aliases."
},
"parts": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
},
"description": "Optional, on a finished job: the parts to return in full, by name (as the result names them) or index — e.g. [\"Oboes\", \"Timpani\"]."
},
"job_id": {
"type": "string",
"description": "Alternatively the job_id (job_…) from a submit tool or the jobs API — replaces task_id + kind."
},
"task_id": {
"type": "string",
"description": "The task_id returned by a submit tool."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}doseedo_wait_task — Wait for a job
Wait for an async doseedo job to finish: polls server-side for up to timeout_seconds (5–50; one call can never hold longer than 50 s), then returns the result or the latest status. If it returns still_running:true, call it again — a submit reply's eta_seconds says how long the whole job usually takes (transcribe ~15 s, a render 1–3 min, audio_to_session ~4 min), so a 3-minute job is three or four calls, not one. A finished job answers with its output, artifacts (pre-signed links) and note.
{
"type": "object",
"properties": {
"kind": {
"enum": [
"generate_music",
"generate_sound",
"cover_stem",
"fill_gap",
"render_midi",
"train_instrument",
"render_score",
"mix",
"session_from_stems",
"spot_video",
"score_to_picture",
"cover_song",
"separate_stems",
"split_soundtrack",
"transcribe",
"audio_to_session",
"convert_project",
"bounce_session",
"analyze_song",
"detect_chords",
"beat_grid",
"check_take",
"analyze_midi",
"generate",
"sound",
"coverstem",
"fillgap",
"render",
"train",
"score",
"stemsess",
"spot",
"picture",
"cover",
"separate",
"soundtrack",
"session",
"convert",
"bounce",
"analyze",
"chords",
"beats",
"check",
"harmony"
],
"type": "string",
"description": "Which job kind created the task — the registry name the submit reply carried (generate_music, generate_sound, cover_stem, fill_gap, render_midi, train_instrument, render_score, mix, session_from_stems, spot_video, score_to_picture, cover_song, separate_stems, split_soundtrack, transcribe, audio_to_session, convert_project, bounce_session, analyze_song, detect_chords, beat_grid, check_take, analyze_midi); the short codes (generate, sound, coverstem, fillgap, render, train, score, stemsess, spot, picture, cover, separate, soundtrack, session, convert, bounce, analyze, chords, beats, check, harmony) are accepted aliases."
},
"job_id": {
"type": "string",
"description": "Alternatively the job_id (job_…) from a submit tool or the jobs API — replaces task_id + kind."
},
"task_id": {
"type": "string",
"description": "The task_id returned by a submit tool."
},
"timeout_seconds": {
"type": "number",
"description": "Max seconds to wait in this call (5–50, default 45). Start with the submit reply's suggested_next_wait."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}doseedo_list_jobs — List jobs
List the jobs this account submitted (generate / render_midi / cover / stems / transcribe / session / convert / bounce / the analyses), newest first — to find an earlier result, check what is still running, or resume after a lost connection. Each row names its artifacts (e.g. ["vocals", "drums", "midi_piano"]); doseedo_check_task {job_id} returns the full result with fresh links. Read-only.
{
"type": "object",
"properties": {
"kind": {
"type": "string",
"description": "Only this job kind (registry name): generate_music, generate_sound, cover_stem, fill_gap, render_midi, train_instrument, render_score, mix, session_from_stems, spot_video, score_to_picture, cover_song, separate_stems, split_soundtrack, transcribe, audio_to_session, convert_project, bounce_session, analyze_song, detect_chords, beat_grid, check_take, analyze_midi. Short codes (generate, sound, coverstem, fillgap, render, train, score, stemsess, spot, picture, cover, separate, soundtrack, session, convert, bounce, analyze, chords, beats, check, harmony) are accepted aliases."
},
"limit": {
"type": "number",
"description": "How many (1–100, default 20)."
},
"before": {
"type": "string",
"description": "Page cursor: the next_cursor of a previous call."
},
"status": {
"enum": [
"queued",
"running",
"succeeded",
"failed",
"canceled"
],
"type": "string"
},
"session_id": {
"type": "string",
"description": "Only jobs whose input names this session — a bounce, stems registered into it, a render of one of its tracks (filtered within the fetched page)."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}doseedo_cancel_job — Cancel a job
Cancel a queued or running job. What that stops and refunds depends on the kind — generate_music / render_midi / cover_song: a render not yet on the GPU is stopped and its credits refunded; one already rendering finishes (credits spent), the job ends as canceled, output discarded. audio_to_session: cooperative — stops at the next stage boundary and refunds the build's sound-tool unit (a separation already run stays charged). bounce_session: a bounce still queued never renders (budget refunded); one mid-render has its result dropped. separate_stems / transcribe / convert_project: no plane-side stop — the work completes (credits spent), the job ends as canceled and its output is discarded. The synchronous analyses are already finished (409 already_terminal).
{
"type": "object",
"required": [
"job_id"
],
"properties": {
"job_id": {
"type": "string",
"description": "The job_id from a submit tool or doseedo_list_jobs."
}
},
"additionalProperties": false
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": true
}doseedo_account — Account and credits
Check the connected doseedo account: plan tier, the monthly credit pool (generation AND DAW conversions draw it), purchased extra-usage credits, and storage. Read-only — consumes nothing. Use it before starting expensive work to confirm there is budget.
{
"type": "object",
"properties": {},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}doseedo_quote — Price a job
Estimate what a job will cost in credits BEFORE submitting it, and whether the connected account can afford it right now. Spends nothing. Pass the job (generate_music, generate_sound, cover_stem, fill_gap, render_midi, train_instrument, cover_song, separate_stems, split_soundtrack, transcribe, audio_to_session, convert_project, bounce_session, spot_video, score_to_picture, analyze_song, detect_chords, beat_grid, analyze_midi, render_score, mix, session_from_stems, check_take) and the same args you would give the job tool (duration_seconds, models, instruments; for render_midi: notes + bpm / tempo_map or duration_seconds, voice_split / voices, takes — takes are free, voices cost one batch per ~6; for render_score: parts + bpm / tempo_map — planned exactly as the job plans it (lines, player rows, length), and `refused` says when the job would refuse it). The estimate follows the planes' own price table; the gate is authoritative and a refusal names the exact price.
{
"type": "object",
"required": [
"job"
],
"properties": {
"job": {
"enum": [
"generate_music",
"generate_sound",
"cover_stem",
"fill_gap",
"render_midi",
"train_instrument",
"cover_song",
"separate_stems",
"split_soundtrack",
"transcribe",
"audio_to_session",
"convert_project",
"bounce_session",
"spot_video",
"score_to_picture",
"analyze_song",
"detect_chords",
"beat_grid",
"analyze_midi",
"render_score",
"mix",
"session_from_stems",
"check_take"
],
"type": "string",
"description": "Which job to price (a doseedo_ tool name or recipe verb is accepted too)."
},
"args": {
"type": "object",
"description": "The arguments you intend to pass to the job tool; only the price-relevant ones matter.",
"additionalProperties": true
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}doseedo_recipes — Recipes (named pipelines)
The named pipelines people actually ask for — stems, session (mix → DAW project), cover, transcribe, generate, render-midi (your notes played by an instrument model), custom-instrument (train your own from a recording), timbre-transfer (your notes, a recording's tone), sound-design (SFX / foley / one-shots), analyze-song (key/tempo/sections/chords), convert, bounce, and the compose-part guide (a part in the session's key at its tempo: analyze → you write the MIDI → place or render it) — each with its inputs, the tool calls in order, outputs, a credit/time estimate and how to VERIFY success from the response. Call with no name for the index (pick by use_when), or with a name for the full recipe. Read-only.
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "A recipe name or alias, e.g. \"session\" / \"stems-to-session\". Omit to list all."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}Prompts
Not advertised
Resources
Not advertised
30-day availability
Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.
- Successful checks
- 1 of 1 (100%)
- Average latency
- 724 ms
- 95th percentile latency
- 724 ms
Maintenance history
Public check and source-refresh events. Editorial and ownership records remain private.
- · probe · passed · 724 ms · metadata changed · 24 tool(s)
Connect from your client
Each snippet registers the same endpoint; pick the client you use.
Claude Code
claude mcp add --transport http doseedo-film-score-mcp https://api.doseedo.com/mcp/filmCodex
codex mcp add doseedo-film-score-mcp --url https://api.doseedo.com/mcp/filmCursor
{
"mcpServers": {
"doseedo-film-score-mcp": {
"url": "https://api.doseedo.com/mcp/film"
}
}
}Cline
{
"mcpServers": {
"doseedo-film-score-mcp": {
"type": "streamableHttp",
"url": "https://api.doseedo.com/mcp/film",
"disabled": false
}
}
}VS Code
{
"servers": {
"doseedo-film-score-mcp": {
"type": "http",
"url": "https://api.doseedo.com/mcp/film"
}
}
}Gemini CLI
gemini mcp add --transport http doseedo-film-score-mcp https://api.doseedo.com/mcp/filmClaude Desktop
{
"mcpServers": {
"doseedo-film-score-mcp": {
"url": "https://api.doseedo.com/mcp/film"
}
}
}Windsurf
{
"mcpServers": {
"doseedo-film-score-mcp": {
"serverUrl": "https://api.doseedo.com/mcp/film"
}
}
}Let your agent find its tools
Find servers like Doseedo Film Score MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.
Other ai and machine learning servers
Do you run Doseedo Film Score MCP?
Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.