Video editing
Trim, join, loop, caption, overlay and assemble video from an AI assistant with Nodaro's editing tools, several of which run without AI and cost no credits.
The video editing tools turn generated clips into a finished video: trim, join, loop and caption them, lay images over them, add or replace their sound, and assemble narrated videos. Most of them render with FFmpeg rather than an AI model, so they are fast, give the same result every time, and cost few or no credits. Every tool needs the workflows:execute permission and returns a job id.
| Tool | What it does | Credits |
|---|---|---|
trim_video | Cuts a clip by time, by frames, or at its cleanest loop point | By length, in 5-second steps |
combine_videos | Joins clips, with transitions or a seamless smart cut | By length, in 5-second steps |
loop_video | Repeats a clip a number of times or to a length | By length, in 5-second steps |
split_media | Cuts a video or audio file into parts between a minimum and a maximum length, or a video into one part per shot | 22, whatever the number of parts |
extract_frame | Takes one frame as an image | 11 |
merge_video_audio | Adds or replaces the sound of a video | 22 |
add_captions | Burns subtitles or word-by-word captions into a video | 33, or 55 for animated or styled captions |
overlay_images | Shows images or video clips over a video at set times | 22 with image layers only; per started 5 seconds of the base with a video layer |
mask_composite | Places one video over another through a mask video | 11 for every started 5 seconds |
still_to_video | Turns one image and one audio track into a video | Free |
slideshow | Turns 2 to 100 images and optional audio into a slideshow | Free |
gif_to_video | Converts an animated GIF to MP4 | Free |
assemble_narrated_video | Fits voice blocks over their clips in one narrated video | 44–143: 3 units, plus one unit for every 6 blocks or part of 6 |
trim_video
Cuts a clip. Choose one of three modes: by time, by frames, or at the cleanest loop point. It works like the Trim Video node.
Permission: workflows:execute. Credits: by the length of the clip it outputs, in steps of 5 seconds, as on the Trim Video node.
| Parameter | Type | Notes |
|---|---|---|
video_url or video_asset_id | string | The source clip. |
start_time, end_time | number | By time: the window to keep, in seconds. end_time must be later than start_time. |
trim_start_frames, trim_end_frames | integer | By frames: frames to drop from the start or the end. They override the times. Useful when exact frames matter, as with VEO 3.1 clips at 24 fps. |
smart_loop_cut | boolean | Finds the last frame that best matches frame 0 and cuts there, for a clean loop. It overrides the other modes. |
smart_loop_cut_lookback | integer | How many final frames to compare, from 2 to 64. Default 16. |
silent | boolean | Removes the sound. Default false. |
Returns: a job id. A smart loop cut reports the chosen frame in output_data.smartLoopCut.
combine_videos
Joins two or more clips into one video, with a transition or a seamless smart cut. It works like the Combine Videos node.
Permission: workflows:execute. Credits: by the estimated length of the output, in steps of 5 seconds, as on the Combine Videos node.
| Parameter | Type | Notes |
|---|---|---|
videos | array | Required. At least 2 clips, each { url } or { asset_id }, in play order. |
transition | string | The transition between clips, such as cut, fade, dissolve, dip-to-black, wipe-left, slide-up, circle-open, pixelize or zoom-in. The tool lists about 50. |
transition_duration | number | From 0 to 5 seconds. |
audio_mode | string | keep, crossfade or remove. |
audio_crossfade_duration | number | A crossfade of the sound only, from 0 to 5 seconds. The picture is not changed. By default it follows transition_duration. |
audio_crossfade_curve | string | With crossfade: linear, equal-power, smooth, logarithmic or exponential. |
smart_cut | boolean | Compares the last frames of each clip with the first frames of the next and cuts where they match. Seamless for clips generated from the previous clip's last frame. Nodaro Cloud only. |
smart_cut_mode | string | best-pair (default), preroll-keep-prev or preroll-keep-next, which decide which side of an overlap is kept. |
smart_cut_frames_prev, smart_cut_frames_next | integer | The search window at the end and at the start of each clip, from 1 to 24 frames. Default 8. |
trim_start_frames, trim_end_frames | integer | The frames cut at each join: from the start of every clip after the first (default 1), and from the end of every clip before the last (default 2). From 0 to 120. Pass them for a frame-exact cut. They are also what a smart cut falls back to. |
Returns: a job id.
loop_video
Repeats a clip a number of times, or until it reaches a length. It works like the Loop Video node.
Permission: workflows:execute. Credits: by the length of the output, in steps of 5 seconds, as on the Loop Video node.
| Parameter | Type | Notes |
|---|---|---|
mode | string | Required. repeat for a number of copies, or duration to loop to a length and trim there. |
video_url or video_asset_id | string | The source clip. |
repeat_count | integer | For repeat: 2 to 20 copies. |
target_duration | number | For duration: the length, from 1 to 300 seconds. |
smart_cut_before_repeat | boolean | Trims the clip to its cleanest loop point before repeating it, so no seam shows at any repeat. Recommended for VEO 3.1 clips made from a first and a last frame. |
smart_cut_lookback | integer | How many final frames to compare, from 2 to 64. Default 16. |
Returns: a job id.
split_media
Cuts a video, an audio file or both into consecutive parts. Every part is between a minimum and a maximum length. It works like the Split into Chunks node.
Permission: workflows:execute. Credits: 22 per run, whatever the number of parts.
| Parameter | Type | Notes |
|---|---|---|
video_url or video_asset_id | string | A video to split. |
audio_url or audio_asset_id | string | An audio file to split. With both a video and an audio file, each is split on its own. |
mode | string | duration (default): parts of at most chunk_duration. shots: one part per shot of the video. Shots mode takes a video only, and does not use chunk_duration, min_part_duration or audio_format. |
chunk_duration | number | The longest a part may be, in seconds. At least 1. Required unless mode is shots. |
min_part_duration | number | The shortest a part may be, in seconds. Default 4, and never above chunk_duration. |
audio_format | string | mp3 (default), wav or aac. An AAC part is saved as an .m4a file. |
A video is cut on whole frames, and each part's sound never runs past its picture. A file can be up to 3 hours long and make at most 200 parts.
Returns: a job id. The parts are in the job's outputData, from get_job or wait_for_job: videoUrls, audioUrls, chunkCount and partDurationsSec. Pass a part URL to another tool as its video_url or audio_url.
With mode: "shots", the cuts are measured from the file, and each part keeps the video's own sound. Videos can be up to 30 minutes long, with at most 200 shots, at the same price. outputData then adds shotCount and shots, each { index, startSec, endSec, durationSec }.
extract_frame
Takes one frame of a video as an image: the first, the last, or the one at a time you choose. Use the last frame of a clip as the first frame of the next one to chain shots. It works like the Extract Frame node.
Permission: workflows:execute. Credits: 11.
| Parameter | Type | Notes |
|---|---|---|
video_url or video_asset_id | string | The source video. |
mode | string | first, last or timestamp. |
time_seconds | number | The time of the frame. Passing it implies timestamp. |
Returns: a job id. The result is an image.
merge_video_audio
Adds sound to a video or replaces it: a voiceover, a soundtrack or a dub. It works like the Merge Video & Audio node.
Permission: workflows:execute. Credits: 22.
| Parameter | Type | Notes |
|---|---|---|
video_url or video_asset_id | string | The video. |
audio_url or audio_asset_id | string | One audio track. |
audio_tracks | array | Several tracks instead, each { url, start_time, volume }: when it starts in the video, in seconds, and its volume from 0 to 200, where 100 is the original. |
voiceover_volume | number | The new audio's volume, from 0 to 200. Default 100. |
keep_original_audio | boolean | Keeps the video's own sound under the new audio. Default true. |
background_volume | number | The volume of the video's own sound, from 0 to 200. Default 30. |
Returns: a job id.
add_captions
Burns captions into a video: one static subtitle block, or animated captions timed word by word. It works like the Add Captions node, which documents every style and option.
Permission: workflows:execute. Credits: 33 for a plain subtitle; 55 for an animated style, or for a subtitle with styling options.
| Style | What it shows |
|---|---|
subtitle (default) | A static block. With text, that text is burned as it is for the whole video and never replaced by a transcript. Without text, the speech is captioned. |
word-highlight, karaoke, bouncy | One line at a time, timed word by word, with the spoken word highlighted |
tiktok-words | Short pages of words. A page never crosses the end of a sentence or a pause, and stays at most 1.5 seconds. |
word-pop | One word at a time. Each word stays until the next one starts, at most 1.5 seconds. |
| Parameter | Type | Notes |
|---|---|---|
video_url or video_asset_id | string | The video. |
style | string | One of the styles above. Default subtitle. |
text | string | On subtitle, the exact text to burn. On an animated style, only a fallback when transcription returns nothing or is off. |
captions | array | Your own timed words, one { text, startMs, endMs } per word, in milliseconds. This is the shape transcribe returns. |
auto_transcribe | boolean | Transcribes the video's speech to time the words. |
transcribe_provider | string | incredibly-fast-whisper (default), elevenlabs-stt or whisper. Animated styles need word timings, so whisper is refused when transcription is their only source. |
look | string | outline (Montserrat 900, uppercase, black outline, yellow spoken word) or clean. Unset, it is outline on animated styles and clean on subtitle. |
font_family, font_size, font_weight, color, uppercase | The type. Rubik, Heebo, Cairo and Tajawal cover Hebrew and Arabic. | |
stroke_color, stroke_width, background_color | The outline and the background box. | |
position, position_y | bottom, top or center, or the block's center as a percent of the height. About 65 sits below a face and above an app's buttons. | |
max_words_per_line | integer | 1 to 20 words per line, or per page of tiktok-words. 1 or 2 gives the punchy social look. Unset fits the width. No effect on word-pop. |
highlight_color, animate | Animated styles only: the color of the spoken word, and false to stop the word motion. | |
segments | array | Different treatments for time ranges of the same video, each with start_ms, end_ms, its own options and optionally its own text. Ranges must not overlap. |
The styling options also work on subtitle, but a styled subtitle bills at the animated price. For your own corrected transcript, map the words from transcribe into captions, one entry per word.
Returns: a job id.
overlay_images
Shows 1 to 20 timed layers over a video, each for a time range: a logo, a product shot, a card, or up to 2 video clips. No AI model runs. It works like the Video Overlay node.
Permission: workflows:execute. Credits: on Nodaro Cloud, 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.
| Parameter | Type | Notes |
|---|---|---|
video_url or video_asset_id | string | The base video, for example a combine_videos result. |
layers | array | Required. 1 to 20 layers, at most 2 of them videos. |
output_aspect | string | Renders onto a 16:9, 9:16, 1:1 or 4:5 canvas instead of the video's own size, with base_fit (cover, the default, or contain) and a background_color. |
base_box | object | Places the base video in the same box units as a layer. anchor and width are required, with optional x, y, height and fit. Needs output_aspect. The uncovered canvas shows background_color. |
layout | string | Places the base, the first video layer or both. See the table below. |
Each layer has exactly one source. An image is url or asset_id, which can be an image_overlay result. A video is video_url or video_asset_id, a video job or upload. A layer with both, or with neither, is refused before anything runs. Each layer also takes these fields:
| Layer field | Notes |
|---|---|
start, end | start is required. The time range in seconds. Without end, the layer stays to the end of the video. |
preset | card (centered, fitted into 78% by 60% of the frame), corner-badge (18% wide, near the corner, bottom right by default) or full-frame. |
anchor, x, y, width, height, fit | An exact box, in the same percent units as image_overlay. A box field overrides the preset. With neither, the layer is a corner badge. |
opacity, animate, z_index | Opacity, a short fade and scale in and out, and the stacking order. animate is on by default for an image and off for a video. |
sound | A video layer only: { volume }, from 0 to 1. The layer's audio is mixed in during its window. |
A video layer plays from its first frame at start. It stops at end or at the end of the base video, and holds its last frame if it runs out first. Only the base video's sound plays, untouched, unless a video layer has sound. That layer's audio is then mixed in under a limiter. sound on an image layer is refused.
layout | Result |
|---|---|
video-bottom, video-top | The whole base video, full width, against that edge. No video layer is needed. |
stack-whole | The whole base video directly above the first video layer, the pair centred |
stack-filled | The base in the top half and the first video layer in the bottom half, both cropped |
pip | The first video layer, 30% of the frame wide, 4% in from its corner |
Every layout except pip needs output_aspect. The stacks and pip need a video layer. A stack refuses base_box. pip and the stacks turn off the fade of the first video layer.
A run with a video layer takes a base video of up to 60 seconds, and each layer video can be up to 200 MB. The base is measured before anything is charged.
Layers past the end of the video are cut or skipped, and an animated image shows its first frame. A video layer with sound but no audio track is drawn silent (layer_no_audio). The job output lists all of these as warnings. A layer id that cannot be found is refused before anything runs, with its position in the list. Pass the result's job id to add_captions as video_asset_id to caption it next.
Returns: a job id.
mask_composite
Places a foreground video over a background video through a mask video, white for the foreground. It can also pixelate or blur the background itself inside the mask. It runs with FFmpeg, without AI. It works like the Mask Composite node.
Permission: workflows:execute. Credits: 11 for every started 5 seconds of the result. The video the result follows can be up to 300 seconds long.
| Parameter | Type | Notes |
|---|---|---|
foreground_url or foreground_asset_id | string | The footage of the subject. The result follows its size, frame rate and length. Not needed with pixelate or blur. |
background_url or background_asset_id | string | The new scene. It loops when it is shorter than the foreground. |
mask_url or mask_asset_id | string | The mask video, white for the foreground, such as a video_mask job. The mask holds its last frame when it is shorter. |
invert_mask | boolean | Swaps which side of the mask shows the foreground. |
feather | integer | Softens the edge, from 0 to 20 pixels. Default 2. |
grow | integer | Grows or shrinks the foreground, from -10 to 10 pixels. A negative value trims halos. Default 0. |
opacity | number | How strongly the fill covers the background inside the mask, from 0 to 1. Default 1. |
fill | string | What fills the mask: video (default, the foreground), pixelate or blur. pixelate and blur use the background itself and take no foreground. The result then follows, and is priced on, the background, and always has the background's sound. |
pixel_size_pct | number | pixelate only. The block size, from 0.2 to 10 % of the width. Default 1.25. |
blur_strength_pct | number | blur only. The blur strength, from 0.1 to 5 % of the width. Default 2. |
background_fit | string | cover (default), contain or stretch. |
audio_source | string | foreground (default), background, mix or none. Ignored with pixelate or blur. |
Returns: a job id.
still_to_video
Turns one image and one audio track into a video, rendered locally without an AI model. The video lasts exactly as long as the audio. Use it for narrated slides, a cover art video for a song, or a still moment inside a longer edit. For AI motion, use animate_image. It works like the Still to Video node.
Permission: workflows:execute. Credits: free.
| Parameter | Type | Notes |
|---|---|---|
image_url or image_asset_id | string | The image. |
audio_url or audio_asset_id | string | The audio, which sets the length. |
motion | string | none (default), zoom-in, zoom-out, pan-left, pan-right or ken-burns. |
intensity | integer | The motion strength, from 1 to 10. Default 3. |
resolution | string | 720p, 1080p (default) or 4K. 4K with motion is slower. |
aspect_ratio | string | 16:9 (default), 9:16, 1:1 or 4:3. |
fps | integer | 24 or 30 (default). |
fit, pad_color | string | cover (default, crops to fill) or contain (adds bars in pad_color, black by default). |
Returns: a job id.
slideshow
Turns 2 to 100 images and one optional audio track into a slideshow video, rendered locally without an AI model. It works like the Slideshow node.
Permission: workflows:execute. Credits: free.
| Parameter | Type | Notes |
|---|---|---|
image_urls or image_asset_ids | array | 2 to 100 images, in order. |
audio_url or audio_asset_id | string | Optional. With audio, the video lasts exactly as long as the audio, and the slides share it equally. |
image_durations | array | Seconds for each slide, or null for automatic. With audio, totals that do not match are scaled to fit, and the job output says by how much. |
per_image_duration | number | Without audio: seconds per slide, from 0.5 to 60. Default 3. |
transition, transition_duration | A transition such as cut, fade, dissolve, dip-to-black or wipe-left, and its length up to 5 seconds. An unknown transition falls back to cut. | |
motion, intensity | none, zoom-in, zoom-out, ken-burns or alternate, which switches the zoom on every slide, with a strength from 1 to 10. | |
resolution, aspect_ratio, fps, fit, pad_color | As on still_to_video. |
For one image, use still_to_video. For AI motion between images, use animate_image.
Returns: a job id.
gif_to_video
Converts an animated GIF into an H.264 MP4, rendered locally without an AI model. Use it to pass a GIF as a motion reference to a video model that does not accept GIFs, such as Seedance. It works like the Gif to Video node.
Permission: workflows:execute. Credits: free.
| Parameter | Type | Notes |
|---|---|---|
gif_url or gif_asset_id | string | The GIF. |
loop_to_minimum | boolean | Loops a short GIF up to target_duration. Default true. A GIF that does not loop cleanly plays forward and backward instead, so no jump appears. |
target_duration | number | The loop length, from 2 to 8 seconds. Default 3. |
interpolate | boolean | Adds frames for smooth 24 fps motion. Default true. false keeps the GIF's original timing. |
alpha_background | string | The background of a transparent GIF: white (default) or black. |
Returns: a job id. A GIF with one frame becomes a short still clip.
assemble_narrated_video
Fits ordered blocks of a clip and a voice into one narrated video. When a voice is shorter than its clip, it is centered with silence around it. When it is longer, the clip slows down to fit, up to a limit, and then holds its last frame. The voice is never cut. It works like the Assemble Narrated Video node.
Permission: workflows:execute. Credits: 44–143, by the number of blocks: 3 units, plus one unit for every 6 blocks or part of 6, as on the Assemble Narrated Video node.
| Parameter | Type | Notes |
|---|---|---|
blocks | array | Required. 1 to 60 blocks in play order, each with a video (video_url or video_asset_id) and an optional voice (audio_url or audio_asset_id). The clips must contain no dialogue. |
voice_volume | number | The voice's loudness in percent, from 0 to 200. Default 100. |
clip_audio_volume | number | The clips' own sound under the voice, from 0 to 200. Default 40. |
max_slowdown | number | How much a clip may slow down for a long voice, from 1 to 2. Default 1.5. |
trim_start_frames, trim_end_frames | integer | Frames trimmed from the start of every block after the first, and from the end of every block before the last, for seamless joins. Up to 120. Default 0. |
Returns: a job id. The video-explainer recipe finishes with this tool; see Content recipes.
Frequently asked questions
Which Nodaro video editing tools are free?
still_to_video, gif_to_video and slideshow cost no credits, because they render locally without an AI model. The other editing tools cost a few credits. Trim, combine and loop are priced by the length of the output, assemble_narrated_video by its number of blocks, and the rest have a fixed price, such as 22 to add or replace the sound.
How do I add TikTok-style captions to a video?
Call add_captions with a kinetic style such as word-highlight or tiktok-words. Leave auto_transcribe on, and Nodaro transcribes the speech and times each word. An unset look renders bold uppercase words with the spoken word in yellow.
How do I put a logo on a video?
Call overlay_images with the video and a layer that holds the logo. Without a placement, the layer becomes a corner badge in the bottom right. Set start and end to show it only for part of the video.
How do I join clips without a visible jump?
Use combine_videos with smart_cut set to true. It compares the last frames of each clip with the first frames of the next and cuts where they match best, which suits clips generated from each other's last frame.
Related
Video
Add Captions
Combine Videos
Analysis and edit lists
Content recipes
Last updated on
Video
Generate video from text or an image, extend, restyle, relight and upscale clips, and make faces talk or move with Nodaro's video tools for AI assistants.
Analysis and edit lists
Analyze a video scene by scene, find shots and silences, sync cameras, render edit decision lists, and cut podcasts into episodes, clips and trailers.