var2_join_videos
Stitch videos / images / audio into one mp4 on a 30fps timeline. Fractional seconds are supported and rounded to frames, not whole seconds; the plan returns timeline_frames and fps. For a VERIFIED duplicated shared endpoint between 30fps clips, shorten the preceding clip by exactly 1/30 second, preserve the next first frame, and use no transition. A shared reference image does not prove actual endpoints match or eliminate duplicate frames; this tool does not extract or compare frames. Never replace one-frame removal with an arbitrary 0.2–0.5 second trim. Continuous background audio spans the joined timeline. Two-pass: dry_run=true (default) returns a plan to review with the user; dry_run=false renders it. Poll with var2_check_join_status (NOT var2_get_video_result).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional project name shown in the user's editor. | |
| dry_run | No | When true (default), returns the planned timeline + render-time estimate WITHOUT actually queuing the render, plus a `plan_id`. ALWAYS call with dry_run=true first, show the plan to the user, get explicit approval, then render by calling with ONLY {plan_id} — no other parameters needed. Renders take minutes-to-hours and use compute budget — never run without confirmation. | |
| plan_id | No | Render an approved plan exactly as shown: after user approval, call with ONLY {plan_id} — nothing else needed (dry_run defaults to render when plan_id is present). A jp_… id ALWAYS comes back HERE to START the render — it is a plan id, NOT a status id (status ids are plain UUIDs and go to var2_check_join_status). {plan_id, dry_run:true} re-displays the stored plan. If any parameter changed after the dry-run, resend full args instead. | |
| segments | Yes | Ordered list of clips on the timeline. ALWAYS ask the user about the order before calling — the order matters and cannot be changed after rendering starts. | |
| resolution | Yes | REQUIRED — always ask the user. 1080p renders roughly 2× longer than 720p but produces a sharper output. | |
| aspect_ratio | Yes | REQUIRED — always ask the user which one they want. 16:9 = landscape (YouTube/desktop), 9:16 = portrait (TikTok/Reels/Shorts), 1:1 = square (Instagram feed). | |
| background_audio_url | No | Optional separate audio track that spans the whole video (storage/signed URL, var2 share link, or placeholder_id — resolved server-side). Ask the user if they want background music. | |
| background_audio_volume | No | ||
| video_audio_when_stacked | No | How to handle the video's native audio when an audio source is layered on top (inline audio segments OR background_audio_url). When the timeline stacks video + audio, ALWAYS ask the user — and recommend `mute` as the first option (cleanest result, no clashing tracks). `reduce` keeps video audio at 0.2× under the music. `keep` plays both at full volume (usually clashes). | |
| background_audio_placeholder_id | No | STRONGLY RECOMMENDED whenever `background_audio_url` is set. The placeholder_id of the asset behind that URL (e.g. the id returned by var2_upload_asset). Without it the editor opens the saved project with an empty background-audio clip — no waveform, no playback in preview — even though the rendered mp4 mixes the audio correctly. The server auto-extracts var2 UUIDs from var2.ai share-page URLs and Supabase storage paths when possible. |