Nodaro Docs
DocumentationNode ReferenceModelsAI Agents (MCP)DevelopersSelf-hostingResearch
CLI

Media and voice commands

Revoice tracks, burn in captions, build slideshows and overlays, process audio and plan edits with the voice, media, audio and edit commands of the Nodaro CLI.

The media and voice commands of the Nodaro CLI work on audio, video and images directly. The voice group revoices tracks and designs voices, media imports, trims, captions and composes media, audio processes and transcribes sound, and edit plans and applies edits for podcasts and long videos. Each command runs the same engine as the matching node in the editor.

Every command that starts a job accepts --watch to wait for the result, --poll-interval <ms> to set the polling interval, and --json. See Output and exit codes.

Voice

nodaro voice list [--clones] [--json]
nodaro voice changer --voice <id> --audio <url>|--video <url> [--model <id>] [--stability <0..1>] [--similarity <0..1>] [--style <0..1>] [--use-speaker-boost] [--seed <n>] [--remove-background-noise] [--watch] [--poll-interval <ms>] [--json]
nodaro voice recast --audio <url>|--video <url> --voices <v1,v2,...>|--voices-json <json> [--model <id>] [--output video|stems] [--analysis-json <json>|--analysis-file <path>] [--no-preserve-background] [--separation-quality fast|best] [--music-volume-mode match|normalize|manual] [--music-volume <0-200>] [--remove-background-noise] [--voice-fx <preset>] [--voice-fx-mix <0-100>] [--voice-fx-delay <20-2000>] [--voice-fx-decay <0-1>] [--watch] [--poll-interval <ms>] [--json]
nodaro voice analyze --audio <url>|--video <url> [--separation-quality fast|best] [--suggest-title] [--watch] [--poll-interval <ms>] [--json]
nodaro voice export --source <videoUrl> --tracks-json <json>|--tracks-file <path> [--voice-fx <preset>] [--voice-fx-mix <0-100>] [--voice-fx-delay <20-2000>] [--voice-fx-decay <0-1>] [--watch] [--poll-interval <ms>] [--json]
nodaro voice design --text <line> --description <desc> [--model <id>] [--loudness <-1..1>] [--guidance-scale <0-100>] [--seed <n>] [--quality <n>] [--enhance] [--user-prompt <text>] [--watch] [--poll-interval <ms>] [--json]
nodaro voice remix --text <text> --description <desc> [--user-prompt <text>] [--watch] [--poll-interval <ms>] [--json]
nodaro voice dub --audio <url> --target-language <code> [--source-language <code>] [--num-speakers <1-20>] [--disable-voice-cloning] [--drop-background-audio] [--watch] [--poll-interval <ms>] [--json]
nodaro voice clones list [--json]
nodaro voice clones delete <id> [--json]
CommandWhat it does
voice listLists the premade voices, or your clones with --clones. Use their names or ids with --voice and --voices.
voice changerRevoices one audio track or one talking video with a single voice, like the Voice Changer node. voice change is the same command.
voice recastRevoices every speaker of a recording at once, like the Voice Changer Pro node. voice pro is the same command.
voice analyzeDetects the speakers without recasting and prints the list with --watch. Nodaro Cloud only.
voice exportRenders the final video from a mixed set of tracks. Nodaro Cloud only.
voice designDesigns a new synthetic voice from a text description, like the Voice Design node.
voice remixSpeaks a text in a described voice, without cloning, like the Voice Remix node.
voice dubDubs a recording into another language and keeps each speaker's voice, like the Dubbing node.
voice clonesLists and deletes voice clones made before cloning was retired.

Recast several speakers

voice recast runs on Nodaro Cloud. A self-hosted install runs it through its connection to Nodaro Cloud.

  • --voices maps voices to speakers in the order Nodaro detects them. The word keep keeps that speaker's original voice, as in --voices Rachel,keep,Aria.
  • --voices-json takes the raw SDK array instead: voice ids, settings objects per voice, or null for a speaker who keeps the original voice.
  • --output stems returns one dry track per speaker, for an interactive mix, instead of a finished video. Render the mix with voice export.
  • --analysis-file reuses a saved voice analyze result, so the speakers are not detected again.

The interactive recast flow

The one-step voice recast renders a finished video in a single call. The three-step flow lets you check the speakers first and mix the result before you render it:

# 1. Detect the speakers. Save the job's output_data for step 2.
nodaro voice analyze --video https://example.com/panel.mp4 --watch --json > analyze.json
jq .output_data analyze.json > analysis.json

# 2. Recast to dry stems, reusing the analysis (no second detection)
nodaro voice recast --video https://example.com/panel.mp4 --voices Rachel,keep,Aria \
  --analysis-file analysis.json --output stems --watch

# 3. Set the level and mute of each track, then render
nodaro voice export --source https://example.com/panel.mp4 --tracks-file mix.json \
  --voice-fx hall --voice-fx-mix 25 --watch

In step 3, each track in mix.json is an object with a url, a gain from 0 to 200, a muted flag and an optional kind, taken from the stems of step 2. The export copies the video stream unchanged; it is never encoded again.

Media

nodaro media download <url> [--max-height <px>] [--section <a-b>] [--watch] [--json]
nodaro media metadata <url> [--json]
nodaro media trim-video --video <url> --start <sec> --end <sec>|--keep-first <sec>|--keep-last <sec> [--watch] [--poll-interval <ms>] [--json]
nodaro media trim-audio --video <url>|--audio <url> [--start <sec>] [--end <sec>] [--format mp3|wav|aac] [--watch] [--poll-interval <ms>] [--json]
nodaro media add-captions <videoUrl> [options, see below]
nodaro media still-to-video --image <url> --audio <url> [--motion none|zoom-in|zoom-out|pan-left|pan-right|ken-burns] [--intensity <1-10>] [--resolution 720p|1080p|4K] [--aspect-ratio <W:H>] [--fps 24|30] [--fit cover|contain] [--pad-color <hex>] [--watch] [--poll-interval <ms>] [--json]
nodaro media slideshow --images <url...> [--audio <url>] [--durations "10,auto,auto"] [--per-image <sec>] [--transition <id>] [--transition-duration <sec>] [--motion none|zoom-in|zoom-out|ken-burns|alternate] [--intensity <1-10>] [--resolution 720p|1080p|4K] [--aspect-ratio <W:H>] [--fps 24|30] [--fit cover|contain] [--pad-color <hex>] [--watch] [--json]
nodaro media collage <imageUrls...> [--sizes <0-3,...>] [--numbered] [--label <text>...] [--badge-position top-left|top-right] [--layout smart|grid] [--resolution 2K|4K] [--aspect-ratio <W:H>] [--gap <px>] [--background-color <hex>] [--watch] [--poll-interval <ms>] [--json]
nodaro media overlay <imageUrl> [layerUrls...] [--layers-file <path>] [--anchor <anchor>] [--x <%>] [--y <%>] [--width <%>] [--opacity <0-1>] [--platform <id>...] [--qr-text <text>] [--mask-mode none|layers|around|outside] [--mask-spread <px>] [--canvas <WxH>] [--base-fit contain|cover] [--background-color <hex>] [--output-format png|jpg|webp] [--watch] [--poll-interval <ms>] [--json]
nodaro media overlay-placement <imageUrl> [--intent <text>] [--aspect <ratio>] [--safe-area <x,y,w,h>] [--json]
nodaro media video-overlay <videoUrl> [layerUrls...] [--at <start[-end]>...] [--preset card|corner-badge|full-frame] [--corner top-left|top-right|bottom-left|bottom-right] [--layers-file <path>] [--aspect 16:9|9:16|1:1|4:5] [--base-fit cover|contain] [--background-color <hex>] [--watch] [--poll-interval <ms>] [--json]
nodaro media save <url> [--filename <name>] [--type image|video|audio] [--watch] [--poll-interval <ms>] [--json]
CommandWhat it does
media downloadImports a video from YouTube, TikTok, Instagram, X or Facebook into your storage. --section fetches one time range, in seconds. --watch streams live progress, and there is no job to poll later.
media metadataReads the duration, dimensions and title of a media URL without downloading it.
media trim-videoCuts a video by start and end time, or keeps its first or last seconds.
media trim-audioCuts the audio of a video or an audio file and saves it as MP3, WAV or AAC.
media add-captionsBurns captions into a video. See Captions.
media still-to-videoTurns one still and one audio file into an MP4, for 0 credits. The video is as long as the audio, so there is no duration option. --motion animates the still.
media slideshowTurns 2 to 100 images, with optional audio, into an MP4 slideshow, for 0 credits.
media collageComposites 2 to 30 images into one large image.
media overlayPlaces up to 12 layers on a base image, pixel-exact, without AI.
media overlay-placementAsks a vision model where one layer should go.
media video-overlayPlaces 1 to 20 timed image layers over a video, without AI, for 20 credits.
media saveSaves a media URL to your storage, as an image, a video or an audio file.

Slideshows

With audio, the audio sets the length of the slideshow. Durations you pinned with --durations are scaled in proportion, and the CLI tells you so. Without audio, the slideshow is silent and lasts the number of images times --per-image.

Collages

  • --sizes gives each image a relative size hint, in the order of the images: 0 automatic, 1 big (about twice as wide), 2 medium, 3 small (about half as wide). Size hints work with the smart layout only.
  • --numbered stamps a sequence number, starting at 1, in a corner of each image, for storyboards.
  • --badge-position sets that corner: top-left, the default, or top-right. It also places the labels.
  • --label adds a caption after the number. Repeat it once per image, in order; an empty "" skips one image.

Image overlays

  • Image URLs after the base image are image layers. They share --anchor, --x, --y, --width and --opacity, which suits a watermark.
  • --layers-file takes the full JSON array of layers instead: options per layer, and the text, QR code and shape kinds.
  • Placement is in percent of the base image, so one command fits a 1K preview and a 4K render.
  • --platform, which you can repeat, also renders the composite at that platform's size. The base render costs 10 credits and each platform adds 2 credits. The job's output lists the extra renders as variants.
  • overlay-placement answers in the same percent units: an anchor, x, y, width and a one-line reason. It answers at once, without a job to poll, and costs one image-to-text call.

Video overlays

  • Give one --at per image URL, in order. 3 means from 3 seconds to the end, and 1.2-2.6 means from 1.2 to 2.6 seconds.
  • --preset and --corner apply to every image layer given as a URL.
  • --layers-file takes the full layers array instead, with a box, opacity, animation and stacking order per layer.
  • --base-fit and --background-color need --aspect.
  • The audio of the base video is kept untouched.

See the Video Overlay node for the layer options.

Captions

nodaro media add-captions <videoUrl> [--text <text>] [--captions-file <file.json>] [--style subtitle|word-highlight|karaoke|tiktok-words|word-pop|bouncy] [--look outline|clean] [--position bottom|top|center] [--position-y <pct>] [--font-size <px>] [--font-family <name>] [--font-weight <100-900>] [--color <c>] [--background-color <c>] [--stroke-color <c>] [--stroke-width <px>] [--highlight-color <c>] [--uppercase|--no-uppercase] [--max-words-per-line <1-20>] [--animate|--no-animate] [--no-auto-transcribe] [--transcribe-provider elevenlabs-stt|incredibly-fast-whisper|whisper] [--segments-file <file.json>] [--watch] [--poll-interval <ms>] [--json]

media add-captions has two kinds of style, like the Add Captions node:

StyleWhat it shows
subtitleStatic captions, without word animation.
word-highlight, karaoke, tiktok-words, word-pop, bouncyKinetic captions, animated word by word. word-highlight, karaoke and bouncy show one held line at a time.

The text of the captions

  • On subtitle, --text is burned in as one static block for the whole video. It is never replaced by a transcription. Omit --text to caption the speech.
  • On a kinetic style, --text is only the fallback when transcription returns nothing, or when you pass --no-auto-transcribe.
  • --captions-file is a JSON array of word-timed entries, [{ text, startMs, endMs }], one entry per word for the kinetic styles. The words of a nodaro audio transcribe result fit it as they are; pair the file with --no-auto-transcribe.
  • --segments-file gives time ranges their own style, look and position. The ranges must not overlap.

Styling

  • The styling options also style a subtitle: --look, --font-family, --font-weight, --stroke-color, --stroke-width, --uppercase, --position-y and --max-words-per-line. A styled subtitle is billed at the kinetic price; a plain subtitle stays at the lower price.
  • --highlight-color and --animate work on kinetic styles only. They are refused on subtitle.
  • --animate is on by default. --no-animate stops the motion of each word, and keeps the grouping and the highlight color.
  • Without --look, the kinetic styles render as outline and subtitle renders as clean.
  • --max-words-per-line caps the number of words on one caption line, or on one page of tiktok-words, from 1 to 20. The frame width, sentence ends and pauses of 0.5 seconds or more also break lines. One or two words give a punchy, fast read; leave it unset to fill the width. On a --text subtitle, it only sets the line breaks, and it has no effect on word-pop.
  • A kinetic or styled render keeps the frame rate of the source, as a whole number from 15 to 60 fps. A variable-frame-rate or very long source renders at 30 fps.

Transcription engine

--transcribe-provider chooses the engine that transcribes the speech. A kinetic style needs word timings, from incredibly-fast-whisper, the default, or elevenlabs-stt. subtitle needs phrase timings only, so whisper also works there.

Audio

nodaro audio separate --audio <url> [--mode vocal_instrumental|stems] [--quality auto|fast|best] [--watch] [--poll-interval <ms>] [--json]
nodaro audio isolate --audio <url> [--watch] [--poll-interval <ms>] [--json]
nodaro audio fx --audio <url> [--preset <preset>] [--mix <0-100>] [--delay <20-2000>] [--decay <0-1>] [--eq-low <db>] [--eq-high <db>] [--watch] [--poll-interval <ms>] [--json]
nodaro audio mix --audio <url> --audio <url> ... [--volumes <csv>] [--watch] [--poll-interval <ms>] [--json]
nodaro audio adjust-volume --audio <url>|--video <url> [--volume <0-200>] [--normalize] [--fade-in <sec>] [--fade-out <sec>] [--watch] [--poll-interval <ms>] [--json]
nodaro audio combine --segment <url[@a-b]> --segment ... [--watch] [--poll-interval <ms>] [--json]
nodaro audio transcribe --audio <url> [--provider elevenlabs-stt|incredibly-fast-whisper|whisper] [--language <code>] [--diarize] [--tag-audio-events] [--word-timestamps] [--watch] [--poll-interval <ms>] [--json]
CommandWhat it doesNode
audio separateSplits vocals from the instrumental, or into stems.Audio Separation
audio isolateKeeps the voice and removes the rest.Voice Extractor
audio fxApplies an effect preset, with mix, delay, decay and equalizer settings.Audio FX
audio mixMixes several tracks, with one volume per track.Mix Audio
audio adjust-volumeChanges the volume, normalizes, and fades in or out.Adjust Volume
audio combineJoins segments one after another. url@a-b takes one time range of a file.Combine Audio
audio transcribeTurns speech into text.Transcribe

These are the building blocks that Voice Changer Pro combines, available on their own.

Transcription engines

EngineWord timingsAlso supports
elevenlabs-sttAlways--diarize (who speaks when) and --tag-audio-events
incredibly-fast-whisperWith --word-timestamps
whisperNone, phrase segments only; --word-timestamps is refused before any credits are spent

If you omit --provider, the whisper engine runs. Name an engine whenever you need word timings.

The completed job's output_data carries text, words (one entry per word, in milliseconds) and json (the normalized transcript, also in milliseconds). A top-level segments list, in seconds, exists only with whisper and incredibly-fast-whisper; elevenlabs-stt returns none, so read words. Pass words to media add-captions --captions-file for a kinetic render.

Edit

The edit commands are editorial building blocks for podcasts and long videos.

nodaro edit silence-detect <audioUrl> [--threshold-db=-35] [--min-silence-ms <ms>] [--pad-ms <ms>] [--watch] [--poll-interval <ms>] [--json]
nodaro edit audio-sync (--source <[id=]url> ... | --sources-file <file.json>) [--reference <id>] [--watch] [--poll-interval <ms>] [--json]
nodaro edit apply-edl --edl <file.json> [--transcript <file.json>] [--source <url> ...] [--output video|audio] [--quality proxy|final] [--crossfade-ms <ms>] [--watch] [--poll-interval <ms>] [--json]
nodaro edit plan --mode tighten|clips|chapters --plan-tier economy|standard|premium --transcript <file.json> (--source <url[@audio|@video]> ... | --sources-file <file.json>) [--silence <file.json>] [--instructions <text>] [--style-guide <text>] [--count <n>] [--target-duration-sec <n>] [--target-aspect 16:9|9:16|1:1|4:5] [--platform <name>] [--watch] [--poll-interval <ms>] [--json]
CommandWhat it doesNode
edit silence-detectFinds the silent passages of a recording.Silence Detect
edit audio-syncAligns 2 to 6 recordings, audio or video, of the same event.Audio Sync
edit planPlans an edit from a transcript: tighten the pace, cut clips or mark chapters.Edit Plan
edit apply-edlRenders an edit decision list (EDL) as a video or an audio file.Apply EDL

edit audio-sync names the recordings source-1, source-2 and so on, unless you give an id as id=url. Its output_data.json holds three fields:

  • reference: the recording the others are aligned to. Choose it with --reference.
  • offsets: one entry per recording, with sourceId, offsetMs, confidence and driftMsPerHour.
  • notes: remarks about the alignment.

A time in a recording converts to the reference with referenceMs = sourceMs + offsetMs.

Frequently asked questions

Last updated on

On this page