NodaroAccount
Nodaro Docs
DocumentationNode ReferenceModelsTemplatesAI Agents (MCP)DevelopersSelf-hostingResearchCompare
CLI

Media and voice commands

Revoice tracks, caption videos, process audio, plan edits, and tighten, chapter and clip podcast episodes with the voice, media, audio and edit CLI commands.

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 favorites [--json]
nodaro voice favorite <voiceId> --name <name> --type premade|library|custom [--preview <url>] [--json]
nodaro voice unfavorite <voiceId> [--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 favoritesLists your favorite voices, newest first: premade, library or clone. Use their ids with --voice and --voices.
voice favoriteStars a voice, with the name and the https preview your favorites list shows it by. Starring it again refreshes them.
voice unfavoriteRemoves a voice from your favorites. It also succeeds for a voice that is not starred.
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 split-media --video <url>|--audio <url> --chunk-duration <sec> [--min-part-duration <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>] [--layout video-bottom|video-top|stack-whole|stack-filled|pip] [--base-box <json>] [--watch] [--poll-interval <ms>] [--json]
nodaro media generate-mask <imageUrl> <prompt> [--threshold <n>] [--watch] [--poll-interval <ms>] [--json]
nodaro media split-layers <imageUrl> [--max-layers <1-99>] [--size 1K|1.5K|2K|auto] [--prompt <text>] [--session <id>] [--idempotency-key <key>] [--watch] [--poll-interval <ms>] [--json]
nodaro media video-mask <videoUrl> <prompt> [--threshold <n>] [--model sam-3.1|sam-3] [--hold-last-mask] [--min-subject-height <pct>] [--max-subject-height <pct>] [--zone <L,R,T,B>] [--per-shot] [--redetect-every <sec>] [--watch] [--poll-interval <ms>] [--json]
nodaro media mask-composite <foregroundUrl> <backgroundUrl> <maskUrl> [--invert] [--feather <px>] [--grow <px>] [--background-fit cover|contain|stretch] [--audio foreground|background|mix|none] [--watch] [--poll-interval <ms>] [--json]
nodaro media mask-composite <backgroundUrl> <maskUrl> --fill pixelate|blur [--pixel-size-pct <pct>] [--blur-strength-pct <pct>] [--invert] [--feather <px>] [--grow <px>] [--watch] [--json]
nodaro media save <url> [--filename <name>] [--type image|video|audio] [--watch] [--poll-interval <ms>] [--json]
CommandWhat it does
media downloadImports the video behind a link 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 split-mediaCuts a video, an audio file or both into parts of at most --chunk-duration and at least --min-part-duration seconds. The default minimum is 4 seconds. The parts are in the job's videoUrls and audioUrls. See Split into Chunks.
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 or video layers over a video, without AI. A run with image layers only costs 22 credits. A run with a video layer is priced per started 5 seconds of the base video.
media generate-maskSelects a subject described in text in an image, and returns a black-and-white mask image, white where the subject is. --threshold runs from 0 to 1, with a default of 0.3. The model that Generate Mask uses today ignores this value, so change the prompt to change the mask. The job's output carries maskUrl, the mask, and imageUrl, the source passed through. Feed both to an inpainting edit. It costs 55 credits. See Generate Mask.
media split-layersSplits one image into a base picture and separate layers, each element on its own transparent PNG. --max-layers (default 9) caps the layers: more elements merge into fewer layers, and none is dropped. --size is each image's pixel budget: 1K, the default, is about one megapixel, and auto keeps the picture's own size. --prompt (up to 2,000 characters) names what to separate, and may carry <bbox>x1 y1 x2 y2</bbox> marks from 0 to 1000. The job's output carries imageUrl (the base), layers (bottom to top) and layerData: each layer's name, zIndex, its file's own size, its box on the base, in the base's pixels, and baseUrl. A layer is cropped to its element, so scale it to its box to put it back. A run holds the price of --max-layers + 1 images and is charged only for the images it returns. --session files the job in one of your sessions. --idempotency-key (8 or more characters) makes a retry answer the first request's job instead of starting a second one.
media video-maskTracks a subject described in text through a video and returns a black-and-white mask video, white where the subject is. SAM 3.1 is the default, and --model sam-3 costs half. --threshold runs from 0.05 to 0.95, with a default of 0.5. A lower value finds more. --hold-last-mask keeps the last mask on frames where the subject is lost, for at most 1 second. --min-subject-height drops subjects shorter than that percent of the frame height, and --max-subject-height drops those taller. --zone 10,10,5,5 keeps only subjects whose center is inside those left, right, top and bottom margins, from 0 to 49 % each. --per-shot finds the scene cuts first and detects the subject again in every shot. --redetect-every, from 1 to 10 (0, the default, is off), also detects the subject again every that many seconds, in each shot with --per-shot. It catches someone who walks in or turns to the camera mid-shot. The run is slower, and the price is the same. See Video Mask.
media mask-compositePlaces the foreground over the background through the mask, white for the foreground. It costs 11 credits for every started 5 seconds of the result. --feather runs from 0 to 20 pixels, and --grow from -10 to 10. --fill pixelate or --fill blur fills the mask with the background itself, so it takes two URLs, the background and the mask, and the result follows the background. --pixel-size-pct runs from 0.2 to 10, default 1.25, and --blur-strength-pct from 0.1 to 5, default 2. See Mask Composite.
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 11 credits, and each platform adds to the price. 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.
  • Positional URLs are image layers.
  • --layers-file takes the full layers array instead, with a box, opacity, animation and stacking order per layer.
  • Video layers go through --layers-file: write "videoUrl" in place of "imageUrl", for at most 2 layers. A video layer is silent unless it sets "sound": {"volume": 0.8}, with a volume from 0 to 1.
  • --layout places the base video, the first video layer or both. video-bottom and video-top put the whole base against that edge. stack-whole and stack-filled put the base above the first video layer. pip puts that layer in its corner. Every layout except pip needs --aspect.
  • --base-box places the base video yourself, as JSON in the layer box units, for example --base-box '{"anchor":"bottom","width":100}'.
  • --base-fit, --background-color and --base-box need --aspect.
  • When no video layer has sound, the audio of the base video is kept untouched.
  • A run with a video layer takes a base video of up to 60 seconds. Its price is per started 5 seconds of the base. Check the price with nodaro models cost video-overlay:video.
[{"videoUrl":"https://example.com/guest.mp4","start":0,"corner":"top-right","sound":{"volume":0.8}}]

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>] [--duck-under <index>] [--duck-amount <0-100>] [--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 pitch-tempo --audio <url>|--video <url> [--semitones <-12..12>] [--tempo <0.5-2>] [--no-preserve-formants] [--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|nemotron-3-5-transcribe] [--language <code>] [--diarize] [--tag-audio-events] [--word-timestamps] [--target-language <code>] [--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. --duck-under makes the other tracks dip under one track, given by its 0-based index. --duck-amount sets how far, default 75.Mix Audio
audio adjust-volumeChanges the volume, normalizes, and fades in or out.Adjust Volume
audio pitch-tempoShifts the pitch in semitones, or changes the tempo without changing the pitch. --no-preserve-formants lets the voice change character with the pitch.Pitch & Tempo
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
nemotron-3-5-transcribeWith --word-timestamps, with a speaker per word--target-language (to or from English) translates the speech instead, with no word timings

If you omit --provider, the whisper engine runs. Name an engine whenever you need word timings. Nemotron 3.5 Transcribe is priced per started minute of the file, and takes files up to 60 minutes and 200 MB.

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. Five commands run a whole podcast edit in one command: edit tighten-episode, edit episode-chapters, edit episode-trailer, edit clip-pack and edit speaker-layout.

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 speaker-map (--source <[id=]url> ... | --sources-file <file.json>) --transcript <file.json> [--offsets <file.json>] [--master <id>] [--wide <id>] [--margin-db <db>] [--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>] [--clip-key <inMs-outMs>] [--watch] [--poll-interval <ms>] [--json]
nodaro edit plan --mode tighten|clips|chapters|trailer --plan-tier economy|standard|premium --transcript <file.json> (--source <[id=]url[@audio|@video]> ... | --sources-file <file.json>) [--silence <file.json>] [--offsets <file.json>] [--transcript-source <id>] [--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]
nodaro edit capabilities [--json]
nodaro edit switch-cameras --edl <file.json> --transcript <file.json> [--speaker-map <file.json>] [--speaker-map-result <file.json>] [--speaker-names <file.json>] [--min-shot-ms <ms>] [--lead-ms <ms>] [--lag-ms <ms>] [--max-shot-ms <ms>] [--wide-every <n>] [--layout-hints] [--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 speaker-mapFinds which camera each speaker is on, from the cameras' own microphones.Speaker Map
edit planPlans an edit from a transcript: tighten the pace, cut clips, mark chapters or cut a trailer.Edit Plan
edit capabilitiesLists the Edit Plan modes this server can plan. Nothing is charged.Edit Plan
edit apply-edlRenders an edit decision list (EDL) as a video or an audio file.Apply EDL
edit switch-camerasPuts each cut of an edit on the camera of the person speaking. The transcript needs speaker labels.Camera Switch
edit tighten-episodeTightens a recording into a finished episode: transcribe, plan and render, with captions, music and framing as set.Tighten Episode
edit episode-chaptersLists a recording's chapters. Nothing is rendered.Chapters
edit episode-trailerCuts a 20 to 40 second trailer in each chosen format.Trailer
edit clip-packCuts a recording into a pack of short clips.Clip Pack
edit speaker-layoutFrames a whole recording by speaker, without cutting anything.Speaker Layout
edit continue-use-caseContinues one of the five runs above as a new job.Tighten Episode

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.

edit speaker-map takes 2 to 6 recordings, with the same --source rules as edit audio-sync. --offsets takes an edit audio-sync result. --master and --wide name recordings that are no one's camera. A row of --sources-file may carry kind: "audio" for a sound-only recording, which is never a camera. The result's output_data.json is { version, speakerMap, confidence, notes, edl? }: pass it to edit switch-cameras --speaker-map-result.

edit apply-edl --quality proxy renders a Preview to review: it is private and billed at the lower preview rate. --quality final renders the delivery. --clip-key names the clip of a Clips-mode plan that the render cuts, as <first inMs>-<last outMs>. The result returns it as output_data.clipKey, beside output_data.quality.

edit capabilities prints the Edit Plan modes this server can plan, who answered, and whether Edit Plan is charged per started minute. A connected self-hosted install is answered by Nodaro Cloud. With --json, it prints { modes, source, perMinute }.

edit switch-cameras --speaker-map-result takes an edit speaker-map result. A label in --speaker-map wins over it. --lead-ms makes each cut come earlier, and --lag-ms makes it come later, by 0 to 5,000 ms. --lag-ms defaults to 0.

Several cameras, step by step

For a multicam recording, edit plan --offsets takes the output_data.json of an edit audio-sync job over the same source ids. The plan applies each source's offset before it starts. A source that was not measured, or that matched weakly, is refused; set its offsetMs in --sources-file instead. A multicam edit runs these commands in order:

  1. audio transcribe --provider elevenlabs-stt --diarize, for a transcript with speaker labels.
  2. edit audio-sync, to measure the offsets.
  3. edit plan --offsets, to plan the edit.
  4. edit speaker-map, to find who is on which camera.
  5. edit switch-cameras --speaker-map-result, to put each cut on the speaker's camera.
  6. edit apply-edl --quality proxy to review, then edit apply-edl --quality final for delivery.

Edit a whole episode in one command

nodaro edit tighten-episode --media <url> [--media <url> ...] [--master-audio <url>] [--wide-camera <n>] [--synced] [--speaker-camera <speaker>=<recording> ...] [--music <url> [--music-duck-amount <0-100>]] [--output video|audio] [--framing 16:9|9:16|1:1|4:5 [--layout auto|single|side-by-side|stacked|grid|pip] [--framing-source auto|static|tracking]] [--no-captions | --caption-style subtitle|word-highlight|karaoke|tiktok-words|word-pop|bouncy] [--review] [--plan-tier economy|standard|premium] [--instructions <text>] [--style-guide <text>] [--idempotency-key <key>] [--estimate] [--watch] [--poll-interval <ms>] [--json]
nodaro edit episode-chapters --media <url> [--plan-tier economy|standard|premium] [--instructions <text>] [--style-guide <text>] [--idempotency-key <key>] [--estimate] [--watch] [--poll-interval <ms>] [--json]
nodaro edit episode-trailer --media <url> [--media <url> ...] [--master-audio <url>] [--wide-camera <n>] [--synced] [--speaker-camera <speaker>=<recording> ...] [--intro-card <url>] [--formats 9:16,1:1,4:5,16:9] [--review] [--plan-tier economy|standard|premium] [--instructions <text>] [--style-guide <text>] [--idempotency-key <key>] [--estimate] [--watch] [--poll-interval <ms>] [--json]
nodaro edit clip-pack --media <url> [--media <url> ...] [--master-audio <url>] [--wide-camera <n>] [--synced] [--speaker-camera <speaker>=<recording> ...] [--count <n>] [--length <sec>] [--framing 16:9|9:16|1:1|4:5|none [--layout auto|single|side-by-side|stacked|grid|pip] [--switch <id>] [--emphasis <style>]] [--framing-source auto|static|tracking] [--no-captions | --caption-style subtitle|word-highlight|karaoke|tiktok-words|word-pop|bouncy] [--review] [--plan-tier economy|standard|premium] [--instructions <text>] [--style-guide <text>] [--idempotency-key <key>] [--estimate] [--watch] [--poll-interval <ms>] [--json]
nodaro edit speaker-layout --media <url> [--media <url> ...] [--master-audio <url>] [--wide-camera <n>] [--synced] [--speaker-camera <speaker>=<recording> ...] [--aspect 16:9|9:16|1:1|4:5] [--layout auto|single|side-by-side|stacked|grid|pip] [--switch <id>] [--emphasis <style>] [--framing-source auto|static|tracking] [--review] [--idempotency-key <key>] [--estimate] [--watch] [--poll-interval <ms>] [--json]
nodaro edit continue-use-case <jobId> --mode from-failed|render-final [--edit <file.json>] [--type tighten-episode|episode-chapters|episode-trailer|clip-pack|speaker-layout] [--idempotency-key <key>] [--watch] [--poll-interval <ms>] [--json]

Each of the five commands takes a recording, video or audio, up to 3 hours. Trailer and Speaker Layout need a recording with picture. A run costs its steps at their own rates, plus a fixed fee per run. A failed run's fee is refunded. --review stops at a preview for a person to check, and prints the edit continue-use-case command that renders the final.

  • --estimate quotes the run the same flags would start, and starts nothing: no job is created and nothing is charged. It prints the total, the steps, the fee per run and the recording's length. The total is marked ≈ when a step is a metered estimate. With --json, it prints { totalCredits, stepsCredits, feeCredits, estimate?, durationSec }. On an edition without credits, it says so.
  • --idempotency-key makes a retry with the same key answer the run already started.
  • --style-guide is a style guide for the planner, up to 4,000 characters.

Several cameras. Repeat --media for the cameras of one conversation, in order, and add --master-audio for the mixer track. --wide-camera, --synced and --speaker-camera set the cameras: --speaker-camera 1=2 puts the first voice heard on recording 2, and 0 is the wide shot. Several recordings or a Master audio need Speaker Map: where it is not available to you, the run is refused with 403 node_not_available. Chapters reads one recording only.

edit tighten-episode transcribes the recording, plans the tightened cut and renders it, plus captions, music and framing as set. --music-duck-amount sets how far the music dips under the voice, 0 to 100, default 75. --caption-style sets the look of the captions, default word-highlight. --layout and --framing-source work only with --framing. --framing-source static, the default, splits the frame evenly by speaker. tracking follows faces with Speaker Frames, charged per started block of 1,000 sampled frames, and is refused where Speaker Frames is not available to you. auto follows faces while Speaker Frames is available to you, and splits evenly otherwise.

edit episode-chapters transcribes the recording and plans its chapters. With --watch, the show notes are printed when the run completes: one 0:00 Title line per chapter.

edit episode-trailer cuts a 20 to 40 second trailer, padded to each format of --formats and never cropped. --formats is comma-separated, and the default is 9:16,1:1,4:5. A format listed twice is refused with 400 validation_error before anything is charged. --intro-card plays a short video, 15 seconds at most, first. With --watch, each format's trailer is printed as 9:16 <url>, then any format that could not be rendered.

edit clip-pack cuts --count clips, 1 to 50 and 8 by default, of about --length seconds each, 5 to 180 and 60 by default. By default, each clip is framed for 9:16 with the speakers stacked, and captioned in the karaoke style. --framing none keeps the recording's shape. --switch is the switch at each speaker change: cut, pan, zoom or xfade:<transition>, default pan. --emphasis is how the speaker who is talking is shown: none, or scale, border and dim joined with +, default scale. With --watch, each clip is printed as 1 <url> <title>.

edit speaker-layout frames the whole recording by speaker, with the same length and nothing cut. --aspect is the shape, default 9:16. --layout defaults to stacked, --switch to cut and --framing-source to auto. A --review preview is rendered at full quality with edit continue-use-case, without --edit: the layout has no cut to change.

Every flag's own value is checked before any request. Whether --wide-camera names a recording with picture is the server's check.

edit continue-use-case continues a run as a new job, in one of two modes:

  • from-failed keeps the steps that finished and runs the rest. The fee is held again, because the failed run's fee was refunded.
  • render-final renders the full-quality result after a --review preview, with the preview's settings and no fee. --edit takes the reviewer's edit of the plan, as an EDL file. For a Clip Pack, it lists the clips to keep. A Chapters run renders nothing.

The run is continued on the route of its own node type. --type names the type. Without --type, the CLI reads the job for its type. When the type cannot be read, for example with a token without the jobs:read scope, nothing is sent. The command then exits with code 1 and asks for --type, with the code use_case_type_unknown.

A refusal that names another job prints its code and that job. already_running means follow that job. continuation_superseded means continue that job instead. render_final_already_rendered means its result is the one to use. With --json, the refusal is written to standard output as { "error": { "code", "message" }, "jobId" }, with exit code 1.

nodaro edit tighten-episode --media https://cdn.example.com/episode-12.mp4 --framing 9:16 --estimate
nodaro edit tighten-episode --media https://cdn.example.com/episode-12.mp4 --framing 9:16 --review --watch
nodaro edit continue-use-case <jobId> --mode render-final --watch
nodaro edit episode-chapters --media https://cdn.example.com/episode-12.mp4 --watch

Frequently asked questions

How do I recast several speakers in a video from the CLI?

Run nodaro voice recast with --video and --voices, one voice per speaker in the order they are detected. Write keep for a speaker who keeps the original voice, for example --voices Rachel,keep,Aria.

Which transcription engine gives word timings?

elevenlabs-stt always returns word timings, and incredibly-fast-whisper returns them with --word-timestamps. whisper returns phrase segments only. If you omit --provider, the whisper engine runs, so name an engine whenever you need words.

Do still-to-video and slideshow cost credits?

No. nodaro media still-to-video and nodaro media slideshow render the video without any AI model and cost 0 credits.

How do I caption a video with words I corrected myself?

Transcribe the audio with a word-level engine, edit the words in the saved JSON file, then pass the file to nodaro media add-captions with --captions-file and --no-auto-transcribe.

Which media commands need Nodaro Cloud?

voice analyze and voice export run on Nodaro Cloud only. voice recast, edit plan and edit switch-cameras run on Nodaro Cloud, and a self-hosted install runs them through its connection to Nodaro Cloud.

Last updated on

On this page