Agents & MCPTool reference

Voice, music and sound

Narration with word timings, spoken lines, the music bed, the beat grid and the mix. 40 tools.

On the main list

The tools a client sees when it connects.

get_timeline

Main listRead-only

The film timeline — every track on one clock

The whole film on one clock: scene windows, tempo, voice, music, cues, SFX, transitions, captions. detail adds bars, beats, words; sync {} checks picture vs sound (guide). Free.

InputTypeDescription
project_id requiredstringProject id.
chapter_idstringOnly this chapter (its window is the default detail range).
detailobjectExpand a range: bars, beats, words, elements, each cue.
syncobjectcheck_sync input (guide).

voice_project

Main listSpends credits

Voice the project

Voiceover and word timings for the project or one chapter; composes nothing. SPENDS CREDITS; dry_run prices it. Async.

InputTypeDescription
project_id requiredstringProject id.
chapter_idstringOnly this chapter.
dry_runbooleanPrice it, change nothing.
include_stalebooleanAlso re-voice blocks whose text changed since.

speak

Main listSpends credits

Speak lines

Speak ≤20 lines into the library, each with word timings. SPENDS CREDITS (a repeated line in the same voice is free).

InputTypeDescription
lines requiredarrayLines; each may override the voice.
voice_idstringDefault voice (list_voices).
clone_idstringDefault voice clone.
languagestringDefault language.

set_music

Main listSpends credits

Set the background music

Project music: track_id, url, generate {…} (SPENDS CREDITS), score {…} or Python code (free; guide "Score"). None = remove.

InputTypeDescription
project_id requiredstringProject id.
track_idstringMusic track id from list_catalog("music").
urlstringDirect audio URL, if you are not using a catalog track.
generateobject
scoreobject
codestring
dry_runboolean
rangeobject

Callable by name

Not listed on connect, to keep the list short. Call them directly by name, or find them with tools.

analyze_audio

Spends credits

Hear what is in a recording

Analyse an audio (or video) asset or a music track into data you can act on. DETECT: is there music, speech, singing, silence, and where (a timeline plus tags). For MUSIC: tempo and the TRACKED beats and bars (downbeats), drum hits (kick / snare / hat, with accent), bass and lead notes, the key, SECTIONS with their energy, and the SALIENT moments (drops, fills, entries). result.condensed is a short readable summary; result.features_url is the full event file the composition kernels read.

SOUND CAPTIONS (music, a few minutes after "ready"): every strike as a record you can move with — its level, attack, decay, pitch and glide, brightness — plus ratchets / rolls / flams as ONE gesture each (strokes, rate, speeding up or slowing) and the phrase landings where the stems converge (with the phrase length). They let motion hit like the sound: an element that rises over the strike's attack and settles over its decay, a stutter that accelerates with the ratchet, the world arriving on the landing. They are a score to choreograph against, not data to chart.

REACH FOR THIS WHEN WHERE OR HOW AUDIO IS USED DEPENDS ON WHAT IS IN IT: placing a track so its drop lands on a reveal, choosing which section of a song fits a scene, checking whether an upload is speech or music before using it, or checking music you generated (does it have a clear beat, the energy arc you asked for, vocals where there should be none). A project's own music is already analysed — get_authoring_context shows it; use this for anything else.

Source: media_asset_id (an uploaded audio/video) or track_id (a music track). Up to 20 minutes.

SPENDS CREDITS, priced by length (about 1 credit per minute); library tracks are free. The same source is never billed twice — a repeat returns the existing analysis (force: true re-runs and charges again). A failed analysis is refunded. A music track (an upload included) is answered from its OWN analysis, free — the same features set_music, get_authoring_context and the render use; a fresh upload answers not_ready until that analysis lands (about half a minute).

ASYNCHRONOUS: returns an analysis id at "queued" — poll get_audio_analysis (about 30 seconds per minute of audio).

InputTypeDescription
media_asset_idstringAn uploaded audio or video (from list_media or an upload). Exactly one of media_asset_id / track_id / url.
track_idstringA music track id (browse_music, generate_music, or the project's music).
urlstringThe mix.wav url of a rendered score laid on a project (score tool, place) — so check_sync can read its beats. Exactly one of media_asset_id / track_id / url.
forcebooleanRun again even if this source was already analysed (charged again).
productionbooleanAlso write the PRODUCTION SHEET (result.production): how the track is made — grid, arrangement, the drum kit's sound and density, the bass's sound design, the mix. Sound programs on this music read it (film.production, fit()) and get a scorecard against it. On a ready analysis it is added without a second charge.
depthstring"map" also writes the MUSIC MAP (result.map: status, url, summary): tempo, key, parts and the event score of how the track is built, from GPU stems when the track has them, else a CPU split (summary.stems says which). On a ready analysis it is added without a second charge.

audio_strip

See a sound (waveform + spectrogram)

A picture of a sound, since you cannot hear it: the waveform over a log-frequency spectrogram, a seconds ruler and your marks drawn across both (words, lines, beats, cues), plus numbers: lufs (loudness), peak_db, bands {low <250 Hz, mid, high >4 kHz} in dB, and silences [[from, to]] of 0.3 s or more. Use it to check a take before placing it (did the voice clip, trail off, leave a long gap?), a music bed (where the drop is, whether it is muddy), or a mix against its cues. url = a file on our storage (a speak or compose_dialogue take, a generate_music track, an upload; "$voice.url" in a chain) or asset_id. from/to cut a window (at most 600 s). Free; seconds; the PNG is named by content, so asking again is free.

InputTypeDescription
urlstringThe sound: a file on our storage (e.g. "$voice.url" in a chain).
asset_idstringOr a library audio (or video) asset id.
fromnumberWindow start, seconds (default 0).
tonumberWindow end, seconds (default the end; at most 600 s after from).
widthnumberPicture width, 400–2400 px (default 1600).
marksarrayUp to 120 marks on the sound's own clock: {t, label?, kind?: word|line|beat|cue}.

audition_voices

Hear voices speak a line

Synthesise the SAME short line with up to 8 voices and get a playable audioUrl for each — the way to compare a shortlist, hear a voice that has no preview yet (new library voices, cheap Replicate models like Chatterbox / Kokoro), or hear a clone speak. Each voice is {voice_id} (a tts_preset id from list_voices) or {clone_id} (from clone_voice). text ≤400 characters; omit it for a natural sample in language (or in each voice's own language). The clip is the voice exactly as narration would render it. Free, rate limited per account. A voice that fails comes back with an error beside the others. To hear an EXCHANGE instead, pass dialogue {lines:[{speaker,text}], cast:{speaker:{voice_id}}} (no voices): each line is spoken by its speaker and the lines come back joined as ONE audioUrl, with each line's start/end on it.

InputTypeDescription
voicesarrayUp to 8 voices; each has exactly one of voice_id / clone_id.
textstringThe line to speak (≤400 characters). Omit for a default sample.
languagestringLanguage to speak, e.g. 'fr' or 'en-gb'. Omit to use each voice's own.
askstringThe question shown with the clips.
dialogueobject

backfill_voice_analysis

Measure the silences in a project's existing voice-over

Voice-overs made recently carry a silence map (where each word boundary really is quiet), so cut_words and set_pauses land between words instead of biting them. Voice-overs made before that have none. This measures them from the stored audio and fills it in: no vendor call, no credits, nothing re-voiced, safe to run again. Returns per chapter how many blocks were analysed, skipped (already done or too short) or failed. Run it once on an older project before cutting words or placing pauses in it. Free.

InputTypeDescription
project_id requiredstringProject id.

browse_music

Read-only

Browse and choose a bed

The beds this account has GENERATED, side by side and playable — and selectable: the user picks one and can vary it or put it on a project without you relaying ids back and forth.

Use it whenever there is a choice to make. After generating two or three takes, call this rather than describing them: music is not judgeable from a description, and the point of making several is hearing them next to each other.

Different from list_catalog("music"), which lists the whole licensed library to pick from. This answers "what have I made?" and carries the grid (bpm, bars, key), the lineage (which takes are variations of which, and how far they travelled) and which bed is on the project — the things you actually compare takes by.

Pass project_id to mark the bed already in use and to offer attaching straight from the list. It does NOT filter to that project: a bed is reusable, and hiding the rest would hide most of the choice.

The selection is ORDERED. Picking one bed offers varying it or putting it on the project; picking SEVERAL, in the order they should play, offers making them the score — sections laid end to end with the last looping to the end of the video. That is how a palette becomes a piece: generate a motif, vary it a few ways, then choose the running order.

InputTypeDescription
querystringFilter by name, case-insensitive substring.
project_idstringMark which bed this project uses, and enable "use in this project".
include_librarybooleanAlso include licensed library tracks. Default false — generated beds only.
include_pendingbooleanAlso list your beds still generating or that FAILED (state + failure reason; a failed bed is refunded). Use it to check a commission that has not landed.
limitnumberMax rows, default 40.
track_idsarrayA shortlist to show instead of every bed, best first — when you are suggesting.
promptstringThe question shown above the picker, when you are asking the user to choose.

clone_voice

Clone a voice from a recording

Make a narration voice from a recording of ONE person speaking — a library asset (media_id, from list_media) or a url to import (upload_url). The recording is checked first: at least 10s of speech, mostly speech (not music or silence), not too noisy or clipped. The best 10–30s becomes the reference and is transcribed. ASYNCHRONOUS: returns an id at status "processing"; poll get_voice_clone. When ready it gives a tts_preset_id for set_project_voice; when refused it gives the reason in words for the user ("found 2.1s of speech, need 10s").

CONSENT IS REQUIRED: pass consent.attested = true ONLY after the user has confirmed the voice is theirs or that the person recorded agreed to be cloned. Ask; never assume. Never clone a public figure. May be disabled on this deployment (feature_disabled) — say so plainly if it is.

InputTypeDescription
media_idstringLibrary audio/video asset id (from list_media). Exactly one of media_id / upload_url.
upload_urlstringAn http(s) url of a recording to import, then clone.
name requiredstringWhat the voice is called in pickers, e.g. "Anna (my voice)".
languagestringLanguage of the recording, e.g. 'en' or 'fr-fr'. Omit to detect it from the audio.
model"fish" | "chatterbox"What the clone is made on: 'fish' (default — Fish S2.1 Pro, premium) or 'chatterbox' (Resemble Chatterbox on Replicate — standard tier, much cheaper; English via Turbo, other languages via Multilingual).
consent requiredobject

cut_words

Cut words out of the narration without re-voicing it

Text-based editing of a VOICED script block: strike a phrase (or a character range) out of its voice-over. Nothing is regenerated — the words stay in the script, struck through, and their audio is skipped in the editor preview, the export and the captions. A range that clips a word takes the whole word. Cut edges are placed in the silence between words, so no neighbouring word is bitten. action:"restore" puts struck words back (no range = all). Cuts belong to the current voice take: regenerating the block's voice drops them. The block must already have its voice-over (get_storyboard shows block ids). Free.

InputTypeDescription
chapter_id requiredstringChapter id.
block_id requiredstringScript block id.
actionstring"cut" (default) or "restore".
phrasestringExact phrase to act on — first occurrence, case-insensitive.
char_fromnumberStart of a character range in the block text (instead of phrase).
char_tonumberEnd of the character range (exclusive).

find_sfx

Read-only

Find a sound effect by meaning and length

Find a sound effect for a sound you can describe: words plus how long it should last. Searches the house library first (cueable now: usable_in_render true, src on our storage), then Openverse (commercial licences only, CC0 and CC-BY). Each hit carries credit (CC-BY needs it on screen or in the credits), license, duration_ms, tags. Openverse hits are NOT cueable until cached (usable_in_render false). want_sec ranks the closest length first; position and behaviour are passed through for the fit step. Free.

InputTypeDescription
q requiredstringWhat the sound is, e.g. "riser" or "paper rustle".
want_secnumberHow long the sound should last, in seconds. Ranks the closest length first.
positionstringWhere it sits, e.g. "scene start" or "on the cut". Passed through.
behaviourstringHow it moves, e.g. "rising" or "decaying". Passed through.
limitnumberMax hits, 1–50. Default 12.

fork_caption_formula

Fork a caption formula

Take a caption style that already EXISTS, change part of it, keep the result as your own. Free. The companion to save_caption_formula: that one writes a rule from nothing, which means knowing the whole vocabulary before you can start; this one starts from something that already works, which is how anyone actually authors.

from is any style id you can read — list_formulas(slot:"caption") shows each one's full spec, so read it, decide what to change, and send only that.

patch is DEEP-merged over the source: {"paint":{"color":"#F0E2C0"}} recolours the line and leaves the source's face and tracking alone. An explicit null REMOVES a key — {"field":null} is how you say "same look, no ring at all", which a merge could not otherwise express.

Mode, position and size are inherited from the source unless you override them: a stacked column that silently reverted to a centred bottom band would not be the thing you forked. The result is validated exactly as authoring from scratch is — composed and linted the way the renderer will — which matters MORE here, because a patch that misnames an ingredient would otherwise inherit a perfectly valid source and save quietly, ignoring the one thing you changed.

Only formula-authored styles can be forked. A catalog look, a v2 preset, or a hand-written template carrying its own markup will say so rather than accept a patch that would do nothing.

InputTypeDescription
from requiredstringThe style id to start from — anything published, or one of your own.
namestringName for the fork. Defaults to "<source> (copy)".
patchobjectDeep-merged over the source formula: recipe, succession[], accent, entry, life, exit, field, slot, paint, fonts[]. null at a key removes it.
modestringOverride the source mode: karaoke | chunk | hero.
default_positionstringOverride the source position: top | middle | bottom.
default_font_sizenumberOverride the source default size.

generate_music

Spends credits

Write a piece of music

Commission an instrumental bed that belongs to NO project yet — it lands in the music library and you attach it later. SPENDS CREDITS. Asynchronous: the bed lands a few MINUTES later, so do not wait on the call — poll browse_music with include_pending (a failed bed shows its reason and is refunded).

Use this to AUDITION. Choosing music means hearing a couple of options and picking one, and set_music binds a bed to a project the moment it is made — so generate two or three here, play them, then attach the one the user likes with set_music (existing project) or music_track_id on create_project (new one).

To iterate rather than re-roll, pass from_track_id: a VARIATION of a bed the user already liked — same room and instrumentation, a different take. That is what "more like that one, but calmer" means. A variation inherits the source's length, so duration_sec is ignored.

MODELS: model picks the maker (list_catalog("models"), modality music; each lists its price and limits). Omit it for ACE-Step, 2 credits, 30-300s. A listed model is priced on its own: per second of length, or flat per call. None of them follows a stated note sequence; mood, tempo and key are what steer them (for exact notes write a score and render it). loop_bars asks for a loop of exactly that many bars (a hold scene's unit); finish decides the ending: loop = cut to whole bars with the tail folded over the head so repeating it has no dip, piece = trim a silent tail only, none = as the model returned it.

Describe INSTRUMENTATION, mood and production in steer — never a tempo or key, which are separate fields; naming them in prose makes the model fight its own conditioning. cue sets density: hush is nearly still, drive is insistent. Beds are snapped to a whole number of bars so they loop cleanly under a video.

InputTypeDescription
steerstringInstrumentation, mood, production — e.g. "warm rhodes, brushed kit, late-night room". NOT tempo or key.
bpmnumberTempo, 40-220. Defaults to the project tempo (120 when the project has none). Tempo and length constrain each other; an impossible pair is rejected before credits are spent.
meternumberBeats per bar. Defaults to 4.
key_scalestringe.g. "A minor". Optional.
duration_secnumberDesired length. ACE-Step: 30-300, snapped UP to the nearest whole bar the provider can hit exactly (its 0.04s grid) — at 100 BPM 4/4, 43.2 stays 43.2 (18 bars). A listed model has its own window (shorter is possible). Omit it and a loop takes the shortest legal bar-exact phrase (ACE-Step has a 30s floor, so a "4-bar" loop at 100 BPM comes back at 16 bars). Ignored when from_track_id is set.
modelstringThe music model, from list_catalog("models") (modality music). Omit for ACE-Step.
loop_barsnumberA loop of exactly this many bars, e.g. 4. ACE-Step cannot go under 30s; a listed model can.
finish"loop" | "piece" | "none"How the audio is finished: loop (whole bars, seam joins itself), piece (trim a silent tail), none. Default: the model's own habit; ACE-Step none.
cue"hush" | "develop" | "drive" | "lift" | "resolve"Density and articulation.
presence"bed" | "present" | "feature"How far forward the music sits. bed = stays under speech (default for hush/develop/resolve); present = a motif is allowed, still carved for speech (default for drive/lift); feature = no retreat at all — ONLY where no narration plays over it, such as an opening, a culmination or a tail. feature under continuous speech sounds worse than anything else here.
accentsstringSpecific instrumentation moments — "a single struck bell on the downbeat", "low brass swell into the last bar". The granular control a mood word cannot express.
seednumberReproducibility — the same inputs and seed give the same bed.
namestringName for the track in the library. Defaults to one derived from the steer.
from_track_idstringVary THIS bed instead of generating from nothing — id of a track that already has audio.
strengthnumberWith from_track_id: how far to travel from it, 0..1. Higher = less like the original. Default is the provider's.

get_audio_analysis

Read-only

Read an audio analysis

The state of an analysis started with analyze_audio: "queued"/"processing" (poll again in ~15 seconds), "ready" (result: detect, tempo, key, sections[], salient[], counts per event kind, condensed), or "failed" (error says why; the charge was refunded). Pass events to get the event lists themselves, windowed with t0/t1 in seconds: beat.tracked, downbeat, hit.kick, hit.snare, hit.hat, note.bass, note.lead, section, salient, key, music, speech, vocals, word, tag, and the sound captions: strike (t, db, lv 0..1, a attack s, dc decay s, hz, gl, br, nz, src), artic.ratchet / artic.roll / artic.flam (n, rate, accel ms per stroke — negative is speeding up, ioi, ramp), phrase (bar, len in bars, why). Free.

InputTypeDescription
analysis_id requiredstringThe id analyze_audio returned.
eventsarrayEvent kinds to include, e.g. ["downbeat","hit.snare"]. Up to 2000 per kind.
t0numberWindow start in seconds (default: the start).
t1numberWindow end in seconds (default: the end).

get_captions

Read-only

Get caption settings

Read the project's global caption default — on/off, style id, colour scheme, alignment, size, AND the stored fine-tune (style) as authored. Read before you write: set_captions DEEP-merges, so patching blind either duplicates a field or keeps one you meant to drop. A scene can override all of it — read that with get_scene (caption_style_id / caption_style).

InputTypeDescription
project_id requiredstringProject id.

get_voice_clone

Read-only

Check a voice clone

The state of a clone started with clone_voice: "processing" (poll again in a few seconds), "ready" (tts_preset_id — apply it with set_project_voice; reference_url is their own recording, not a synthesis; audition_url is the CLONE speaking a sample line — play that), or "rejected" (reject_reason — tell the user what to record instead). Free.

InputTypeDescription
clone_id requiredstringThe id clone_voice returned.

get_voice_performance

Read-only

Check a take-to-voice run

The state of a run started with perform_voice: queued / listening / writing / speaking (poll again in a few seconds), "ready" (url of the spoken line, asset_id, text_with_tags — edit it and call speak to redo the line; heard = what the listener reported per stretch of the take) or "failed" (error; the credits were refunded). Calling it after the tags are written also speaks the line. Free to call.

InputTypeDescription
performance_id requiredstringThe id perform_voice returned.

groove_library

Browse, read, save and delete loops in the loop library

The LOOP LIBRARY: every groove this account can drop into a project — curated loops (built in, read-only) and the account's own saved loops. action "list" browses (q searches id, name, note, tags and voices; patterns:true returns each pattern to read and learn from); "get" reads one with its pattern; "save" writes one of yours (a pattern, or from_project + pattern_id to keep a groove you made in a project); "delete" removes one of yours (projects that copied it keep their copy). To USE a loop, set_groove add_loops copies it into the project, then default_id / scenes pick it. Patterns carry no tempo or key — they play at the project's. Free.

InputTypeDescription
action"list" | "get" | "save" | "delete"Default "list".
idstringLoop id (get / save / delete): lowercase letters, digits, - or _.
qstringlist: search words.
source"curated" | "mine"list: only one half.
patternsbooleanlist: include every pattern.
namestringsave: display name.
notestringsave: what it sounds like and when to use it.
tagsarraysave: tags, e.g. "half-time", "tense".
patternobjectsave: the pattern JSON (the set_groove grammar).
from_projectobject

list_voices

Read-only

List the voices for a project

The voices available for this project's narration: the one currently set and the library (include_recent adds the ones this workspace uses). Short rows with caps (tags, direction, dialogue, clone); page with offset, drop heard voices with exclude. Each has a preview_url to HEAR, not an adjective. Free. Narrow with language / provider / gender / age_group / query; compact:false adds supported_languages and preview languages. To hear voices say the SAME line — or a voice with no preview — use audition_voices.

InputTypeDescription
project_idstringProject id. Optional: without one you get the workspace-used and library buckets (no "currently set"), so you can pick a narrator before create_project.
languagestringLocale prefix — 'en' matches en-US and en-GB — also matching multilingual voices that list it.
providerstringOnly this TTS provider, e.g. 'replicate' (cheap Chatterbox / Kokoro / Qwen / Inworld on Replicate), 'inworld', 'fishaudio', 'qwen', 'gemini'.
tierstring'standard' or 'premium'.
clonesbooleanOnly the account's own cloned voices.
genderstringFilter by gender.
age_groupstringFilter by age group.
querystringSubstring over name, description and category.
limitnumberLibrary rows (default 24, max 60).
offsetnumberRows to skip; use next_offset.
excludestringComma-separated voice ids to leave out.
supportsstringComma-separated, all required: tags, direction, dialogue, clone.
include_recentbooleanAdd the workspace-used voices (default false).
compactbooleanShort rows (default true).

perform_voice

Take to voice: your recorded performance, spoken in another voice

Turn a RECORDED TAKE into a line spoken by a chosen voice with the take's pacing, pauses, sighs and mood. The take is any audio asset (take_media_id, from list_media or create_upload; up to 60 s) — no voice clone is needed. Steps: a listening model describes the take (words and timings, sounds, mood), an LLM writes the same words with Drama 3 expression tags and "..." pauses, then the voice (voice_id from list_voices, or your clone_id) speaks it. ASYNCHRONOUS: returns an id; poll get_voice_performance (a cold start can take a couple of minutes; the poll that finds the tags written speaks the line). dry_run:true prices it without spending.

WHAT SURVIVES (measured): pacing, pauses, sighs and mood. NOT singing and NOT a real laugh: tags cannot sing; say so if the take is mostly singing. mode "convert" (keeping the performance itself) is not available yet. SPENDS CREDITS: listening per second of take, plus the voice at the speak rate; refunded if it fails. Confirm with the user before a real run.

InputTypeDescription
take_media_id requiredstringLibrary audio/video asset id of the recorded take (list_media).
voice_idstringA voice from list_voices (stock Drama 3 voices carry the tags best). Exactly one of voice_id / clone_id.
clone_idstringOne of your own voice clones (clone_voice).
mode"tags"'tags' (default): the take's delivery written as expression tags.
line_hintstringWhat you are after, in a few words, e.g. "sad ending". Passed to the tag writer.
project_idstringThe project the line belongs to.
dry_runbooleanQuote only: credits for the listening and an estimate for the voice. Spends nothing.

revoice

Spends credits

Re-voice the narration

Speak the narration again, optionally in a DIFFERENT voice: one call for a project, a chapter or one block. set_project_voice alone changes only the setting (what is already voiced keeps the old voice); this changes it AND re-synthesises every spoken block in scope, with word timings. Omit voice_id to re-take with the current voice (a re-roll of a block you did not like). SPENDS CREDITS per character: ALWAYS dry_run:true first. It prices the candidate voice without saving it and reports plan (blocks, characters) and warnings: pauses stay (they are text positions); cut_words strikes do not carry to the new take (re-apply them); scenes you authored are timed to the OLD words (check them against the new take). Returns voiceover_generations to poll with get_project_status. Compare voices first with audition_voices (free).

InputTypeDescription
project_id requiredstringProject id.
voice_idstringtts_preset id to switch to (list_voices). Omit to re-take with the current voice.
scope"project" | "chapter" | "block"How much to re-voice. Default "project".
chapter_idstringRequired when scope is "chapter".
block_idstringRequired when scope is "block".
dry_runbooleanTrue = price it and report the plan; changes nothing (the voice is NOT saved). Do this first.

save_caption_formula

Author a caption formula

AUTHOR a caption look as a FORMULA and keep it as a reusable style you own. Free, and the companion to save_caption_style: that one CAPTURES the look a project is already wearing, this one WRITES a new rule from nothing.

A formula says how words MOVE, which the style layer cannot express at all: recipe one named look for the whole line — "velocity". succession a list; word k takes step k mod N. Two steps alternate, five cycle. Each step may carry its own paint, so every other word can switch face AND colour. accent a step for the EMPHASISED word alone, over whatever the line is doing — "velocity everywhere, bounce on the accent word". entry/life/exit pick the three axes yourself instead of naming a recipe. Each is an id or {spec, params}. slot WHERE the line sits: band (centred, y%), alternate (corner to corner — first half high left, its answer low right), stack (one word per line, a column), drift (each line a step lower). This is the only route to horizontal placement; the style position block cannot reach it. field a treatment wrapping each word. paint — colour, font, size, weight, italic, tracking — line-wide or per step. A #hex is literal; a bare name is a theme role.

Ingredient ids come from the library; a recipe carries its own signature colour and face, so naming one is usually enough. The formula is validated by COMPOSING and LINTING it the way the renderer will: an unknown ingredient or a broken template law is rejected with the reason, rather than quietly rendering as a plain caption. Always private; the id appears in list_catalog("caption-styles") with user_authored: true and is what you pass as set_captions style_id.

InputTypeDescription
name requiredstringWhat to call it — how you will recognise it in a picker later.
formula requiredobjectThe formula: any of recipe, succession[], accent, entry, life, exit, field, slot, paint, fonts[]. id and name are set for you.
modestringkaraoke (per-word timings), chunk (whole line) or hero. Default karaoke.
default_positionstringtop | middle | bottom — where a project starts it. Default bottom.
default_font_sizenumberDefault caption size. Default 60.

save_caption_style

Save the caption look as a reusable style

Name the project's CURRENT caption look and keep it as a reusable style you own. Free. This is what turns authoring into a preset: set_captions writes a look onto one project, this names it, and from then on any surface reaches it by id — another project, the editor picker, or a later agent asked to make something "like that one". What is saved is self-contained (the base look merged with the fine-tune), so it reproduces without the project it came from. Always private; it shows up in list_catalog("caption-styles") with user_authored: true, and its id is what you pass back as set_captions style_id.

InputTypeDescription
project_id requiredstringProject whose current caption look should be saved.
name requiredstringWhat to call it — how you will recognise it in a picker later.

search_sfx

Read-only

Find a sound effect in the library

Search the SOUND EFFECT LIBRARY by words (every word must match the slug, name, category or tags) and/or category. Each hit carries src (on our storage), duration_ms, tags and default_volume. Cue one from a composition with data-tc-sfx-src="<src>" on the element whose motion makes the sound, or {"t": …, "src": "<src>"} in the x-tc-sfx tag; a sound you made yourself goes up with create_upload(kind:"sfx"). Free.

InputTypeDescription
qstringWords to match, e.g. "door slam" or "whoosh".
categorystringOne category, exact.
limitnumberMax hits, 1–100. Default 30.

set_audio_fx

Put an audio effect on words of the narration

Apply an audio effect to specific words of a VOICED script block — "reverb on that word", a pitch drop on a phrase, a telephone band (highpass+lowpass), a level change, a pan. Nothing is re-voiced and nothing moves in time: captions and scene timing stay put, and reverb/echo tails ring over what follows. Address the words with words (exact text, first occurrence, case-insensitive; a partial word takes the whole word) or a char range. Effects and params (missing = default, out of range = clamped): reverb {mix 0..1 (0.35), decayMs 100..6000 (1500), preDelayMs 0..200 (12), damping Hz (6000)}; echo {delayMs 20..2000 (260), feedback 0..0.9 (0.4), mix 0..1 (0.5)}; pitch {semitones -12..12}; lowpass {frequency Hz (1200), q}; highpass {frequency Hz (400), q}; gain {db -40..12}; pan {pan -1..1}. tail_ms overrides how long reverb/echo ring. Setting the same effect again on the same words replaces it. clear:true removes effects on the words (all words when none given; only kind fx when given). Effects belong to the current voice take — regenerating the block's voice drops them. Heard in the editor preview and the export (re-render or re-share to hear it). The same effects (plus eq, width, gain_db) go on a whole sound effect (data-tc-sfx-fx in the scene HTML) or a music/sfx clip (apply_changes edit_clip/add_clip fx), baked on the server. Free.

InputTypeDescription
chapter_id requiredstringChapter id.
block_id requiredstringScript block id.
wordsstringExact words to affect — first occurrence, case-insensitive.
char_fromnumberStart of a character range in the block text (instead of words).
char_tonumberEnd of the character range (exclusive).
fx"reverb" | "echo" | "pitch" | "lowpass" | "highpass" | "gain" | "pan"The effect. Required unless clear:true.
paramsobjectNumeric effect params, e.g. {"mix":0.5,"decayMs":2500}.
tail_msnumberReverb/echo only: how long the tail rings past the words (ms).
clearbooleanRemove effects instead of adding one.

set_captions

Set caption settings

Turn captions on or off, pick their look, and AUTHOR the look itself. Free, and unlike a theme change this needs no regeneration — captions are a render overlay, so the change lands on the next render. Style ids come from list_catalog("caption-styles").

style is where authoring happens: a CaptionStyle partial, DEEP-merged over what is stored (pass null to clear the whole fine-tune). Every geometric value is PROPORTIONAL, so one style renders correctly at 16:9, 9:16, 1:1 and 4:5. The blocks: position { anchorX left|center|right, anchorY top|middle|bottom, offsetXPct, offsetYPct, safeAreaPct } — offsets are % of the frame axis. layout { widthPct, textAlign start|center|end, maxLines, maxWords }. font { family, weight, italic, transform, sizePct, letterSpacingEm, lineHeight, color } — sizePct is % of frame WIDTH and acts as a MAX the renderer fits down from. About 3 reads well at 1920×1080. THREE TEXT ROLES, each the same vocabulary (color, background, fontFamily, weight, italic, transform, sizeEm, scale, letterSpacingEm, outline, shadow, radiusPct, padXPct), inheriting field-by-field from font: font is every word, activeWord is the word being spoken, keywordEmphasis is the words picked out as the point. Only the fields you set are stored, and an explicitly set field OUTRANKS the look own paint — so a role is how you make a stock look yours. shadow / outline / glow / background — optional decoration; present means on. Colours and families may be a theme token instead of a literal: { token: "color-role.accent" } or { token: "text-role.display" }, which re-colours with the theme. A literal is an explicit opt-out of theming. Per-SCENE authoring is the same object on update_scene (caption_style).

InputTypeDescription
project_id requiredstringProject id.
enabledbooleanCaptions on or off.
style_idstringCaption style id from list_catalog("caption-styles").
color_scheme"default" | "theme"'theme' paints the caption from the project theme's palette; 'default' keeps the style's own colours.
alignmentstringe.g. "bottom", "center".
font_sizenumberCaption font size.
styleobjectA CaptionStyle partial, deep-merged over the stored fine-tune. See the description for the blocks and the three text roles. Read get_captions first.
expected_versionintegerThe project's edit_version (from get_project or the last project-level write's response). Optional: when sent, the write is refused with a conflict (current_version, last_writer) if anyone changed the project settings since — nothing is written. Omit to write unconditionally.

set_conductor

Read or edit the conductor: tempo map with ramps, signatures, markers, arrangement

The project's musical grid as a CONDUCTOR (a Logic-style tempo map): tempo points with curved ramps, signature changes, key changes, markers and an arrangement lane, anchored in MUSICAL position (q = quarter-notes from bar 1, or bar + beat) so an edit at bar 5 does not slide bar 9. Only project_id = READ (conductor + edit_version). With ops: id-addressed edits applied in order, all or nothing. dry_run:true writes nothing and returns the diff in seconds (bars that move, music-span scenes, sound cues). Sound cues and music loops follow a grid change like set_tempo; scene windows are NOT re-fitted (reported only). Pass expected_version. Free. Ops and shapes: guide "The conductor".

InputTypeDescription
project_id requiredstringProject id.
opsarrayEach {op, ...}: add_point{q|bar,beat, bpm?, curve?(-1..1), hold?} move_point{id, q|bar,beat?, bpm?} remove_point{id} set_curve{id, curve?|null, hold?} set_base_tempo{bpm} set_meter{beats,unit} set_origin{origin_sec} set_key{key_scale, q|bar?, id?} remove_key{id} add_signature{bar>=2, beats, unit} edit_signature{id,...} remove_signature{id} add_marker{q|bar,beat, label, color?} edit_marker{id,...} remove_marker{id} add_arrangement{start_bar,end_bar,label,color?,hold?{on,exit_bar?,exits?:[{on,bar}],quantize?:beat|bar,interactive?},then_bar?} edit_arrangement{id,...,hold?|null,then_bar?|null} remove_arrangement{id} set_warp{mode:off|on} replace_all{conductor}. ≤64.
dry_runbooleanValidate and return the diff; write nothing.
ripple"ripple" | "hold"'ripple': music-span scenes (timing music) keep their bars, so their scene windows are rewritten to the new grid in the same call (scenes it cannot move safely are left untouched and listed with a reason in diff.reflow); 'hold' (default): every window stays on seconds.
expected_versionintegerThe project's edit_version (from get_project or the last project-level write's response). Optional: when sent, the write is refused with a conflict (current_version, last_writer) if anyone changed the project settings since — nothing is written. Omit to write unconditionally.

set_cues

Name moments on a scene that other things can fire on

Put named moments on a scene — {name:"subscribe", at:"word:subscribe"} — so something else can be told to fire on them. A cue does NOTHING on its own; it is an address. Today the brand mark reads them: set_branding formula:"ghost" rests the mark low and lifts it on hit:<name>, which is how you get a subscribe bump on the exact word rather than on a beat. at is seconds from the scene start, or a moment on the scene's own rulers: "word:subscribe", "word:#4", "bar:3", "beat:7", "cam:hero", "end-2", with +0.25 / +1b / +2B offsets. PREFER the moment form — a cue pinned to a word survives a re-cut of the narration and one pinned to 4.2s does not. It resolves at render against the scene's measured grid; a cue that does not resolve is dropped rather than firing at zero. The list REPLACES what the scene carries (send [] to clear). Names are lowercase letters, digits and dashes, because they are addressed as literal text. Free; re-render to see the reaction in the MP4.

InputTypeDescription
scene_id requiredstringScene id (from get_storyboard).
cues requiredarrayThe complete cue list for this scene. Send [] to clear.

set_groove

Read or set the project's grooves

The project's GROOVES: a synthesized loop per scene that plays on the project's tempo (bar n is bar n in every scene, so neighbouring grooves stay in phase across a join and a seam sound from set_transition lands on it). Set a default every scene plays, override ONE scene (pattern_id null = silent there, "inherit" = back to the default), let a scene play its fill into the next seam, add or edit library patterns, set gain_db and enabled. Presets: glass-acid, grain-garage, pluck-bells, stutter-house — copied into the library the first time they are used. A pattern is {bars 1–32 (≤16 tracks), tracks: [{voice, steps, notes?, fill?, octave?, gain?, pan?, tone?, duck?, crush?, vel?, nudge?, split?, dyn?}], swing?, res?, seed?, humanize?, room?}; voices kick clap hat ohat rim acid fmbass reese stab pluck grain glitch texture bell, and an ACOUSTIC KIT bd snare brush ride crash tomhi tommid tomlo pedal (measured drums: velocity changes the timbre, not just the level; and an ACOUSTIC BAND upright piano vibes (measured notes; a note sounds for the steps it is held with - ties); and a STRING SECTION strings trem spicc pizz (recorded notes: each note is played by the section whose register it is in — violins from G3, violas, celli, basses — so octave -1/-2 moves a part down the orchestra; a CHORD is voiced across the section — top note first violins, then seconds and violas, the lowest note to the celli (a low bass doubled by the basses), split:false to turn that off; each section sits in its own seat on the stage; vel is the level (pp→ff ≈21 dB) and crossfades soft to loud recordings; ties hold a strings/trem note, and a note starting as the last ends is played legato); a held brush "x--" is a sweep). steps are "." rest, x hit, X accent, g ghost, 2–4 ratchet (a roll), - tie (one string, or up to 32 bar strings); vel is 0..1 per hit, cycled — the part's dynamics; nudge (ms) lays a track back or pushes it; humanize {ms, vel} is a player's looseness; room 0..0.6 the space. Swing a jazz part by writing it on triplets (res 12: ride "x..x.xx..x.x"). notes are scale degrees in the project key, strings for accidentals ("b7", "#4"), an array is a chord, and a roman numeral is a chord in the key ("i", "iv", "V", "bVI", "ii°", "V7"). dyn is a part's dynamics as a curve — [[1,"pp"],[8,"ff"]] is an 8-bar crescendo (levels 0..1 or ppp…fff, straight lines between; vel then only shapes accents) — so write a swell as two points, not a velocity per note. Tempo and key always come from the project. Call with only project_id to READ; render:true also returns each scene's hits (trains, scene-local seconds) to sync visuals to, and its ears: loudness, peak, each voice's level against the loudest (balance, dB) and notes (a buried voice, a slice hitting the ceiling) — read them to hear what you wrote. A scene still rendering comes back {pending: true}: read again in a minute. Free.

InputTypeDescription
project_id requiredstringProject id.
default_idstringGroove every scene without an override plays (library or preset id). Empty string = none.
scenesarrayPer-scene picks.
upsertarrayAdd or replace library patterns (validated).
add_presetsarrayPreset ids to copy into the library.
add_loopsarrayLoop-library ids (groove_library) to copy into this project.
removearrayLibrary ids to delete (the default and scene picks that use them are cleared).
gain_dbnumberGroove level in dB (−30..12, default 0).
enabledbooleanGrooves on/off for the whole project.
renderbooleanAlso render each scene's slice and return its hits (a read).
expected_versionintegerThe project's edit_version (from get_project or the last project-level write's response). Optional: when sent, the write is refused with a conflict (current_version, last_writer) if anyone changed the project settings since — nothing is written. Omit to write unconditionally.

set_mix

Read or set how the music sits under the voice

How the MUSIC sits under the VOICE — the same in the editor, the share link and the export. Two layers. MODE: "bed" ducks any music (tracks and grooves) under any voice, like a YouTube bed: it dips duck_db before the voice lands (attack_sec), stays down through breaths shorter than bridge_sec, comes back over release_sec, and carves a notch (carve_db at 2.5 kHz) so the words sit in it; "off" never ducks. New projects start on bed. MOMENTS are film-editor cues hung off a scene edge, so they move when the scene is re-timed, and they work whatever the mode: swell = the music takes the room (up db, default +5, over ramp_sec, held hold_sec, then back) — a title, a reveal, a pause in the voice; out = cue the music out (to silence over ramp_sec, default 1.5) until the next in — a serious line said dry; in = cue it back (only after an out, in the same chapter); hit = a stop-down, dead silence for hold_sec (default 0.5) then straight back — put it on a beat. edge "start" | "end" of the scene, offset_sec from it (negative = before: edge end, offset -4 = four seconds before the scene ends). Call with no changes to READ: mode, the effective duck, every moment with its index and at_sec on the film clock. SIDECHAIN FROM ANY SOURCE (ducks): up to 4 rules {source: "vo"|"sfx", target: "music"|"sfx", duck_db, attack_sec, release_sec, bridge_sec} — the target bus dips while the source sounds, the same ramp shape as the bed (default -8 dB on music, -4 dB on SFX). vo->sfx keeps sound effects out of the words; sfx->music dips the bed under a hit. The bed duck of mode "bed" stays as is; rules stack on top of it. Replaces all rules ([] clears). AUX SENDS (room): one shared reverb that buses feed — room {send: {vo, music, sfx} each 0..1 (default 0 = none), return_db -24..+6 (default -6), decay_ms 100..6000 (default 900), pre_delay_ms 0..200 (default 12), damping Hz 500..16000 (default 6000)}; null clears the room. Bus-level only, not per track. Both live in the project's mix settings, so they ride along when a project is forked or used as a basis. Free.

InputTypeDescription
project_id requiredstringProject id.
mode"bed" | "off""bed" = music ducks under voice; "off" = never.
duckobject
ducksarraySidechain from any source — REPLACES all rules ([] clears), at most 4. The target bus dips while the source sounds.
roomobject | nullAux sends: one shared reverb the buses feed (bus-level, not per track). A merge — null resets a knob; pass null for the whole room to remove it.
add_momentsarrayMoments to add.
remove_momentsarrayIndexes (from a read) of moments to delete.
clear_scenesarrayDelete every moment on these scenes.
momentsarrayReplace ALL moments with this list ([] clears them).
expected_versionintegerThe project's edit_version (from get_project or the last project-level write's response). Optional: when sent, the write is refused with a conflict (current_version, last_writer) if anyone changed the project settings since — nothing is written. Omit to write unconditionally.

set_pauses

Set timing pauses in a script block

Set the pacing of a script block: a pause is SILENCE inserted into the voice-over timeline at a point in the text, so every word after it is heard later (the editor's pause chips). Nothing is re-voiced; the block's anchored scenes re-time (a scene window grows by the silence inside it) and the chapter timeline follows. Use it to recreate a source video's pacing, or to leave room for a scene to land. Place each pause with after_text (it goes right AFTER that phrase — case-insensitive; occurrence picks the n-th match, default 1) or a raw char_pos; duration_ms 1–20000. mode "replace" (default) makes the list the block's pauses — pauses:[] clears them; "merge" keeps existing pauses at other positions. Omit pauses to read the current ones. Returns each pause with its char_pos and the text just before it — check the placement. Pauses are text positions, so they survive a voice regeneration, but rewriting the block text clears them. get_storyboard shows block ids. Free.

InputTypeDescription
chapter_id requiredstringChapter id.
block_id requiredstringScript block id.
pausesarrayThe pauses (max 64). Omit to read the current ones.
mode"replace" | "merge""replace" (default): these become the block's pauses. "merge": keep existing pauses at other positions.

set_project_voice

Set the project's narration voice

Set the voice this project's narration is spoken in. Free and reversible. It does NOT synthesise anything — voiceover is generated by resolve_project, which runs the voice BEFORE the scenes bound to it. A project with narration-bound scenes and no voice will have its resolve refused until one is set, because a scene authored with no word timings comes out at a default length and has to be paid for twice. Pick one from list_voices and say why it fits; changing the voice does not re-voice what is already generated.

InputTypeDescription
project_id requiredstringProject id.
voice_id requiredstringtts_preset id from list_voices.
expected_versionintegerThe project's edit_version (from get_project or the last project-level write's response). Optional: when sent, the write is refused with a conflict (current_version, last_writer) if anyone changed the project settings since — nothing is written. Omit to write unconditionally.

set_tempo

Read or set the project tempo

The project's musical grid: bpm, meter, key, where bar 1 falls (origin_sec) and tempo sections. Changing it does what the editor's tempo chip does: every grid-bound sound cue moves to the same bar:beat on the new grid, grid-bound motion follows at mount, and a music LOOP is re-conformed (time-stretched) to the new tempo — a full-length track keeps its own tempo, and going back to a loop's own tempo restores its original file. Send only what changes (e.g. just bpm); the rest is kept. A loop bake can take a few seconds and swaps itself in (status "pending"). FLAT edits only: it flattens tempo ramps into steps (the result says flattened_ramps) — use set_conductor for ramps, curves, signatures, markers. Call with only project_id to READ. Free.

InputTypeDescription
project_id requiredstringProject id.
bpmnumberTempo in quarter-note BPM, 20-400.
meterobject
key_scalestring | nullKey, e.g. "C minor"; null clears it.
origin_secnumberFilm seconds of bar 1, beat 1 (the first downbeat).
sectionsarrayTempo/meter/key changes from a point onward. Replaces the list; [] clears it.
expected_versionintegerThe project's edit_version (from get_project or the last project-level write's response). Optional: when sent, the write is refused with a conflict (current_version, last_writer) if anyone changed the project settings since — nothing is written. Omit to write unconditionally.

silence_trims

Read or set the silence trims of a script block

A silence trim tightens or stretches the NATURAL silence after a word (the quiet the voice itself left between two words), the way dragging the edge of a dark gap box on the timeline's voice track does. Omit at_audio_ms to list the block's trims. Pass at_audio_ms (the END of the word the silence follows, in the voice file: a word's endMs from get_audio_analysis / the cut_words reply) and delta_ms (> 0 stretches the silence, < 0 shortens it, 0 removes the trim; at most 5000 either way). Nothing is re-voiced; the block's anchored scenes re-time and the timeline follows. Authored pauses are separate (set_pauses); a trim belongs to the voice take it was made on. Free.

InputTypeDescription
chapter_id requiredstringChapter id.
block_id requiredstringScript block id.
at_audio_msnumberEnd of the word the silence follows, in the voice file (ms). Omit to list.
delta_msnumberChange to that silence in ms (> 0 longer, < 0 shorter, 0 removes the trim).

suggest_voices

Suggest voices for a brief

Get a ranked shortlist of voices for a BRIEF — no line to speak needed. Say what the voice is for (brief: "calm documentary about space, older male") and/or narrow by language, gender, age_group, provider, tier; pass project_id to lean on this workspace's habits. Each voice comes back with a score, reasons (why it is on the list), and a playable sample_url. The list is spread across providers (at most 3 each) so it is a real choice, up to 8. audition:true also synthesises a default sample (or your text, ≤400) for shortlisted voices that have no sample yet. Free; only the audition half is rate limited. Then compare two or three on the actual line with audition_voices, and set_project_voice.

InputTypeDescription
briefstringWhat the voice is for, in words (tone, subject, audience). ≤600 characters.
languagestringLanguage to speak, e.g. 'fr' or 'en-gb'. Includes multilingual voices that list it.
genderstringFilter by gender.
age_groupstringFilter by age group.
providerstringOnly this TTS provider, e.g. 'replicate', 'inworld', 'fishaudio'.
tierstring'standard' or 'premium'.
project_idstringProject id: leans toward voices this workspace already uses; its current voice is left out.
limitnumberVoices to return (default 8, max 8).
auditionbooleanSynthesise a sample for shortlisted voices that have none. Default false.
textstringThe line for that audition (≤400). Omit for a default sample in the language.

tighten_silences

Cut the dead air out of a project's narration

Tighten the pacing of a whole project (or one chapter) in one call. Finds every silence in the voice-over from the audio itself, cuts each one longer than keep_ms (default 300) down to keep_ms, and leaves the rest. The cuts are real: every word timing, caption and scene window anchored to the narration moves up with them, so anything tied to words follows with no further edit, and the film gets shorter. Not a stretch: the voice is untouched, only the quiet is removed. Keep a dramatic pause with keep:[{before:"Leave"}] (leave the silence just before those words) or {after:"..."} (just after), optionally scoped to a block_id, or keep_at_least_ms to leave every silence at least that long. dry_run:true reports what would be cut (per block: silences, savings, what was kept) and writes nothing; run it first. Re-running replaces this tool's own cuts and leaves cut_words strikes alone; silence trims on a tightened block are cleared. Older takes are measured first (free). Cuts belong to the voice take: re-voicing a block drops them, run it again. Anchor visuals to words, not absolute seconds, and re-timing stays free. Free.

InputTypeDescription
project_id requiredstringProject id.
chapter_idstringOnly this chapter (default: every chapter).
keep_msnumberSilence left between sentences, ms (default 300).
edge_keep_msnumberSilence left at the start and end of each block's audio, ms (default half of keep_ms).
keep_at_least_msnumberLeave every silence at least this long untouched (a deliberate pause).
keeparraySilences to leave as they are: {before:"phrase"} the silence right before those words, {after:"phrase"} right after, both to require both; block_id optional.
dry_runbooleanReport only; write nothing.

transcribe

Spends credits

Read the words out of a recording

Timed words from a library recording or video. SPENDS CREDITS (~1/min).

InputTypeDescription
media_asset_id requiredstringThe library asset to transcribe (from list_media).
project_idstringWhich project the transcript should ground.

transcribe_media

Spends credits

Read the words out of a recording

Transcribe an audio or video asset that is ALREADY in the library, and ground the project in what was said. Word-level timings come back with it. Fast — about a minute of wall clock per hour of audio.

SPENDS CREDITS, priced by the length of the recording (~1 credit per minute of audio). The charge belongs to the REQUEST: polling an in-flight transcription is free, and the same asset is never billed twice. Confirm before transcribing something long.

REACH FOR THIS THE MOMENT A RECORDING IS THE SUBJECT. "Use this talk", "clip the highlights", "make something from this interview", "what does he say at the end" — all of them need the words first, and nothing else in this surface has read the file. Without it you are working from a file name: a video is captioned from ONE poster frame, so list_media and list_observations can tell you a clip exists and how long it is, never what is in it.

ASYNCHRONOUS: it returns status: "pending" and the work continues in the background. Poll rather than calling again — a second call on the same asset reports the state, it does not queue a second pass.

NO SPEECH, NO TRANSCRIPT: a recording the audio analysis heard no speech or singing in (an instrumental) is refused before any charge — force: true transcribes it anyway — and get_sources reports such a source usable:false, "instrumental — no speech detected", with no segments: text speech-to-text makes up over music is never a transcript.

InputTypeDescription
media_asset_id requiredstringThe library asset to transcribe (from list_media). An id, never a url.
project_idstringWhich project the transcript should ground. Defaults to the asset's own project; required when the asset belongs to none.
role"subject" | "supporting" | "style"How the transcript is used: "subject" (what the video is about — the default), "supporting" (evidence alongside other material).
forcebooleanTranscribe even when the audio analysis heard no speech or singing in it (charged).

voice_takes

List or switch the voice takes of a script block

Every time a block is voiced the result is KEPT as a take; the active one is what plays. Omit take_id to list the block's takes (id, length, words, which is active). Pass take_id to make that take active: nothing is re-voiced or billed, the block's anchored scenes re-time to its length and the timeline follows. Pauses carry over (they are text positions); cuts and silence trims were made on a specific take, so the reply's stale_edits counts the ones that no longer apply. Use it to compare two readings (switch, then check_sync / share_project) or to go back after a re-voice. get_storyboard shows block ids. Free.

InputTypeDescription
chapter_id requiredstringChapter id.
block_id requiredstringScript block id.
take_idstringThe take to make active. Omit to list the takes.

On this page