# invideo Documentation > invideo makes and edits video on a real timeline, for people and for the AI agents they use (Claude, ChatGPT, Cursor, Codex and others, through invideo MCP or the invideo CLI). These docs have one page per video task, in the words people use to ask for it, plus setup, reference, comparisons and the invideo help center. ### Quick start Source: https://docs.invideo.io/agents.md Connect your agent to invideo to generate video, images, voice and music with the leading models and edit them on a real timeline. Setup lines for every client, the work loop and the rules. invideo puts the leading video, image, voice and music models next to a professional timeline editor, in the cloud. Your agent generates the shots, voices and music a project lacks, cuts them with your own footage, and exports the result, all in one project. Agents and people work in the same project, and you watch every edit land live in the browser. Agents with a terminal use the invideo plugin and the CLI. The plugin installs the skills, and the agent installs the CLI, one binary with no sudo, on the first video job. In Cursor, add the skills with `npx skills add invideoio/skills`. The Cursor Marketplace plugin is the MCP route in Cursor, and it carries the MCP server only. Agents without a shell use the MCP server at `https://mcp.invideo.io/mcp`. ```bash claude plugin marketplace add invideoio/skills claude plugin install invideo@invideo ``` ```bash codex plugin marketplace add invideoio/skills codex plugin add invideo@invideo ``` ```bash agy plugin install https://github.com/invideoio/skills ``` ```bash npx skills add invideoio/skills ``` ```bash npx skills add invideoio/skills ``` ```bash curl -fsSL https://agents.invideo.io | sh ``` ```powershell irm https://raw.githubusercontent.com/invideoio/cli/main/install.ps1 | iex ``` A chat app, or an agent with no shell, uses MCP. In ChatGPT, the person installs the official invideo plugin: **Customize**, then **Plugins**. In Claude on the web or desktop, the person adds invideo as a connector: **Customize**, then **Connectors**. In the Gemini app, the person adds invideo as a custom app with the server URL: **Settings**, then **Connected Apps**. Antigravity, Claude Code and Codex use the CLI only. Cursor uses the CLI first, and its Marketplace plugin is the MCP route. Gemini CLI and VS Code have no invideo plugin, so they take the MCP server with the lines below. ```bash code --add-mcp \ '{"name":"invideo","type":"http","url":"https://mcp.invideo.io/mcp"}' ``` ```bash gemini mcp add --transport http --scope user invideo \ https://mcp.invideo.io/mcp ``` ```json { "mcpServers": { "invideo": { "url": "https://mcp.invideo.io/mcp" } } } ``` Each start page below has the full steps. If you are the agent reading this, run the setup yourself. Installing the plugin, the CLI or the server changes the person's machine, so ask once ("Should I add invideo to your Claude Code?") and do it on a yes. Give the person a command to run only when nothing you can do works. #### Start pages Each client has its own page with the setup, the sign-in, a first prompt and the known failures. - [Set up invideo in Claude Code](/start/claude-code) - [Set up invideo in Codex](/start/codex) - [Set up invideo in Cursor](/start/cursor) - [Set up invideo in Antigravity](/start/antigravity) - [Use invideo in ChatGPT](/start/chatgpt) - [Use invideo in Gemini](/start/gemini) - [Make a video with invideo without a terminal](/start/no-terminal) The plugin for Claude Code, Codex and Antigravity, and the skills command for Cursor, install the invideo skills, and the skills are CLI-first: the agent installs the CLI and signs in on the first job. The plugin carries no MCP config. ChatGPT uses the official invideo plugin. The Gemini app takes invideo as a custom app, Claude on the web as a connector, and Gemini CLI and VS Code as an MCP server. None of them gets the skills. #### CLI or MCP Both reach the same projects, the same timelines and the same account. Pick one per session and stay on it. Mixing them in one session splits your state and your name in the project. - **Use the CLI** in a terminal agent with the invideo plugin (Claude Code, Codex, Cursor, Antigravity), and in a script or a server. It is the only way in that the start pages give for those agents, and the way the skills teach. Each command prints the URLs and the next step. Add `--json` to get one JSON object. `--out ` saves files on `invideo notebook show` and `invideo edit capture`; `invideo status` follows a job and saves nothing. - **Use MCP** in a chat app (Claude on the web, ChatGPT, the Gemini app), in VS Code or Gemini CLI, which have no invideo plugin, or in any agent with no shell. You call tools like `read` and `edit_timeline` and pass a URL as `url`. Gemini CLI has a shell, so it can also use the CLI instead; see [Use invideo in Gemini](/start/gemini). Check the CLI install with this command. It prints `invideo` and the version. ```bash invideo --version ``` #### Sign in There are no API keys. Every call runs as a signed-in person, in the workspaces they chose when they signed in. - **CLI.** Run `invideo auth login` in the background or with a long timeout. It opens the browser and waits. Tell the person in one message that a sign-in tab opened. - **MCP in a chat app.** Claude on the web, ChatGPT and the Gemini app run the browser sign-in themselves when the server asks. - **MCP in VS Code, Gemini CLI or another client.** The client runs the browser sign-in when the server asks, or has its own authenticate step. In Gemini CLI that step is `/mcp auth invideo`. Signing in the invideo CLI does not sign in an MCP connection. Never run a login command that needs an interactive terminal from the agent's shell. - **No browser.** On ssh, in a container or on a cloud machine, use a device code. ```bash INVIDEO_NO_BROWSER=1 invideo auth login invideo auth status ``` The first command prints a link and a code at once, then waits for approval. Send the person the link and the code in one message. They open the link on their own device and approve. `invideo auth status` shows who is signed in. The device code above signs in the CLI only. An MCP client with no browser uses its own device flow over HTTP. The steps are on [Sign in, device codes and sessions](/account/sign-in). Never ask the person for a password, an email code, or the device code back. One sign-in at a time: while a code is pending, do not request another. #### The work loop Every job follows the same loop. Call `get_help` once for the full guide, or `get_help` with a `topic` for one section. Find the project with `list_projects`, or make one with `new_project`. Call `read` on its URL to see pages, threads and sequences. In a project, call `register` once and pass your name as `as` on every call there. You see the project URL and its notebook. Add files with `add_media`. For a local file, call `start_upload`, PUT the bytes to the `upload_url`, then call `add_media` with the `upload_id`. In Claude on the web or the desktop app, the PUT goes from Claude's sandbox to the `upload_url` on m.invideo.io. If that PUT cannot reach m.invideo.io (the host does not resolve, the connection is refused, or the sandbox network blocks it), do not describe the files in text instead, and do not ask the person to send them again. Tell the person to allow m.invideo.io in Claude under **Settings**, then **Capabilities**, then **Allowed websites** (the steps are on [How do I let Claude upload my files to invideo?](/ai-agents/how-do-i-let-claude-upload-my-files-to-invideo)), and retry in a new chat once they have. Find stock with `search_library`. You see a sequence URL for each file. For a shot, an image, a voice, music or a sound that nobody has, find a model with `find_models` and the job in words, read its inputs with `get_model`, then call `generate` with `dry_run: true` to price it. Follow the cost rule below, then call `generate` again with `max_credits` and an `idempotency_key`. Media inputs are sequence URLs from this project. You see a thread URL at once and a sequence URL when the result lands; `read` it, do not call `generate` again to check. Make a timeline with `new_timeline`. Create a branch with `timeline_history` unless the person asks you to edit main. Read with `get_timeline`, look up fields with `timeline_catalog`, then send `edit_timeline` with the latest `expected_state_token`. You see a new `state_token`. Look before you say done. Call `capture` at the moments that matter, `check_timeline` for structure, and `media` with `video.frames` or `audio.loudness` for a source. You see frames and findings. Fix what is wrong and look again. Call `export` with the timeline URL and a `format`, and an `idempotency_key`. `video` renders a 1080p MP4. `premiere`, `davinci` and `final_cut` make a project file that Premiere Pro, DaVinci Resolve or Final Cut Pro opens. You see an export card URL. `read` it until its status is `completed`. For `premiere`, `final_cut` and `davinci`, read it again until the files list is there; `completed` can come before the media package. Tell the person what changed, with timecodes and URLs. Each URL opens exactly that thing in invideo. The same loop on the CLI. The CLI calls a timeline an edit: `invideo edit new` makes a timeline, and the `` it prints is the timeline's URL. ```bash invideo project new --title "Launch teaser" invideo agent register --name scout export INVIDEO_AS=scout invideo asset upload ./shots/*.mp4 invideo notebook new-page --title "Shots" invideo gen models --query "cinematic product shot" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ -i prompt="slow push on the bottle, studio light" invideo gen run --model seedance_2_5.r2v \ --max-credits --idempotency-key teaser-shot-1 \ -i prompt="slow push on the bottle, studio light" invideo edit new --name "Teaser v1" invideo edit show --json invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit check invideo edit capture --at 1,3.5 --out ./frames invideo edit export --format video --quality 1080 \ --idempotency-key teaser-export-1 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` comes from `invideo project new`. `INVIDEO_AS` passes your registered name on every later command, like `--as`. - `` comes from `invideo notebook new-page`. A generation on a page starts a new thread there. - `` is the `estimated_credits` in the dry run's answer. Pass the same `-i` inputs on the dry run and the paid run. - `` comes from `invideo edit new`. `` comes from `invideo edit show`, and each `edit change` returns a fresh one. - `ops.json` holds a bare JSON list of operations, `[ {...}, {...} ]`, with no `operations` wrapper. - `` is `.sequences[0]` in the export's answer. `invideo status` waits for the job and saves nothing. `invideo notebook show` with `--out` saves the file as `export.mp4`; rename it after. #### The cost rule Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent follows these rules on every paid call. - On MCP, call `generate` with `dry_run: true` before the first paid call. It checks the inputs and returns the price. Then call it with `max_credits` set, so nothing starts above that price. - Paid `media` ops, like `audio.transcript` and `video.upscale`, take the same `dry_run` and `max_credits`. - On the CLI, use `--dry-run` first, then `--max-credits`. - Pass an `idempotency_key` on every `generate` and `export`. A retry after a timeout then finds the first job instead of paying twice. - Models retire. A retired model is refused as not found. Run `find_models` with the job in words, use the best match, run the dry run again, and tell the person which model you used. Prices and the balance are on [Credits and what they cost](/account/credits). For a question about plans, prices or credits, read the credits FAQ and its sibling pages, not only the pricing page. #### Check before you say done Never tell the person a video is done without looking at it. Call `capture` on the timeline, read the frames, and call `check_timeline`. On the CLI, run `invideo edit capture` and `invideo edit check`. `check_timeline` reports structure only. It does not judge the cut, so you still look at the frames. #### Conventions These are the places where agents guess wrong. The left column is the usual guess. The right column is what invideo does. | You'd guess | invideo uses | | --- | --- | | An id or a name points to a project | A URL is the handle. Every tool takes a URL as `url` and every result gives the next URLs. | | Calls are anonymous | `register` a name in the project, then pass it as `as` on every call. | | Each operation lands on its own | An `edit_timeline` call lands all its operations or none. | | After a timeout, read again and resend | Retry the identical request with the same `expected_state_token`. A conflict means it landed. | | Decide the next call yourself | Follow `next` in every result. It names the tools and URLs to use. | | Call `generate` again to check on it | `read` the URL or call `status`. `retry_after_s` says when to look again. | | A model id from a page or a saved prompt is forever | Models retire. A retired model is refused as not found. Run `find_models` with the job in words, use the best match, and tell the person. | | Edit the main timeline | Create a branch with `timeline_history`. Edit main only when asked. | | Mix the CLI and MCP | Pick one per session. The skills teach the CLI wherever there is a shell. | | Ask the person for the sign-in code | Send the link and the code once. Never ask for them back. | | Say done after the last edit | `capture` and `check_timeline` first. | #### If something goes wrong Read the refusal. A refused call returns `status`, `code` and `message`. The `message` says how to fix it once. | Symptom | Fix | | --- | --- | | invideo's tools do not appear in the client. | Finish the sign-in, then restart the client. In a chat app, turn invideo on for the chat. Then follow your start page again. | | Refusal `code` `unavailable` | The timeline is starting. Retry the same request in a few seconds. | | Refusal `code` `timeout` on a read, capture or `media` look | Nothing changed. Read again. | | Refusal `status` `completion_unknown` | Retry the identical request with the same token. | | Refusal `code` `failed` | Try once more. If it fails again, file `report_bug` and tell the person. | | Job `status` `needs_confirmation` | Only the person can confirm it, in invideo. Tell them. | | CLI exit code 4 | Not signed in. Run `invideo auth login`. | | CLI exit code 3 | The timeline changed since your read. Run `invideo edit show` and rebuild. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | The same refusal comes back | Stop, tell the person, and file `report_bug`. | File `request_feature` when the person asks for something these tools cannot do, and say what you did instead. If invideo still does not connect, tell the person this: Contact support from the chat button on the invideo site, or email support@invideo.io. Include the client's name, the exact error and a screenshot of the connection status. #### How-to guides for every job These pages cover habits that apply to every job. - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) #### Reference - [MCP tools](/reference/mcp-tools) - [CLI commands and flags](/reference/cli) - [Exit codes](/reference/exit-codes) - [Sign in, device codes and sessions](/account/sign-in) - [Is there an invideo API?](/api) ### Know the cost first Source: https://docs.invideo.io/how-to/cost-before-you-spend.md Your agent prices every paid call with a dry run, caps it with max_credits, and tells you the price before it spends. Your agent knows the price of a generation, a transcript or an upscale before it starts one. It runs a dry run, which prices the call and spends nothing. Then it runs the real call with a cap, so nothing starts above the price you agreed to. A retry after a timeout does not pay twice. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. For prices, see [Credits](/account/credits). Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this rule once, at the start of the session: ```text Before any call that costs credits, run it with dry_run and tell me the price. Pass max_credits and an idempotency_key on every paid call. Wait for my yes before you spend. ``` In a chat app, your agent shows you the price in the chat. In a terminal, it prints the dry run answer, then runs the real command with `--max-credits`. #### How it works Three fields control spending. They work the same on `generate` and on the `media` ops that cost credits. - **`dry_run`** checks the inputs and returns the price. Nothing starts and nothing is spent. - **`max_credits`** is the most a call may cost. Nothing starts when the price is higher. `generate` needs it on every call that is not a dry run. A `media` op needs it when the op costs anything. - **`idempotency_key`** is any text unique to one call, like a UUID. A retry with the same key finds the first call's result instead of paying twice. Credit prices by model are on the video, image and audio pricing pages. The dry run is the price of one specific call. Some prices are estimates. When `pricing` says the price is an estimate, the final charge can end above it. ##### What costs credits and what is free Most of the work on a timeline is free. The paid calls are generation, transcripts, the model ops in `media`, and stock. | Free | Costs credits | | --- | --- | | Every `edit_timeline` change | `generate` with any model | | `export`, in every format | `media` `audio.transcript`, on the call that starts it | | `capture`, `check_timeline`, `get_timeline` | `media` model ops: `audio.separate`, `audio.clean`, `video.upscale`, `image.upscale`, `video.removeBackground`, `image.removeBackground` | | `media` reads: `metadata`, `video.frames`, `audio.waveform`, `audio.loudness`, `audio.content`, `audio.beats` and the other audio reads | `add_media` with `stock`, at the cost the search result shows | | `find_models`, `get_model`, `search_library` | | `document.pages` and the `media` tool ops that make a file without a model, like `video.trim`, `video.loop` and `image.crop`, can show a charge. The dry run shows its price before anything starts. A transcript charges once. Your agent calls `audio.transcript` again with the same file to follow it, and later calls spend nothing. Stock has no dry run. `search_library` shows each result's `cost`, and searching and looking are free. Your agent tells you the cost before it adds a paid stock item with `add_media`. ##### Check, then preview, then render Spend credits last. Work in this order: 1. **Check.** Run the dry run. It checks the inputs and gives the price for free. 2. **Preview.** Look before you pay for the full thing. On a timeline, `capture` shows frames for free. For a generation, try a short or low resolution take first, where the model's inputs allow it. `get_model` lists the inputs. 3. **Render.** Run the full call with `max_credits` and an `idempotency_key`. #### Steps The agent follows these steps for every paid call. The agent runs `find_models` with the job in words and picks a model. A good pick for a video shot is `seedance_2_5.r2v`. It runs `get_model` for the model's inputs, then calls `generate` with `dry_run: true`. Expected result: a price and no new sequence. The agent tells you the price in credits, and says when it is an estimate. It follows the rule at the top of this page. Expected result: your yes, or a change to the request. The agent calls `generate` with `max_credits` at the agreed price and a new `idempotency_key`. Expected result: a thread URL at once. The agent follows the job with `status` or `read`, at the time `retry_after_s` gives. Expected result: status `completed`. The agent never calls `generate` again to check on a job. When the status is `needs_confirmation`, only you can confirm it, in invideo. When it is `held`, a safety review is running and the job is not over. Expected result: the agent tells you and waits. The same flow from a terminal: ```bash invideo gen models --query "slow product shot" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ -i prompt="slow push on the bottle" invideo gen run --model seedance_2_5.r2v \ --max-credits --idempotency-key bottle-push-1 \ -i prompt="slow push on the bottle" invideo status --wait ``` Where each value comes from: `` from `invideo project new`, and `` from `invideo notebook show `, which lists the notebook pages. `` is the price the person agreed to, from the dry run's `.estimated_credits`. `` is the `url` the paid run returns. A retry uses the same key, so it finds the first run. A `media` op that costs takes the same flags: ```bash invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo media video.upscale --dry-run ``` `` is the file's sequence URL, from `add_media` or `invideo asset upload`. Ops that cost or make a file refuse a media bin id with `--asset`. The key MCP call is the arguments of `generate` for a dry run. `` is a notebook page from `read` on the project. ```json { "url": "", "model": "seedance_2_5.r2v", "inputs": { "prompt": "slow push on the bottle" }, "dry_run": true } ``` Your agent checks the credits you have left with `current_user`. In a terminal, `invideo auth status` shows them. #### If something goes wrong Most cost problems come from a retry without a key, or a cap that is too low. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Refused because the price is above `max_credits` | Nothing started. Tell the person the new price, then run again with a new cap. | | CLI exit 5, a limit: credits or quota | Stop and tell the person. Credits are listed in [Credits](/account/credits). | | CLI exit 8, needs the person's confirmation | Stop. The person confirms it in invideo. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | Status `needs_confirmation` | Only the person can confirm it, in invideo. Tell them and wait. | | The dry run refuses an input | Fix the input the `message` names, and run the dry run again. | | A call returns `completion_unknown`, or times out | Retry the same call with the same `idempotency_key`. It finds the first call. | | The final charge is above the dry run price | The price was an estimate. Say so before the next estimated call. | | Avoid: calling `generate` again to check on a job | Instead: `read` or `status` the thread URL. | | Avoid: a retry with a new `idempotency_key` | Instead: retry with the same key, so it does not pay twice. | | Avoid: spending first and telling the person after | Instead: dry run, tell the price, then spend. | #### Related - [Credits](/account/credits) - [Check your video before you say it is done](/how-to/check-your-video) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [Models reference](/reference/models) - [Exit codes](/reference/exit-codes) ### Check your video Source: https://docs.invideo.io/how-to/check-your-video.md Your agent looks at frames and listens to the sound before it reports done, then exports a video that has no cropped faces or silent clips. Your agent checks the video before it tells you the video is done. It looks at frames of the timeline, listens to the sound of each clip, and checks the timeline's structure. Then it exports. A cut that "should be fine" often has a cropped face, a caption off the edge of a phone, or a clip with no sound. Use invideo for this when your agent edits on a timeline: it can render the timeline as it looks now and read every source file's sound, for free, before the export. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then add this line to any edit request: ```text Before you say it is done, capture frames across the timeline, check the sound of every clip, run check_timeline, and tell me what you found. ``` In a chat app, your agent shows you the frames it captured. In a terminal, it saves them to a folder with `--out`, and you open the folder. #### How it works Three tools do the checking. None of them changes the timeline. `capture`, `check_timeline` and the `media` reads cost no credits. - **`capture` looks at the timeline.** It renders frames of the timeline as it looks now, with every layer, effect and text, at the times in seconds you list in `at_seconds`. In the CLI it is `invideo edit capture` with `--at`. - **`media` looks at and listens to one source file.** `video.frames` gives frames of the file. `metadata` gives its streams and duration. `audio.waveform` gives its levels, `audio.loudness` its integrated loudness, true peak and range, and `audio.content` where its sound is speech, music, effects or silence. `video.contactSheet` makes one image of frames across a video, in a grid. - **`check_timeline` checks the structure.** It finds problems like a clip that points at something deleted, or a clip that ends before it starts. Each finding says what is wrong and how to fix it. In the CLI it is `invideo edit check`. `check_timeline` does not judge the edit. A timeline can pass the check and still look wrong. That is why the agent also looks and listens. The `media` sound reads work on one file, not on the live timeline. The agent checks each clip's source before the export, sets the loudness of the mix with `target_lufs` on `export`, then runs `audio.loudness` on the export card's URL to confirm the final mix. The card is a sequence, so `media` takes it as it is. #### Steps The agent runs this checklist after the last edit and before the export. It fixes what it finds, then runs the checklist again. The agent runs `check_timeline` on the timeline URL. It fixes each finding with `edit_timeline`, as the finding says. Expected result: no findings. The agent runs `capture` at `0` and at one frame before the end. Ranges are half-open, so the end time itself is past the last frame. Expected result: two frames that open and close the video the way you asked, with no black frame and no stray clip. The agent picks times at each cut, each text, and each caption, and runs `capture` with them. It looks for faces cut off at the edge, heads cut at the top, and text near the frame edge. Expected result: every face in frame. The agent looks at each captured frame with text as a person sees it on a phone. Text that is thin, small, or low in contrast fails this check. Expected result: you can read every line at a glance. The agent runs `media` with `metadata` on each source that should have sound, and checks it has an audio stream. Then it runs `audio.content` to see where the sound is speech, music, effects or silence. Expected result: sound on every clip that needs it, and silence only where you want a pause. The agent runs `audio.loudness` on the voice and music sources, and `audio.waveform` where it needs the shape of the sound. It compares them with the target loudness for the platform. Expected result: every source in range. For the final mix, the agent sets `target_lufs` on the export to the platform's target. The agent tells you what it checked, what it fixed, and what needs your eye, with timecodes and the timeline URL. Then it runs `export`. Expected result: an export card with status `completed`. The same checklist from a terminal: ```bash invideo edit check invideo edit capture --at 0,4.5,9,14.9 --out ./frames invideo media metadata invideo media audio.content invideo media audio.loudness invideo media audio.waveform invideo media video.frames --at 0,2,4 --out ./frames invideo edit export --format video --quality 1080 ``` Where each value comes from: `` from `invideo edit new`, and `` from the URL `invideo asset upload` or `add_media` returns. For a read of a file in an edit's media bin, like `metadata` or `audio.loudness`, pass the edit's URL and `--asset` with the bin id from `invideo edit show`. Ops that make a file, like `video.contactSheet`, refuse `--asset`; pass the sequence URL. The key MCP call is `capture`, with frames at the cuts and the last frame. `` is the timeline's URL, from `new_timeline` or `invideo edit new`. ```json { "url": "", "at_seconds": [0, 4.5, 9, 14.9] } ``` To see a whole source video in one image, the agent runs `media` with `video.contactSheet`. It needs all four of `columns`, `rows`, `resolution` and `style`, and `style` is `labeled` or `plain`. It takes the file's sequence URL, and it makes a new image beside the file. It is a tool op; the dry run shows its price before anything starts. Like every op that makes a file, it still takes `dry_run` and `idempotency_key`. #### What to check This list is the minimum. Add your own checks to the project's rules in `invideo_rules.md`, and your agent reads them before it works. | Check | Tool | Pass | | --- | --- | --- | | Structure | `check_timeline` | No findings | | First and last frame | `capture` | Opens and closes as asked | | Faces | `capture` | No face cut at an edge | | Text | `capture` | Readable on a phone | | Sound on each clip | `metadata`, `audio.content` | Sound where it is needed | | Silence | `audio.content` | Silence only where planned | | Loudness | `audio.loudness`, `audio.waveform` | In range for the platform | #### If something goes wrong Most problems come from a stale read or from saying done too early. | Symptom | Fix | | --- | --- | | `capture` returns `timeout` | Nothing changed. Run the same `capture` again. | | `capture` returns `unavailable` | The timeline is starting. Retry the same call in a few seconds. | | `check_timeline` is refused with an old `expected_state_token` | The timeline changed since that read. Read it again with `get_timeline`, then check again. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` again. | | CLI exit 7 | Nothing ran. Run the same command again. | | A finding comes back after the fix | Read the timeline again with `get_timeline`, fix it once more, and tell the person if it stays. | | A face is cropped in a capture | Move or zoom the clip with `set_position` or `set_zoom`, then capture again. | | Text is hard to read at phone size | Change the text with `set_text_style`, then capture again. | | A clip is silent | Check that its sound is on the timeline and not muted. | | The export card status is `failed` | Read the card for the reason, and tell the person. | | A frame looks wrong after a fix | Capture again. A capture is tied to a revision, so an old capture shows the old edit. | | The export is too loud or too quiet | Export again with `target_lufs` set to the platform's target. | | Avoid: saying done after `check_timeline` alone | Instead: capture frames and read the sound too. The check does not judge the edit. | | Avoid: checking the sound of the export only | Instead: check each source with `media`, so you know which clip to fix. | #### Related - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) - [MCP tools reference](/reference/mcp-tools) - [Export loudness, track volume and peak level](/guides/how-is-export-loudness-different-from-track-volume-and-peak-level) ### CI and servers Source: https://docs.invideo.io/how-to/ci-and-servers.md Sign in once with a device code, then run the invideo CLI from a script with JSON answers, capped spending, safe retries and a file on disk. You can run invideo from a CI job, a cron script or a server with no browser. A person signs in once with a device code. After that, the script makes projects, uploads files, generates with a cap, exports, and saves the result to disk. Every answer is JSON, and every failure has an exit code your script can act on. There are no API keys. Every command runs as a signed-in person, in their workspace. #### How it works The CLI is one binary, and the same commands work in a terminal and in a script. Six things make it fit for a pipeline. - **Device sign-in.** `INVIDEO_NO_BROWSER=1 invideo auth login` prints a link and a code, then waits until a person approves on their own device. The CLI keeps the sign-in on this machine. `invideo auth logout` forgets it. - **A name in the project.** `invideo agent register` takes a name in a project, like `ci-render`. Set it once as `INVIDEO_AS`, or pass `--as` on every command. People watching the project see who did what. - **JSON answers.** `--json` prints the whole answer as one JSON object, with `next` included. `INVIDEO_JSON=1` does that on every command. Errors and notices always go to stderr. - **Waiting.** A command that starts a job returns the URL to follow at once. `invideo status --wait` checks back until the job is over. `--timeout ` stops waiting after that many seconds. `invideo status` saves no file. `invideo notebook show --out ` saves what an export made, with the card's URL from the export answer's `.sequences[0]`. - **Exit codes.** Each failure has its own code, so the script knows when to retry and when to stop and tell a person. - **Safe retries and caps.** `--idempotency-key` on `invideo gen run` and `invideo edit export` makes a retry find the first job. `--max-credits` on `invideo gen run` stops a generation that costs more than the cap. ##### Sign in on a machine with no browser A person signs in once, on the machine that runs the jobs. Run this in the background, because it waits for the approval: ```bash INVIDEO_NO_BROWSER=1 invideo auth login ``` It prints a link and a code at once. Send both to the person in one message. They open the link on their own device, enter the code, and choose the workspaces. Then check it: ```bash invideo auth status ``` Never ask the person for a password, an email code or the code back. A fresh container starts with no sign-in, and the CLI exits with code 4. For a runner that does not keep its state, use the MCP server over HTTP with the device sign-in and a refresh token kept in your secret store. The steps are on [Sign in, device codes and sessions](/account/sign-in). ##### Exit codes in scripts These come from `invideo help exit-codes`. Your script acts on each one. | Code | Meaning | What the script does | | --- | --- | --- | | 0 | ok | Go on | | 1 | failed (invideo's side, or unknown) | Stop and log the `message` | | 2 | usage, or a request that cannot be done as asked | Fix the command | | 3 | conflict: the timeline changed since your read; read it again | Run `invideo edit show` again and rebuild the change | | 4 | not signed in: run `invideo auth login` | Stop. A person runs `invideo auth login` | | 5 | a limit: credits or quota | Stop and tell a person | | 6 | held by moderation: a safety review, not a refusal | Wait, then run `invideo status --wait` again | | 7 | transient: nothing ran | Run the same command again | | 8 | needs the person's confirmation | Stop and tell a person | | 9 | update required: run `invideo update`, then run it again | Run `invideo update`, then run it again | With `--wait`, a command tries again by itself when nothing ran (exit 7). A retry is the same request, so it never starts anything twice. ##### The confirmation hold Some jobs stop with the status `needs_confirmation`, or exit 8. Only a person can confirm it, in invideo. A pipeline cannot confirm it. The script stops, logs the URL, and tells someone. When the person has confirmed it, run `invideo status --wait` to pick the job up again. #### Steps The script below runs one full job. It checks the sign-in, makes a project and an edit, uploads a file, generates a clip with a cap, places the upload on the timeline, checks the edit, exports, waits for the card, and saves the video. It needs `jq`. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. In a pipeline, the person gives that yes once, as the cap. A person runs the device sign-in above on the machine that runs the jobs. Expected result: `invideo auth status` shows their name. Price the generation once, by hand, before the first run. 1. Run `invideo gen models --query ""`, the CLI's `find_models`. A good pick is `seedance_2_5.r2v`. Your agent can search for others with `find_models`. 2. Run `invideo gen model --model seedance_2_5.r2v` to read its inputs. 3. Run `invideo gen run` on the same URL as the script, with `--dry-run` and the real inputs, and tell the person the price. `` is any project of yours, from `invideo project new`. Set `MAX_CREDITS` to the price the person agreed to, from the dry run's `.estimated_credits`. Expected result: the script refuses to start without it. Run the script below. Expected result: `./out/export.mp4` on disk and the export card's URL in the log. Look at the frames in `./out/frames` before you ship the video. Expected result: the video looks as planned. ```bash #!/usr/bin/env bash # One invideo render from a pipeline. Needs jq and a signed-in CLI. set -euo pipefail export INVIDEO_JSON=1 RUN="${RUN_ID:?set RUN_ID, unique to this run}" MAX_CREDITS="${MAX_CREDITS:?set the agreed cap}" OUT=./out stop() { case "$rc" in 4) echo "Not signed in: a person runs invideo auth login" ;; 5) echo "Out of credits or quota: tell the account owner" ;; 6) echo "Held by moderation: tell the account owner" ;; 8) echo "Needs a person to confirm it in invideo" ;; 9) echo "Run invideo update, then run the job again" ;; *) echo "invideo failed with exit $rc" ;; esac >&2 exit "$rc" } iv() { invideo "$@" || { rc=$?; stop; }; } # 1. Signed in? iv auth status >/dev/null # 2. A project, and a name in it PROJECT=$(iv project new --title "Nightly $RUN" | jq -r .url) iv agent register "$PROJECT" --name ci-render >/dev/null export INVIDEO_AS=ci-render # 3. An edit, and the source file in its media bin EDIT=$(iv edit new "$PROJECT" --name "Nightly cut" | jq -r .url) iv asset upload "$EDIT" ./media/intro.mp4 --wait >/dev/null # 4. Generate: read the inputs, price it, then run it with a cap and a key iv gen model "$PROJECT" --model seedance_2_5.r2v >/dev/null iv gen run "$EDIT" --model seedance_2_5.r2v --dry-run \ -i prompt=@prompt.txt GEN=$(iv gen run "$EDIT" --model seedance_2_5.r2v \ --max-credits "$MAX_CREDITS" --idempotency-key "$RUN-gen" \ -i prompt=@prompt.txt | jq -r .url) iv status "$GEN" --wait >/dev/null # 5. Place the upload, then check and capture SHOW=$(iv edit show "$EDIT") TOKEN=$(jq -r .state_token <<<"$SHOW") TL=$(jq -r .main_timeline_id <<<"$SHOW") ASSET=$(iv edit show "$EDIT" --mode collection --collection asset \ | jq -r '.objects[0].id') jq -n --arg a "$ASSET" \ '[{op:"insert_media",asset:$a,track:"V1",at_f:0,ripple:true}]' \ > ops.json iv edit change "$EDIT" --timeline "$TL" --token "$TOKEN" \ --operations @ops.json iv edit check "$EDIT" iv edit capture "$EDIT" --at 0,1,2 --out "$OUT/frames" # 6. Export, wait for the card, then save the file CARD=$(iv edit export "$EDIT" --format video --quality 1080 \ --idempotency-key "$RUN-export" | jq -r '.sequences[0]') iv status "$CARD" --wait >/dev/null iv notebook show "$CARD" --out "$OUT" >/dev/null test -f "$OUT/export.mp4" || { echo "No file saved: $CARD" >&2; exit 1; } echo "Exported: $CARD" ``` Notes on the script: - `insert_media` places the picture alone. To place the file with its sound, use `place_media` with `linked_audio`. `invideo edit catalog --ops place_media` lists its fields. - The generated clip lands in the edit's thread. To place it too, read its sequence URL with `invideo notebook show`, and pass that URL as `asset` in the operation. - `invideo status` waits for the export and saves nothing. `invideo notebook show` on the card saves the file as `$OUT/export.mp4`, whatever `--file-name` says. The script checks the file is there before it reports success. - The script reads the card's URL, the state token and the main timeline's id from the JSON answers. Run each command once with `--json` and check the keys before you rely on the script. - A key only matches in its own project, for a generation, or on its own timeline, for an export. A rerun of the whole script makes a new project, so it pays again. To retry one step, run that command again with the same URL and the same key. #### If something goes wrong Most pipeline failures are a lost sign-in, a stale token, or a hold that needs a person. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit 4 on the first command | The machine has no sign-in. A person runs `INVIDEO_NO_BROWSER=1 invideo auth login` on it. | | Exit 3 on `invideo edit change` | Someone edited first. Run `invideo edit show` again for a new token and rebuild the change. | | Exit 5 | Credits or quota ran out. Stop and tell the account owner. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | Exit 8, or status `needs_confirmation` | Only a person can confirm it, in invideo. Stop, log the URL, and tell someone. | | Exit 7 | Nothing ran. Run the same command again, or add `--wait`. | | Exit 9 | Run `invideo update`, then run the job again. | | `--wait` stops before the job is over | Raise `--timeout`, or run `invideo status --wait` again later. | | The answer says you acted as a shared name | Register a name with `invideo agent register` and set `INVIDEO_AS`. | | The script stops with "No file saved" | Read the card with `invideo notebook show`, then run the last line again. | | The frames in `./out/frames` look wrong | Run the checks in [Check your video before you say it is done](/how-to/check-your-video). | | Exit 0, but `./out` has no video | `invideo status` saves nothing. Run `invideo notebook show --out ./out`, with the card's URL from `.sequences[0]` of the export answer. | | Avoid: running `invideo gen run` again to check a job | Instead: `invideo status --wait`. | | Avoid: a new `--idempotency-key` on a retry | Instead: the same key, so the retry finds the first job. | | Avoid: asking the person to paste a code or password | Instead: send the link and code from the device sign-in, and wait. | #### Related - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Check your video before you say it is done](/how-to/check-your-video) - [Sign-in](/account/sign-in) - [CLI reference](/reference/cli) - [Exit codes](/reference/exit-codes) - [Environment variables](/reference/environment) ### Export to Premiere, Resolve or Final Cut Source: https://docs.invideo.io/how-to/export-to-premiere-resolve-final-cut.md Your agent exports an invideo timeline as a project file that Premiere Pro, DaVinci Resolve or Final Cut Pro opens, with its media in a folder or a zip. Your agent turns an invideo timeline into a project file that Premiere Pro, DaVinci Resolve or Final Cut Pro opens. `export` with `format` set to `premiere`, `davinci` or `final_cut` makes it. The project comes with its media in a folder or a zip, so an editor can open it in their app and keep cutting. Exports are free. Use this when the rough cut happens in invideo, with your agent, and the finish happens in another editing app. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it the timeline URL and this prompt: ```text Check this timeline, then export it as a Premiere Pro project with its media in a zip. Give me the download when it is ready. ``` In a chat app, your agent gives you the export card's URL, and you download the files from invideo. In a terminal, your agent saves the files to a folder with `invideo notebook show --out `. #### How it works `export` takes a timeline's URL and a `format`. The branch in the URL is what gets exported, so export the branch you approved. | `format` | What you get | | --- | --- | | `premiere` | A project Premiere Pro opens, with its media | | `davinci` | A project DaVinci Resolve opens, with its media | | `final_cut` | A project Final Cut Pro opens, with its media | | `invideo` | An invideo project export | | `video` | A rendered video file | For `premiere`, `davinci` and `final_cut`, the option `media_packaging` says how the media comes with the project: - **`folder`** is the default. The card gives the project file and a zip of the media. - **`zip`** gives the project file, and a zip that holds the media and a second copy of the project. - **`none`** sends the project without its media. Use it when the editor has the source files. They point the clips at their own copies in the app. The export returns its thread's URL at once, and the export card's URL once it appears. The agent reads the card for its status. Once it is `completed`, the card gives the files, with fresh download URLs on every read, and the project's export page. `completed` can arrive before the media zip is packed. When the card says the media is still packing, the agent reads the card again until the zip is in the files list. Exports are free. They need export permission on the project. In invideo Editor, the same export is **Editable project** in the **Export** window, where DaVinci Resolve is the **OpenTimelineIO** option. ##### Check the project in the app before you deliver The project opens in the other app as an editable timeline. Some parts of an invideo edit may look different there. Open the project and check these before you deliver: - Transitions, and custom transitions - Effects, and custom effects made with `add_custom_effect` - Text and titles: fonts, styles and position - Captions - Color grades - Audio levels, fades and audio effects - Keyframed moves, like zooms and fades - Clip timing at each cut Compare the project with a frame from invideo at the same time. `capture` gives frames of the timeline as it looks in invideo. #### Steps The agent runs these steps for one project export. The agent runs the checklist in [Check your video before you say it is done](/how-to/check-your-video), with `check_timeline` and `capture`. Expected result: no findings, and frames that look right. The agent saves a checkpoint with `timeline_history`, or marks the branch final. Expected result: a checkpoint you can name in the hand-off. The agent calls `export` with the timeline URL, the `format` for the app, `media_packaging`, and an `idempotency_key`. Expected result: a thread URL at once. The agent follows the card with `status` or `read`, at the time `retry_after_s` gives. Expected result: status `completed`, then the project file and the media zip in the files list. The agent gives you the download, or saves it with `invideo notebook show --out ` in a terminal. Expected result: a project file and a zip of its media. Then you open it in the app and run the check above. The same export from a terminal: ```bash invideo edit check invideo edit capture --at 0,5,10 --out ./frames invideo edit show invideo branch checkpoint --title "to the editor" \ --token invideo edit export --format premiere --media-packaging zip \ --idempotency-key "handoff-v1" --json invideo status --wait invideo notebook show invideo notebook show --out ./handoff ``` Where each value comes from: - `` is the URL of the branch you approved, from `invideo edit new` or `invideo branch new`. `` comes from `invideo edit show`. - `` is `.sequences[0]` of the export answer. `invideo status` waits and saves nothing. - The first `notebook show` reads the card. Run it again until the media zip is in its files, then save with `--out`. For DaVinci Resolve use `--format davinci`, and for Final Cut Pro use `--format final_cut`. For a timeline inside the edit, add `--timeline` with its id from `invideo edit show`. The key MCP call is `export`. `` is the URL of the branch you approved, from `new_timeline` or `timeline_history`. ```json { "url": "", "format": "davinci", "options": { "media_packaging": "folder" }, "idempotency_key": "handoff-v1" } ``` #### If something goes wrong Most export problems come from the wrong branch, a missing permission, or a retry without a key. | Symptom | Fix | | --- | --- | | The export is refused for permission | The project needs export permission for you. Ask the person who shares the project. | | The project shows an earlier state of the edit | The URL named another branch. Export the URL of the branch you approved. | | The export card returns `failed` | Read the card for why. Try once more. If it fails again, file `report_bug` with the URL and what you sent. | | A call times out or returns `completion_unknown` | Retry with the same `idempotency_key`. It finds the first export. | | CLI exit 7 | Nothing ran. Run the same command again. | | The clips have no media in the app | With `none`, no media came with the project. Point the clips at your copies, or export again with `folder` or `zip`. | | The card says `completed` but lists only the project file | The media zip is still packing. Read the card again in a few seconds until the zip is listed. | | The checks before export find a problem | Fix the edit first, then check again. | | You want to keep editing after the hand-off | The agent works on a new branch, so the checkpoint you sent stays as it was. | | CLI exit 0, but the folder is empty | `invideo status` saves nothing. Run `invideo notebook show --out `. | | A download link stops working | Read the card again for a fresh URL. | | Avoid: calling `export` again to check on one | Instead: `status` or `read` the card's URL. | | Avoid: delivering without opening the project | Instead: open it in the app and run the check above. | #### Related - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [Export video, audio or a still from invideo Editor](/projects-and-exports/how-to-export-video-audio-or-a-png-still-from-invideo-editor) - [Security and data](/account/security-and-data) ### Is there an API? Source: https://docs.invideo.io/api.md There are no invideo API keys, by design. Use invideo MCP, the invideo CLI, or device sign-in for servers and scripts. There are no API keys, by design. Every call to invideo, whether it generates a shot with a model or cuts a timeline, runs as a signed-in person, in that person's workspace. You reach invideo through three routes: invideo MCP for AI apps and agents, the invideo CLI for shells and scripts, and device sign-in for servers with no browser. ```bash curl -fsSL https://agents.invideo.io | sh invideo auth login invideo project list --json ``` #### Why there are no API keys A key is a secret that works for anyone who holds it. invideo uses a person's sign-in instead, for these reasons. - **Every call has an owner.** Each edit, generation and export is made by a named person, in a workspace they chose. People in the project see who did what. - **Credits come from the right place.** Paid calls spend the credits of the workspace the person works in. A leaked key cannot spend them. - **Access matches the person.** Your agent can open only what you can open. - **Nothing to rotate in code.** There is no key to paste into a config file, a repo or a chat. If a tool asks you for an invideo API key, it is not one of invideo's routes. Use one of the routes below. #### Route 1: invideo MCP invideo MCP is a remote MCP server at `https://mcp.invideo.io/mcp`. MCP (Model Context Protocol) is a standard way for AI apps to call outside tools. It is the route for clients without a shell: Claude on the web, ChatGPT, the Gemini app, VS Code, Gemini CLI, and any client that supports remote MCP servers over Streamable HTTP. Terminal agents such as Claude Code, Codex, Cursor and Antigravity use the CLI instead. ```json { "mcpServers": { "invideo": { "url": "https://mcp.invideo.io/mcp" } } } ``` The client asks you to sign in to invideo in your browser when it connects. Then your agent calls tools such as `list_projects`, `edit_timeline`, `generate` and `export`. See [invideo for AI agents](/agents) for every client, and [MCP tools](/reference/mcp-tools) for the full list. The server is plain JSON-RPC over HTTP POST. An agent with no MCP client can call it with `curl`, with an access token from device sign-in. [Sign in, device codes and sessions](/account/sign-in) has the device flow over HTTP. #### Route 2: the invideo CLI The invideo CLI is one program for macOS, Linux and Windows. It does the same work as MCP from a shell, and saves files to disk. Use it for scripts and coding agents that run commands. ```bash invideo project new --title "Launch teaser" invideo asset upload ./shots/clip.mp4 invideo edit new --name "Teaser v1" invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` `` comes from `invideo project new`, and `` from `invideo edit new`. `` is `.sequences[0]` in the export's answer. `invideo status` waits and saves nothing. `invideo notebook show` with `--out` saves the video as `export.mp4`. Pass `--json` on every command in a script. Each answer is one JSON object, with `next` saying what to run after it. Use one route per session. Do not mix MCP and CLI calls in the same session. See [CLI commands and flags](/reference/cli). #### Route 3: device sign-in for servers On a machine with no browser, such as a CI runner, a container or a cloud agent, sign in with a device code. A person approves once, on a phone or laptop. ```bash INVIDEO_NO_BROWSER=1 invideo auth login ``` The command prints a link and a code. The person opens the link, enters the code, chooses the workspaces and approves. The sign-in then lasts on that machine. This code signs in the CLI only. Over HTTP without the CLI, the agent runs its own device flow, gets an access token and a refresh token, and refreshes the access token when it expires. Your agent never asks the person for a password or for the code back. It sends the link and the code in one message and waits. See [Sign in, device codes and sessions](/account/sign-in) and [Run invideo in CI and on servers](/how-to/ci-and-servers). #### What each route is good for Pick the route that fits where your code or agent runs. | You have | Use | | --- | --- | | A chat app such as Claude or ChatGPT | invideo MCP, as the ChatGPT plugin or a Claude connector | | A coding agent such as Claude Code, Codex or Cursor | The CLI, through the invideo plugin | | A shell script or a batch job on your laptop | The CLI, signed in with `invideo auth login` | | A CI job, a container or a cloud agent | The CLI or MCP over HTTP, with device sign-in | | Your own app that serves other users | Each user signs in with their own invideo account | #### Cost Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. The same rules hold on every route. See [Credits and what they cost](/account/credits). #### If something goes wrong Most problems come from looking for a key that does not exist. | Symptom | Fix | | --- | --- | | A tool or guide asks for an invideo API key. | Avoid keys. Instead, sign in with the browser or a device code. | | A call returns a sign-in challenge. | The client is not signed in. Finish the sign-in, then retry the call. | | The CLI exits with code 4. | Run `invideo auth login`, or `INVIDEO_NO_BROWSER=1 invideo auth login`. | | An HTTP call returns 401. | The access token expired. Refresh it with the refresh token. | | The agent mixes MCP tools and CLI commands. | Avoid this. Instead, pick one route for the whole session. | | A server job needs a person each time. | Keep the refresh token in a secret store, so one approval lasts. | #### Related - [invideo for AI agents](/agents) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [Sign in, device codes and sessions](/account/sign-in) - [CLI commands and flags](/reference/cli) - [MCP tools](/reference/mcp-tools) - [Credits and what they cost](/account/credits) ## Connect your agent ### Claude Code Source: https://docs.invideo.io/start/claude-code.md Install the invideo plugin in Claude Code, sign in once in the browser, and have your agent generate video, voice and music and edit it on a real timeline you can watch live. Claude Code gets the invideo skills and the CLI, opens your projects by URL, generates the shots, voices and music a video lacks, and edits it all on a timeline you watch live in the browser. In Claude Code, invideo runs through the CLI, not through an MCP server. #### Set up Install the invideo plugin. Run these in your terminal, or ask Claude Code to run them for you. ```bash claude plugin marketplace add invideoio/skills claude plugin install invideo@invideo ``` The plugin installs the invideo skills: how to connect, the work loop, the cost rule, and the steps for each kind of video. The skills are CLI-first. On your first video request, Claude Code installs the invideo CLI, a single binary with no sudo, and opens a browser tab for you to sign in. Run the two lines above. You see invideo in the plugin list. Give Claude Code a video job. It installs the CLI with the install script and runs `invideo auth login`. A sign-in tab opens in your browser. Sign in and choose the workspaces your agent may use. Come back to Claude Code. It carries on with your job, and `invideo auth status` shows your name. You can also install the CLI yourself, before the first job. ```bash curl -fsSL https://agents.invideo.io | sh invideo --version invideo auth login ``` On Windows, install with the PowerShell line on [invideo for AI agents](/agents). #### Sign in With the CLI, `invideo auth login` opens the browser and waits for you to approve. Claude Code runs it in the background or with a long timeout and tells you a tab opened. Where no browser can open, on ssh, in a container or on a cloud machine, the agent uses a device code. ```bash INVIDEO_NO_BROWSER=1 invideo auth login ``` It prints a link and a code. Open the link on another device and enter the code. Your agent never asks you to send the code back, and never asks for a password. #### First prompt Start with a prompt that proves the connection works. ```text Use invideo to show me my projects. ``` Then give it a real job. Name the folder with your files. ```text Make a new invideo project called "Launch teaser". Upload the clips in ./shots, cut a short teaser on a branch, add a title card and a short generated opening shot. Tell me the price before you spend, and show me the frames before you export. ``` Claude Code replies with project and timeline URLs. Open them to watch the edit land. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### If something goes wrong Most problems come from the install path or the sign-in. | Symptom | Fix | | --- | --- | | `claude plugin install` says the plugin is not found | Run `claude plugin marketplace add invideoio/skills` first, then install again. | | The agent says `invideo` is not found after the install | The install script wrote `~/.local/bin/invideo`. Run it by its full path, or add that folder to `PATH`. | | CLI exit 4, not signed in | Run `invideo auth login`, or the device code line above. | | The sign-in tab never opened | Run `INVIDEO_NO_BROWSER=1 invideo auth login` and open the link it prints. | | The agent cannot see a workspace | Run `invideo auth login` again and choose that workspace in the browser. | | Avoid: the agent asks for your code or password | Instead: you approve in the browser, and the agent waits. | | Avoid: the agent adds invideo as an MCP server in Claude Code | Instead: use the CLI. The skills teach it, and the plugin carries no MCP config. | If invideo still does not appear, check the plugin with `claude plugin list`. #### Next - [invideo for AI agents](/agents), the rules your agent follows - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Claude Code as your AI film editor](/how-to/film/claude-code-as-film-editor) - [CLI commands and flags](/reference/cli) ### Cursor Source: https://docs.invideo.io/start/cursor.md Add the invideo skills to Cursor, sign in once in the browser, and have Cursor's agent generate video, voice and music and edit it on a real timeline you can watch live. Your agent in Cursor gets the invideo skills and the CLI, opens your projects by URL, generates the shots, voices and music a video lacks, and edits it all on a timeline you watch live in the browser. In Cursor, invideo runs through the CLI first. #### Set up Add the invideo skills to your project. The agent then drives invideo through the CLI in its terminal, like Claude Code and Codex do. ```bash npx skills add invideoio/skills ``` The skills hold how to connect, the work loop, the cost rule, and the steps for each kind of video. On your first video request the agent installs the invideo CLI, a single binary with no sudo, and opens a browser tab for you to sign in. Run the line above in your project. You see the invideo skills in your project's skills folder. Give the agent a video job. It installs the CLI with the install script and runs `invideo auth login`. A sign-in tab opens in your browser. Sign in and choose the workspaces the agent may use. Come back to Cursor. It carries on, and `invideo auth status` shows your name. You can also install the CLI yourself, before the first job. ```bash curl -fsSL https://agents.invideo.io | sh invideo --version invideo auth login ``` On Windows, install with the PowerShell line on [invideo for AI agents](/agents). ##### The Cursor Marketplace plugin, for MCP The invideo plugin on the Cursor Marketplace is the MCP route. Click **Customize**, search `invideo`, then click **Install**. The plugin adds the invideo MCP server to Cursor and nothing else: no skills, no CLI. Use it when you want the tools in the chat without a terminal. Pick the CLI or MCP for a session, not both. Over MCP the agent has no skills, so it reads the rules from [invideo for AI agents](/agents) and from `get_help`. #### Sign in With the CLI, `invideo auth login` opens the browser and waits for you to approve. Sign in and choose the workspaces the agent may use. Where no browser can open, on ssh or in a container, the agent uses a device code. ```bash INVIDEO_NO_BROWSER=1 invideo auth login ``` It prints a link and a code. Open the link on another device and enter the code. Your agent never asks you to send the code back, and never asks for a password. #### First prompt Start with a prompt that proves the connection works. ```text Use invideo to show me my projects. ``` Then give it a real job. Name the folder with your files. ```text Make a new invideo project called "Release notes video". Upload the screen recordings in ./recordings, cut them on a branch, add a title for each one and a short generated opening shot. Tell me the price before you spend, and show me the frames before you export. ``` The agent replies with project and timeline URLs. Open them to watch the edit land. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### If something goes wrong Most problems come from the install path or the sign-in. | Symptom | Fix | | --- | --- | | The Marketplace plugin is installed, but the agent has no skills | That plugin carries only the MCP server. Add the skills with `npx skills add invideoio/skills` for the CLI path. | | The agent says `invideo` is not found after the install | The install script wrote `~/.local/bin/invideo`. Run it by its full path, or add that folder to `PATH`. | | CLI exit 4, not signed in | Run `invideo auth login`, or the device code line above. | | The sign-in tab never opened | Run `INVIDEO_NO_BROWSER=1 invideo auth login` and open the link it prints. | | The agent cannot see a workspace | Run `invideo auth login` again and choose that workspace in the browser. | | Avoid: the agent asks for your code or password | Instead: you approve in the browser, and the agent waits. | | Avoid: the agent uses the CLI and the MCP plugin together | Instead: pick one for the session. | #### Next - [invideo for AI agents](/agents), the rules your agent follows - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [CLI commands and flags](/reference/cli) ### Codex Source: https://docs.invideo.io/start/codex.md Install the invideo plugin in Codex, sign in once in the browser, and have Codex generate video, voice and music and edit it on a real timeline you can watch live. Codex gets the invideo skills and the CLI, opens your projects by URL, generates the shots, voices and music a video lacks, and edits it all on a timeline you watch live in the browser. In Codex, invideo runs through the CLI, not through an MCP server. #### Set up Install the invideo plugin. Run these in your terminal, or ask Codex to run them for you. ```bash codex plugin marketplace add invideoio/skills codex plugin add invideo@invideo ``` The plugin installs the invideo skills: how to connect, the work loop, the cost rule, and the steps for each kind of video. The skills are CLI-first. On your first video request, Codex installs the invideo CLI, a single binary with no sudo, and opens a browser tab for you to sign in. Run the two lines above. You see invideo in `codex plugin list`. Give Codex a video job. It installs the CLI with the install script and runs `invideo auth login`. A sign-in tab opens in your browser. Sign in and choose the workspaces your agent may use. Come back to Codex. It carries on with your job, and `invideo auth status` shows your name. You can also install the CLI yourself, before the first job. ```bash curl -fsSL https://agents.invideo.io | sh invideo --version invideo auth login ``` On Windows, install with the PowerShell line on [invideo for AI agents](/agents). #### Sign in With the CLI, `invideo auth login` opens the browser and waits for you to approve. Codex runs it in the background or with a long timeout and tells you a tab opened. Where no browser can open, on ssh, in a container or on a cloud machine, the agent uses a device code. ```bash INVIDEO_NO_BROWSER=1 invideo auth login ``` It prints a link and a code. Open the link on another device and enter the code. Your agent never asks you to send the code back, and never asks for a password. #### First prompt Start with a prompt that proves the connection works. ```text Use invideo to show me my projects. ``` Then give it a real job. Name the folder with your files. ```text Make a new invideo project called "Product demo". Upload the clips in ./footage, cut them into one timeline on a branch, add captions and a short generated opening shot. Tell me the price before you spend, and show me the frames before you export. ``` Codex replies with project and timeline URLs. Open them to watch the edit land. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### If something goes wrong Most problems come from the install path or the sign-in. | Symptom | Fix | | --- | --- | | `codex plugin add` says the plugin is not found | Run `codex plugin marketplace add invideoio/skills` first, then add again. | | The agent says `invideo` is not found after the install | The install script wrote `~/.local/bin/invideo`. Run it by its full path, or add that folder to `PATH`. | | CLI exit 4, not signed in | Run `invideo auth login`, or the device code line above. | | The sign-in tab never opened | Run `INVIDEO_NO_BROWSER=1 invideo auth login` and open the link it prints. | | The agent cannot see a workspace | Run `invideo auth login` again and choose that workspace in the browser. | | Avoid: the agent asks for your code or password | Instead: you approve in the browser, and the agent waits. | | Avoid: the agent adds invideo as an MCP server in Codex | Instead: use the CLI. The skills teach it, and the plugin carries no MCP config. | #### Next - [invideo for AI agents](/agents), the rules your agent follows - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [CLI commands and flags](/reference/cli) ### ChatGPT Source: https://docs.invideo.io/start/chatgpt.md Install the official invideo plugin in ChatGPT, sign in once, and ask ChatGPT to generate video, voice and music and edit it on a real timeline. ChatGPT gets the invideo tools through the official invideo plugin, opens your projects by URL, generates the shots, voices and music a video lacks, and edits it all on a timeline you watch live in the browser. #### Set up invideo is an official ChatGPT plugin. Install it once from ChatGPT's plugin list. In ChatGPT, open **Customize** in the sidebar, then **Plugins**. invideo is listed under **Creativity** as "Edit videos & motion graphics". You can also search for `invideo` in the plugin search box. Click the plus next to invideo. It appears under **Installed** in the left column. Ask ChatGPT for a video. The first call opens the invideo sign-in in your browser. Sign in and choose the workspaces ChatGPT may use. ChatGPT retries the call after you approve. ChatGPT gets the plugin only. It gets no invideo skills, so ChatGPT learns the rules from the server's own guide, `get_help`. If you want to work in Codex instead, use the Codex plugin and the CLI: see [Set up invideo in Codex](/start/codex). #### Sign in ChatGPT runs the sign-in in the browser. When a call needs your account, ChatGPT shows the invideo sign-in and retries the call after you approve. You never paste a code or a password into the chat. ChatGPT agents that run in the cloud cannot use the plugin. They call the server over HTTP with a device code instead. The steps for that are on [Sign in, device codes and sessions](/account/sign-in). #### First prompt Start with a prompt that proves the connection works. ```text Use invideo to show me my projects. ``` Then give it a real job. In ChatGPT, your files go into the invideo project first. Open the project in invideo and drag them into the Media panel, then name them in the chat. ```text In my invideo project "Summer trip", use the clips I uploaded to make a short vertical video with music made to fit. Generate a short opening shot. Tell me the price before you generate anything, and show me frames before you export. ``` ChatGPT replies with project and timeline URLs. Open them to watch the edit land, and change anything by hand. #### Cost A ChatGPT plan does not include invideo. You sign in with your own invideo account, and its plan pays for the credits. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. See [Credits and what they cost](/account/credits). #### If something goes wrong Most problems come from the plugin not being installed or the sign-in not being finished. | Symptom | Fix | | --- | --- | | invideo is not in the plugin list | Search for `invideo` under **Customize**, then **Plugins**. In a managed workspace, your admin controls which plugins you can add; ask them. | | ChatGPT does not use invideo | Check that invideo is under **Installed**, then name invideo in the prompt: "Use invideo to ...". | | ChatGPT asks you to sign in again | Finish the invideo sign-in in the browser. ChatGPT retries the call. | | ChatGPT cannot see a workspace | Sign in again from the plugin and choose that workspace. | | A ChatGPT agent in the cloud cannot connect | Cloud agents cannot use the plugin. They use the device code over HTTP. | | Avoid: ChatGPT asks for your code or password | Instead: you sign in through the invideo page that ChatGPT opens. | | Avoid: ChatGPT says done without a link | Instead: ask it to `capture` frames and give you the timeline URL. | #### Next - [invideo for AI agents](/agents), the rules ChatGPT follows - [Make a video with ChatGPT, Claude or Gemini](/how-to/personal/with-chatgpt-claude-gemini) - [Make a video with invideo without a terminal](/start/no-terminal) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Gemini Source: https://docs.invideo.io/start/gemini.md Connect invideo to the Gemini app as a custom app, or to Gemini CLI as an MCP server, and have Gemini generate video, voice and music and edit it on a real timeline. Gemini gets the invideo tools, opens your projects by URL, generates the shots, voices and music a video lacks, and edits it all on a timeline you watch live in the browser. The Gemini app takes invideo as a custom app. Gemini CLI takes it as an MCP server. #### Use invideo in the Gemini app In the Gemini app, invideo is a custom connected app. You add it once in the web app, and it works in the web app and the mobile app. Gemini gets the MCP server only, with no invideo skills, so it learns the rules from the server's own guide, `get_help`. Google sets the rules for custom apps. You must be 18 or over, in the US, signed in with a personal Google Account, with Keep Activity on. Work and school accounts cannot add custom apps, and custom apps work in English only. Check Google's custom apps help page for its rules. On your computer, go to gemini.google.com. At the bottom, click **Settings**, then **Connected Apps**. If you do not see it, click **Personal Intelligence** first. Under **Custom apps**, click **Add a custom app**, and enter the MCP server URL: `https://mcp.invideo.io/mcp`. Click **Next**. invideo supports dynamic client registration, so you enter no credentials. Follow the on-screen steps. Your browser opens on the invideo sign-in. Sign in and choose the workspaces Gemini may use. You see invideo under Custom apps. In a chat, type `@` and select invideo, then ask for a video. Gemini asks you to confirm each action that changes something. To disconnect, turn invideo off under **Custom apps**, or open **More details** and choose **Disconnect**. **Remove app** unlinks the server from your Google Account. #### Use invideo in Gemini CLI Run this in your terminal, or ask Gemini CLI to run it for you. ```bash gemini mcp add --transport http --scope user invideo \ https://mcp.invideo.io/mcp ``` `--scope user` adds invideo to `~/.gemini/settings.json`, so it works in every folder. Without it, Gemini CLI adds the server to the current project only. Gemini gets the MCP server only. It gets no invideo skills, so Gemini learns the rules from the server's own guide, `get_help`. You can also add the server to `~/.gemini/settings.json` by hand. ```json { "mcpServers": { "invideo": { "httpUrl": "https://mcp.invideo.io/mcp" } } } ``` Run the `gemini mcp add` line, or save the config above. If the file has other servers, add the `invideo` entry to the same `mcpServers` object. Exit Gemini CLI and start it again so it loads invideo. Run `gemini mcp list` in your terminal. You see invideo with its connection status. ##### Use the CLI instead Gemini CLI can also drive invideo through the invideo CLI in its shell. Use it when you want files on disk, work from scripts, or run on a machine with no browser. Pick MCP or the CLI for a session, not both. ```bash curl -fsSL https://agents.invideo.io | sh invideo --version invideo auth login ``` On ssh, in a container or on a cloud machine, sign in the CLI with a device code instead. ```bash INVIDEO_NO_BROWSER=1 invideo auth login ``` It prints a link and a code. Open the link on another device and enter the code. This signs in the invideo CLI only, not the MCP server. If a CLI command exits with code 4, it is not signed in: run `invideo auth login` again. #### Sign in Gemini CLI runs the browser sign-in when invideo asks for it. If it does not, run this in Gemini CLI: ```text /mcp auth invideo ``` Your browser opens on the invideo sign-in. Sign in and choose the workspaces Gemini may use. Run the same command again if the sign-in lapses. Gemini never asks you to send a code back, and never asks for a password. Signing in the invideo CLI does not sign in this MCP connection. On a machine with no browser, use the CLI path in "Use the CLI instead" for that session. An MCP client that runs its own device flow follows the steps on [Sign in, device codes and sessions](/account/sign-in). #### First prompt Start with a prompt that proves the connection works. ```text Use invideo to show me my projects. ``` Then give it a real job. Name the folder with your files. ```text Make a new invideo project called "Recipe reel". Upload the clips in ./cooking, cut a vertical reel on a branch with captions, and add a short generated opening shot. Tell me the price before you spend, and show me the frames before you export. ``` Gemini replies with project and timeline URLs. Open them to watch the edit land. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### If something goes wrong Most problems come from Google's rules for custom apps, the scope, the restart or the sign-in. | Symptom | Fix | | --- | --- | | Gemini app: there is no Connected Apps or Custom apps section | Your account does not meet Google's rules for custom apps: a personal account, 18 or over, in the US, with Keep Activity on. | | Gemini app: Gemini does not use invideo for a prompt | Type `@` and select invideo at the start of the prompt. | | Gemini CLI: the invideo tools do not appear | Exit Gemini CLI and start it again. | | invideo works in one folder only | You added it without `--scope user`. Add it again with that flag. | | invideo asks for authentication | Run `/mcp auth invideo` and sign in in the browser. | | Gemini CLI with no browser cannot finish `/mcp auth` | Switch to the CLI path for the session and sign in with a device code. | | Gemini cannot see a workspace | Run `/mcp auth invideo` and choose that workspace. | | Avoid: Gemini asks for your code or password | Instead: you approve in the browser, and the agent waits. | | Avoid: Gemini uses MCP and the CLI together | Instead: pick one for the session. | #### Next - [invideo for AI agents](/agents), the rules your agent follows - [Make a video with ChatGPT, Claude or Gemini](/how-to/personal/with-chatgpt-claude-gemini) - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Antigravity Source: https://docs.invideo.io/start/antigravity.md Install the invideo plugin in the Antigravity CLI or IDE, sign in once in the browser, and have the agent generate video, voice and music and edit it on a real timeline you can watch live. Your agent in Antigravity gets the invideo skills and the CLI, opens your projects by URL, generates the shots, voices and music a video lacks, and edits it all on a timeline you watch live in the browser. The same plugin works in the Antigravity CLI, `agy`, and in the Antigravity IDE. In Antigravity, invideo runs through the CLI, not through an MCP server. #### Set up Install the invideo plugin from its GitHub URL. Run this in your terminal, or ask the agent to run it for you. ```bash agy plugin install https://github.com/invideoio/skills ``` The plugin installs the invideo skills: how to connect, the work loop, the cost rule, and the steps for each kind of video. Antigravity converts the plugin on install and lists its skills. The skills are CLI-first. On your first video request, the agent installs the invideo CLI, a single binary with no sudo, and opens a browser tab for you to sign in. Run the line above. You see `invideo` marked ok with its skills processed. `agy plugin list` shows it as enabled. Give the agent a video job, or type `/invideo` to open the primary skill. The agent installs the CLI with the install script and runs `invideo auth login`. A sign-in tab opens in your browser. Sign in and choose the workspaces the agent may use. Come back to Antigravity. It carries on with your job, and `invideo auth status` shows your name. You can also install the CLI yourself, before the first job. ```bash curl -fsSL https://agents.invideo.io | sh invideo --version invideo auth login ``` On Windows, install with the PowerShell line on [invideo for AI agents](/agents). If the Antigravity CLI is not on this machine, Google's install line is the same shape, and the binary lands in the same folder. ```bash curl -fsSL https://antigravity.google/cli/install.sh | bash agy --version ``` #### Sign in With the CLI, `invideo auth login` opens the browser and waits for you to approve. The agent runs it in the background or with a long timeout and tells you a tab opened. Where no browser can open, on ssh, in a container or on a cloud machine, the agent uses a device code. ```bash INVIDEO_NO_BROWSER=1 invideo auth login ``` It prints a link and a code. Open the link on another device and enter the code. Your agent never asks you to send the code back, and never asks for a password. #### First prompt Start with a prompt that proves the connection works. ```text Use invideo to show me my projects. ``` Then give it a real job. Name the folder with your files. ```text Make a new invideo project called "Sprint demo". Upload the screen recordings in ./demo, cut them into one timeline on a branch, add a title for each one, and generate a short opening shot and a music bed. Tell me the price before you spend, and show me the frames before you export. ``` The agent replies with project and timeline URLs. Open them to watch the edit land. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### If something goes wrong Most problems come from the install path or the sign-in. | Symptom | Fix | | --- | --- | | `agy plugin install` says the target must be a directory | You passed `invideoio/skills`. Pass the full URL, `https://github.com/invideoio/skills`, or a local clone's path. | | `agy plugin install invideo@invideo` says unknown marketplace | invideo is not in Antigravity's marketplace. Install from the GitHub URL. | | The agent says `invideo` is not found after the install | The install script wrote `~/.local/bin/invideo`. Run it by its full path, or add that folder to `PATH`. | | `agy` is not found after Google's install script | The script prints where it put the binary. Add that folder to `PATH`, or run `agy install`, which sets the path for you. | | CLI exit 4, not signed in | Run `invideo auth login`, or the device code line above. | | The sign-in tab never opened | Run `INVIDEO_NO_BROWSER=1 invideo auth login` and open the link it prints. | | The agent cannot see a workspace | Run `invideo auth login` again and choose that workspace in the browser. | | Avoid: the agent asks for your code or password | Instead: you approve in the browser, and the agent waits. | | Avoid: the agent adds invideo as an MCP server in Antigravity | Instead: use the CLI. The skills teach it, and the plugin carries no MCP config. | #### Next - [invideo for AI agents](/agents), the rules your agent follows - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [CLI commands and flags](/reference/cli) ### Without a terminal Source: https://docs.invideo.io/start/no-terminal.md Generate and edit a video with Agent Two in the invideo app, or with Claude, ChatGPT or the Gemini app in the browser. No install, no commands. You can make a video with invideo without a terminal: generate the shots, voices and music it needs, cut them with your own footage, and export. Use Agent Two inside the invideo app, or connect invideo to Claude, ChatGPT or the Gemini app in the browser. In ChatGPT, install the official invideo plugin. For Claude or the Gemini app, add invideo as a connector or custom app with this name and URL. Agent Two needs no setup. ```text Name: invideo MCP server URL: https://mcp.invideo.io/mcp ``` #### Pick a path Every path works on the same invideo projects. You can start in one and continue in another. | Path | Where you ask | Set up | | --- | --- | --- | | Agent Two | The agent panel in the invideo app | None. Sign in at invideo.io. | | Claude | A chat on claude.ai or the Claude desktop app | Add invideo as a connector once. | | ChatGPT | A chat on chatgpt.com | Install the official invideo plugin once, from Customize, then Plugins. | | Gemini app | A chat on gemini.google.com or the Gemini mobile app | Add invideo as a custom app once, in the web app. Google limits who can. | #### Agent Two in the invideo app Agent Two works inside invideo, next to your timeline. Nothing to install. Sign in at invideo.io. Open a project, or create a blank timeline. Open the Media panel and select Upload, or drag your files into the panel. You see each file in the panel when its upload ends. Open the agent panel on the left and describe the video. Say the length, the shape, which files to use, and what must stay the same. Watch the result in the Monitor and on the timeline. Change anything by hand, or give Agent Two a short follow-up. #### Claude, no install Claude on the web or the desktop app uses invideo as a connector. In Claude, open **Customize**, then **Connectors**, and click **Add**. Choose the custom web connector. Name it `invideo`. Use the URL `https://mcp.invideo.io/mcp`. Select Connect. Sign in to invideo in the browser and choose your workspaces. In a conversation, open the + menu, choose Connectors, and turn on invideo. So Claude can upload the files you attach to a chat, open **Settings**, then **Capabilities**, and add m.invideo.io under **Allowed websites**. You do this once. You see m.invideo.io in the list. The full steps are on [How do I let Claude upload my files to invideo?](/ai-agents/how-do-i-let-claude-upload-my-files-to-invideo). In a Claude organization, an owner adds invideo to the organization's connectors first. #### ChatGPT, no install ChatGPT has an official invideo plugin. The full steps are on [Use invideo in ChatGPT](/start/chatgpt). In short: open **Customize**, then **Plugins**, add invideo from the Creativity list, then ask for a video and sign in when ChatGPT opens the invideo page. #### Gemini app, no install The Gemini app uses invideo as a custom app. The full steps and Google's rules for who can add one are on [Use invideo in Gemini](/start/gemini). In short: in the Gemini web app, open **Settings**, then **Connected Apps**, add a custom app with the URL `https://mcp.invideo.io/mcp`, sign in, then type `@` and select invideo in a chat. #### Continue an existing project To work on a project you already have, open it in invideo Editor, copy the URL from the browser's address bar, and paste it into the chat. Ask your agent to open it and list its timelines, then say which one to change. The URL is how every tool in invideo finds a project, so the agent needs no other id. #### Where your files go Put your files in the invideo project, then name them in the chat. - **In the invideo app**, drag files into the Media panel. - **In Claude, ChatGPT or the Gemini app**, open the project in invideo and drag the files into its Media panel. Then tell the chat which files to use. You can also attach a file to the chat, and the agent brings it into the project. In Claude, this needs m.invideo.io allowed once. See [How do I let Claude upload my files to invideo?](/ai-agents/how-do-i-let-claude-upload-my-files-to-invideo). Use folder and file names in your request, like "use product.mp4 first". The agent finds the files by name. #### How to ask Describe the result, not the clicks. Say the length, the shape (9:16 vertical, 16:9 wide, 1:1 square), the files, the music mood, and the text to show. ```text Make a short vertical birthday video for Maya from the photos in this project. Open on the beach photo, add soft music made for it, a voice that says "Happy birthday, Maya" and the same words on screen at the end. Tell me the price before you generate anything. ``` ```text Shorten this timeline and keep the speaker's lines in order. Add captions. Show me frames from the start, middle and end. ``` The agent works on a branch, so your main cut stays as it was until you accept the change. #### See the cost Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. Here is where you see the cost on each path. - **In the invideo app**, select the three dots on an agent message to see what that reply used. For the whole project, select the three dots at the top right and choose Project Usage. The permission toggle in the chat box can make Agent Two ask before every generation. - **In Claude, ChatGPT or the Gemini app**, the agent tells you the price of each paid call in the chat. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from invideo not being on in the chat. | Symptom | Fix | | --- | --- | | Claude does not use invideo | Open the + menu, choose Connectors, and turn on invideo. | | Claude says it cannot upload your files to invideo | Allow m.invideo.io in Claude under **Settings**, then **Capabilities**, then **Allowed websites**, and start a new chat. See [How do I let Claude upload my files to invideo?](/ai-agents/how-do-i-let-claude-upload-my-files-to-invideo). | | ChatGPT does not use invideo | Check that invideo is installed under **Customize**, then **Plugins**, and name invideo in the prompt. | | The chat cannot find your files | Check that they are in the project's Media panel, and use their names. | | The chat cannot see a workspace | Reconnect invideo and choose that workspace in the sign-in. | | Avoid: the chat asks for a code or password | Instead: you sign in on the invideo page that opens. | | Avoid: the chat says done without a link | Instead: ask for the timeline URL and frames from the video. | #### Next - [Make a video with ChatGPT, Claude or Gemini](/how-to/personal/with-chatgpt-claude-gemini) - [Make a birthday montage from photos and clips](/how-to/personal/birthday-montage) - [Use invideo in ChatGPT](/start/chatgpt) - [Know the cost before you spend](/how-to/cost-before-you-spend) ## Personal videos ### Video invitation Source: https://docs.invideo.io/how-to/personal/video-invitation.md A vertical video invitation, or evite, with your photos, the event details, music and a QR code that opens your RSVP page. You get a vertical video invitation, also called a video invite or an evite, for a birthday, a wedding, a baby shower, a gender reveal or a save the date. It shows your photos or a generated scene, the names, the date, the place and a QR code for the RSVP. You send the MP4 in a chat or by email, and guests watch it on their phones. Use invideo for this when you want to change the date, the venue or a name later: the invitation stays an editable timeline, and a changed invitation is one export away. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a vertical video invitation for Maya's 30th birthday. Use the photos in ./maya. Show "Maya turns 30", "Saturday 14 June, 7 pm", "The Garden Room, 12 Hill Street" and a QR code for https://example.com/rsvp. Add happy music. Show me frames before you export, and tell me the price before you generate anything. ``` In a chat app, you drag your photos into the project's Media panel in invideo, then name them in the chat. In a terminal, you name the folder and the agent uploads it. #### What you need Collect these before you start. The text matters most, so check the spelling of every name. - **The event details.** Who, what, when, where, and the dress code if there is one. - **The RSVP link.** A web page or form for replies. Links in a video are not clickable, so the agent turns the link into a QR code image. - **Photos or clips.** JPG, PNG, MP4 or MOV from your phone. Or ask for a generated background scene instead. - **The shape.** Vertical 9:16 for phones. Ask for 1:1 if you post it in a feed. - **The mood.** Elegant, playful, cute, a theme color. Characters from a film, a show or a game, such as a princess, a superhero or a cartoon dog, belong to their owners, and some image models decline them. Ask for an original look in the same spirit, like "a friendly dinosaur in green and gold". #### Steps Your agent works in your invideo project and tells you what it made at each step. The agent makes a project with `new_project`, a 9:16 timeline with `new_timeline`, and a branch with `timeline_history`, so the main timeline stays as it is. For each local file, it calls `start_upload`, sends the bytes to the `upload_url`, then calls `add_media` with the `upload_id` on the branch URL. Expected result: a branch URL, and one sequence URL and media bin id per photo. The agent makes a QR code image for your RSVP link with its own tool, like a QR code library on your machine, and saves it as a PNG. An image model can redraw the squares, so the agent does not make the code with one. Then it brings the PNG in with `start_upload` and `add_media`. Expected result: a QR code in the media bin. With no photos, the agent finds a scene with `search_library` in `stock_video`, or generates one. To generate, it runs `find_models` with the job in words, like "vertical party background image", and `get_model` on its pick. A good pick is `nanobanana_pro`. Your agent can search for others with `find_models`. It calls `generate` with a `prompt`, `aspect_ratio` 9:16 and `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a background sequence URL, which the agent reads with `read`, never with a second `generate`. The agent places the photos with `place_media` or `insert_media`, fills the frame with `fill_frame`, and adds each line of text with `add_text`. It puts the QR code on a track above with `place_media` and sizes it with `set_zoom` and `set_position`. Fades come from `add_edge_transition` with the `fade` transition. Expected result: a new `state_token` and the clips on the timeline. The agent searches `stock_music` with `search_library`, plays you the previews, and adds your pick with `add_media` and `stock`. It fades the end with `set_audio_fades`. Expected result: music on an audio track that ends with the video. The agent runs `capture` at the title, the details and the QR code, and `check_timeline`. You scan the QR code frame on your screen with your phone. Expected result: every line is readable, no text sits at the edge, and the code opens your RSVP page. The agent runs `export` with `format` video and an `idempotency_key`, then reads the export card until its status is `completed`. In a terminal, it saves the file with `invideo notebook show` on the card's URL. Expected result: a 1080p MP4 you download and send. The same job from a terminal: ```bash invideo project new --title "Maya 30 invite" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Invite" --width 1080 --height 1920 invideo asset upload ./maya/*.jpg ./rsvp-qr.png invideo library search --library stock_music \ --query "happy party" invideo asset add --stock invideo gen models --query "vertical party background image" invideo gen model --model nanobanana_pro invideo gen run --model nanobanana_pro --dry-run \ -i prompt="warm garden party at dusk, string lights" -i aspect_ratio=9:16 invideo gen run --model nanobanana_pro \ --max-credits --idempotency-key maya-bg-1 \ -i prompt="warm garden party at dusk, string lights" -i aspect_ratio=9:16 invideo edit show --json invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 1,5,9 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. `` comes from `library search`. - The `gen` lines are only for a generated background. `` is a notebook page; `invideo notebook show ` lists them. `` is the dry run's `.estimated_credits`. The paid run returns a thread URL; `invideo notebook show` on it lists the image's sequence URL once it lands. - `` comes from `invideo edit show`. `ops.json` holds a bare list of operations, like the `operations` list in the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits and saves nothing. `invideo notebook show` saves the file as `./out/export.mp4`. The key MCP call is the full call. It places the QR code and the details text in one `edit_timeline` call. `` is the `branch_url` that `timeline_history` returns. The `` and the ids, like `m4` for the QR code, come from `get_timeline`. Times ending in `_f` are frames at the timeline's rate. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "place_media", "asset": "m4", "track": "V2", "at_f": 240, "source_start_seconds": 0, "source_end_seconds": 5, "mode": "place_on_top", "linked_audio": false }, { "op": "add_text", "track": "V3", "start_f": 0, "end_f": 390, "text": "Saturday 14 June, 7 pm\nThe Garden Room", "style": { "font_size": 72, "align": "center", "color": "#ffffff", "shadow": true } } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** uploads, the layout, text, transitions, the QR code your agent makes, frame checks and the export. - **Costs credits:** paid stock music or stock video with `add_media`, and any generated background with `generate`. A photo invitation takes a few minutes. A generated background adds the time the model takes. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are the QR code, text at the edge, or a character a model declines. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The QR code does not scan | Make it larger with `set_zoom`, and keep it on a plain background. Scan the `capture` frame again. | | The timeline is not 9:16 | The agent sets the size with `set_timeline_settings`, then `capture` again. | | Text is cut at the edge of a phone | Move it in with `set_position`, and `capture` again. | | A model declines a character | The provider does not allow that character. Ask for an original look in the same colors. | | `edit_timeline` refused as a conflict | The timeline changed since the read. Read it with `get_timeline` and send again with the new token. | | CLI exit 5 | A credit limit. Use your own photos, or check your balance. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: putting the RSVP link as text only | Instead: add the QR code, and paste the link in the message you send with the video. | | Avoid: saying done without looking | Instead: `capture` frames and scan the QR code first. | #### Prompts to try Each prompt is a different kind of invitation. ```text Make a 15 second gender reveal teaser, vertical. Pink and blue balloons, the words "Boy or girl? Find out 3 May" and a QR code for our RSVP form. Soft music. No characters from films. ``` ```text Make an elegant wedding save the date from our engagement photos in ./photos. Gold text, "Priya and Sam, 20.09.2027, Jaipur", a slow fade between photos, and a QR code for our wedding website. ``` ```text Make a baby shower invite in 1:1 for Instagram and 9:16 for WhatsApp, one branch each. Same text, same QR code, gentle music. ``` #### When to use something else A video file cannot hold a link you tap or a reply button. Use your RSVP tool, like a form or an event page, for the replies, and send its link with the video. For a printed card, use a design tool and export a PDF. invideo exports video, not print files. #### Related - [Make a birthday montage from photos and clips](/how-to/personal/birthday-montage) - [Make a photo slideshow for any occasion: anniversary, graduation, retirement, baby's first year, family recap](/how-to/personal/occasion-slideshow) - [Make a personalized video message from Santa or an AI presenter](/how-to/personal/personalized-message-video) - [Make a video with ChatGPT, Claude or Gemini](/how-to/personal/with-chatgpt-claude-gemini) - [Check your video before you say it is done](/how-to/check-your-video) ### Make a birthday montage from photos and clips Source: https://docs.invideo.io/how-to/personal/birthday-montage.md A birthday montage, or birthday slideshow, cut to the beat of the music, with gentle zooms on the photos and a title card. You get a birthday montage, also called a birthday slideshow or photo video, from your photos and phone clips. Each photo and clip changes on a beat of the song, the photos move with a gentle zoom, and a title card opens it with the name and the age. Use invideo for this when you want the cuts to land on the beat without counting them by hand: your agent reads the beats of the song, places every cut on one, and you can still move any photo after on the timeline. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a birthday montage for Leo's 8th birthday from the photos and clips in ./leo. Cut on the beat of a happy song from stock music, add a slow zoom on each photo and open with "Happy 8th birthday, Leo". 16:9 for the TV. Show me frames before you export. ``` In a chat app, you drag your files into the project's Media panel in invideo, then name them in the chat. In a terminal, you name the folder and the agent uploads it. #### What you need Pick the files in the order you like, or let the agent sort them by date. - **Photos and clips.** JPG, PNG, HEIC, MP4 or MOV from a phone or camera. - **The title text.** The name, the age, and a closing line if you want one. - **The song or the mood.** A track from stock music, or your own file if you have the rights to it. - **The shape.** 16:9 for a TV or a laptop, 9:16 for a phone story, 1:1 for a feed. - **The length.** A song length, or a number of seconds. #### Steps Your agent edits on a branch and tells you what changed at each step. The agent makes a project with `new_project`, a timeline with `new_timeline` in the shape you asked for, and a branch with `timeline_history`. For each local file it calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id` on the branch URL. Expected result: a branch URL, and a sequence URL and a media bin id for each file. The agent searches `stock_music` with `search_library`, for example "happy birthday" or "upbeat kids". You listen to the previews and pick one, and the agent adds it with `add_media` and `stock`. Expected result: the song in the media bin. The agent runs `find_models` with the job in words, such as "birthday song that sings a name", and reads its pick with `get_model`. A good pick is `elevenlabs_music_v2_5_song`. Your agent can search for others with `find_models`. It calls `generate` with `prompt`, `duration` and `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then the song's sequence URL, which the agent reads with `read`. The agent reads the beat times with `media` `audio.beats` and the big moments with `audio.sections`, and turns each time into a frame: seconds times the frame rate. Then it places each photo and clip with `insert_media` or `place_media` and moves each cut to a beat with `trim_clip`, all in one `edit_timeline` call. Expected result: every cut on a beat. In one call, the agent adds the `dynamic_zoom` effect to each photo with `add_effect`, and the title with `add_text`. Then it reads the timeline with `get_timeline` for the new ids. In a second call it sets the end zoom with `set_effect_parameter` on the effect's id, for a slow push, and fades the title in with `set_keyframes` on `opacity` on the title clip's id, like `t1`. Expected result: the photos move gently and the title fades in. The agent runs `capture` at the title, a few cuts and the end, and `check_timeline`. It checks that no face is cut off by the zoom. Expected result: frames where every face is in view. The agent runs `export` with `format` video, then reads the export card until its status is `completed`. In a terminal, it saves the file with `invideo notebook show` on the card's URL. Expected result: a 1080p MP4. The same job from a terminal: ```bash invideo project new --title "Leo turns 8" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Montage" invideo asset upload ./leo/* invideo library search --library stock_music \ --query "happy birthday" invideo asset add --stock invideo gen models --query "birthday song that sings a name" invideo gen model --model elevenlabs_music_v2_5_song invideo gen run --model elevenlabs_music_v2_5_song --dry-run \ -i prompt="upbeat kids pop song, sing happy birthday Leo" -i duration=60 invideo gen run --model elevenlabs_music_v2_5_song \ --max-credits --idempotency-key leo-song-1 \ -i prompt="upbeat kids pop song, sing happy birthday Leo" -i duration=60 invideo status --wait invideo media audio.beats invideo edit show invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 0,4,12,24 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. `` comes from `library search`. - The `gen` lines and the `status` line are only for a custom song; skip them for stock. `` is a notebook page; `invideo notebook show ` lists them. `` is the dry run's `.estimated_credits`. - `` is the `url` the paid run returns. `` is the song's sequence URL: the one `asset add` returns, or the one `invideo notebook show ` lists once the song lands. - `` comes from `invideo edit show`. `ops.json` holds a bare list of operations, like the first call's `operations` list below. - `` is `.sequences[0]` of the export result. `invideo status` waits and saves nothing. `invideo notebook show` saves the file as `./out/export.mp4`; rename it after. The key MCP call is the full call. It trims a photo to the next beat, adds the zoom and adds the title. At 30 fps, a beat at 2.4 seconds is frame 72. `` is the `branch_url` that `timeline_history` returns, and `` comes from `get_timeline` on that branch. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "trim_clip", "clip": "c2", "edge": "tail", "from_f": 90, "to_f": 72, "mode": "close_gap", "linked": true }, { "op": "add_effect", "clip": "c2", "effect": "dynamic_zoom" }, { "op": "add_text", "track": "V2", "start_f": 0, "end_f": 90, "text": "Happy 8th birthday, Leo", "style": { "font_size": 96, "align": "center", "shadow": true } } ] } ``` The end zoom needs the effect's id, which only `get_timeline` returns. So the agent reads the timeline, finds the effect's id and the title clip's id, like `t1`, and sends the second call with the new `state_token`. The fade on the title is in it: ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "set_keyframes", "clip": "t1", "property": "opacity", "points": [ { "at_f": 0, "value": 0, "ease": "ease_out" }, { "at_f": 20, "value": 1 } ] } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** uploads, the cuts, the zoom, the title, frame checks and the export. - **Tool ops:** `audio.beats` and `audio.sections`. The dry run shows its price before anything starts. - **Costs credits:** a paid stock song, or a song made with `elevenlabs_music_v2_5_song`. Your own music file costs nothing. A montage takes a few minutes for the agent. Picking the photos and the song takes you longer. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from beats that do not suit the photos, or a zoom that crops a face. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The cuts feel too fast | Ask for a cut on every second or fourth beat. The agent skips beats in the list. | | A face is cut off by the zoom | Lower the end zoom of `dynamic_zoom`, or move its end point onto the face, then `capture` again. | | `trim_clip` refused as stale | The edge moved. Read with `get_timeline` and send the trim with the new `from_f`. | | `audio.beats` finds few beats | The song has a soft beat. Read `audio.markers` for tempo, or pick a song with a clear beat. | | The music ends before the video | Trim the last photo, or ask for a longer song. | | CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild the ops. | | Avoid: the agent edits main | Instead: it works on a branch from `timeline_history`, and you accept the change. | | Avoid: saying done without looking | Instead: `capture` frames at the title, the cuts and the end. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 60 second vertical birthday montage for Grandma's 90th from the old photos in ./grandma. Slow, warm music, a cut on every second beat, and "Happy 90th, Grandma Rose" at the start and the end. ``` ```text Cut my son's year in clips to this song, ./song.mp3. Put the cuts on the strong beats, the fun clips on the chorus, and his name and age on a title card. 16:9. ``` ```text Make a 30 second Instagram story montage of the party clips in ./party. Fast cuts on every beat, a flash transition on the drop, and "Best night ever" at the end. ``` #### When to use something else invideo does not print photo books or cards. Use a print service for those, with stills from the montage made by `export` in `mode` image. If you want the song to react to faces or dance moves, like a CapCut template, see [Make a trend edit like CapCut: slow-mo, meme, freeze frame](/how-to/personal/trend-edit). Templates you bought for CapCut or After Effects do not open in invideo. Your agent rebuilds the look on the timeline instead. #### Related - [Make a photo slideshow for any occasion: anniversary, graduation, retirement, baby's first year, family recap](/how-to/personal/occasion-slideshow) - [Make a video invitation for a birthday, wedding, baby shower or gender reveal](/how-to/personal/video-invitation) - [Make a trend edit like CapCut: slow-mo, meme, freeze frame](/how-to/personal/trend-edit) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Check your video before you say it is done](/how-to/check-your-video) ### Make a vertical travel video from phone clips Source: https://docs.invideo.io/how-to/personal/travel-video.md A vertical travel video, or travel reel, from your phone clips: wide shots reframed to 9:16, music, a route title and text clear of the app buttons. You get a vertical travel video, also called a travel reel or trip recap, from the clips on your phone. Wide clips are reframed to 9:16 so nothing important falls off the side. The video has music, a route title like "Lisbon to Porto to Faro", and text that stays clear of the buttons and captions the app puts on top. Use invideo for this when your clips are a mix of vertical and wide shots: your agent reframes each wide clip on the timeline, keeps the subject in frame, and you can nudge any shot after. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 45 second vertical travel video from the clips in ./portugal. Reframe the wide clips to 9:16 and keep the people in frame. Add upbeat music, the title "Lisbon to Porto to Faro" and keep text out of the Reels buttons. Show me frames before you export. ``` In a chat app, you drag your clips into the project's Media panel in invideo, then name them in the chat. In a terminal, you name the folder and the agent uploads it. #### What you need Pick your best clips. Fewer, better clips make a better reel. - **Clips.** MP4 or MOV from your phone, vertical or wide, in any order. - **The route or the places.** The title text, and a place name per clip if you want labels. - **The platform.** Instagram Reels, TikTok or YouTube Shorts. Each puts its buttons in a different place. - **The music mood.** Upbeat, chill, cinematic, or your own licensed track. - **The length.** A number of seconds, or "the length of the song". #### Steps Your agent edits on a branch and tells you what changed at each step. The agent makes a project with `new_project` and a 9:16 timeline with `new_timeline`. It creates a branch with `timeline_history`. Expected result: a vertical timeline URL on the new branch. The agent uploads each clip with `start_upload` and `add_media`. It runs `media` with `metadata` for each clip's size and length, and `video.frames` to see what is in it. Expected result: a sequence URL per clip, and a note of which clips are wide. For each wide clip, the agent places it with `place_media`, fills the frame with `fill_frame`, then slides it with `set_position` so the person or the view stays in the middle. It uses `set_zoom` to go closer. Expected result: no black bars, and the subject in the middle. The agent runs `find_models` with the job in words, like "reframe a wide video to vertical", and `get_model` on its pick. A good pick is `ltx_2_3_pro.reframe`. Your agent can search for others with `find_models`, such as `luma_ray_32.reframe`, which also needs a `prompt`. These models paint new picture at the edges. They do not track a face. The agent calls `generate` with `video`, `aspect_ratio` 9:16 and `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a new vertical sequence URL to place instead of the wide clip, which the agent reads with `read`, never with a second `generate`. The agent adds guides with `create_guide` ops: one horizontal guide under the top bar, one above the caption area, and one vertical guide left of the buttons. It takes the positions from the platform's own safe zone guide. Expected result: guide lines in the editor that you see too. The agent finds a song with `search_library` in `stock_music` and adds it with `add_media`. It reads the beats with `media` `audio.beats` and trims the cuts to them with `trim_clip`. It adds the route title and place names with `add_text`, inside the guides. Expected result: music under the whole video and text inside the safe area. The agent runs `capture` at the title and at each place name, and `check_timeline`, and looks for no face cut off and no text under the guides. Then it runs `export` with `format` video and reads the card. In a terminal, it saves the file with `invideo notebook show` on the card's URL. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Portugal trip" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Reel" --width 1080 --height 1920 invideo asset upload ./portugal/*.mov invideo media metadata invideo media video.frames --at 0,3,6 --out ./frames invideo gen models \ --query "reframe a wide video to vertical" invideo gen model --model ltx_2_3_pro.reframe invideo gen run --model ltx_2_3_pro.reframe --dry-run \ -i video= -i aspect_ratio=9:16 invideo gen run --model ltx_2_3_pro.reframe \ --max-credits --idempotency-key reframe-c3 \ -i video= -i aspect_ratio=9:16 invideo edit show invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 1,10,20,40 --out ./frames invideo edit export --format video --quality 1080 --json invideo status --wait invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. `` is the URL `invideo asset upload` returns for each clip. - `` is a notebook page; `invideo notebook show ` lists them. `` is the dry run's `.estimated_credits`. `` is the `url` the paid run returns; `invideo notebook show ` lists the new clip's sequence URL once it lands. - `` comes from `invideo edit show`. `ops.json` holds a bare list of operations, like the `operations` list in the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits and saves nothing. `invideo notebook show` saves the file as `./out/export.mp4`. The key MCP call is the full call. It reframes one wide clip by hand and adds the guides. The guide positions below are an example; the agent uses the platform's own spec. `` is the `branch_url` that `timeline_history` returns. The `` and the clip ids, like `c3`, come from `get_timeline`. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "fill_frame", "clip": "c3" }, { "op": "set_position", "clip": "c3", "x": -220, "y": 0 }, { "op": "create_guide", "timeline": "T1", "orientation": "horizontal", "position": 0.1, "locked": true }, { "op": "create_guide", "timeline": "T1", "orientation": "horizontal", "position": 0.8, "locked": true }, { "op": "create_guide", "timeline": "T1", "orientation": "vertical", "position": 0.85, "locked": true }, { "op": "add_text", "track": "V2", "start_f": 0, "end_f": 90, "text": "Lisbon to Porto to Faro", "style": { "font_size": 80, "align": "center", "stroke": true, "stroke_color": "#000000", "stroke_width": 4 } } ] } ``` `set_position` takes canvas pixels from the center, so a negative `x` slides the picture left. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** uploads, the manual reframe with `fill_frame`, `set_position` and `set_zoom`, the guides, text and the export. - **Tool ops:** `metadata`, `video.frames`, `audio.beats` and `video.trim`. The dry run shows its price before anything starts. - **Costs credits:** paid stock music, and the reframe models, which charge per second of the source clip. A reel takes a few minutes with manual reframes. Model reframes add the time the model takes for each clip. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are a subject that leaves the frame, or text under the app's buttons. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | A person walks out of the vertical frame | Split the clip with `split_clip` and set a new `set_position` for each part, or use a reframe model. | | The reframe model is refused for the clip's length or format | Trim the clip with `media` `video.trim` first, and send the shorter file. | | A reframed edge looks invented | It is: the model paints the sides. Use the manual crop for faces and signs. | | Text sits under the like and share buttons | Move it inside the guides with `set_position`, and `capture` again. | | `fill_frame` is refused | The clip's zoom is animated. Remove the animation, or set the size with `set_zoom`. | | CLI exit 5 | A credit limit. Reframe by hand, which is free. | | Avoid: the agent resends `generate` to check on a reframe | Instead: it reads the thread URL, or calls `status`. | | Avoid: saying done without looking | Instead: `capture` frames at every text and every reframed clip. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 30 second TikTok from my Japan clips in ./japan. Fast cuts on the beat, a place name on each clip, and keep everything clear of the TikTok buttons. ``` ```text I have wide drone shots in ./drone. Make a vertical reel, reframe them with a model so nothing is cropped, and tell me the price first. ``` ```text Make a one minute road trip recap from ./roadtrip. Open with a map image I give you, then the title "Route 66, 12 days". Chill music. ``` #### When to use something else invideo does not draw animated route maps from GPS data. Make the map in a map tool, export an image or a clip, and your agent brings it in with `add_media`. For stabilizing very shaky footage, use your phone's own stabilization when you shoot, or a desktop editor. invideo has no stabilize op. #### Related - [Repurpose one video for every platform, one branch each](/how-to/creators/repurpose-for-every-platform) - [Make Reels and Shorts from your footage: hook, captions, transitions, sound effects](/how-to/creators/reels-and-shorts-from-your-footage) - [Make a birthday montage from photos and clips](/how-to/personal/birthday-montage) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Check your video before you say it is done](/how-to/check-your-video) ### Photo slideshow for any occasion Source: https://docs.invideo.io/how-to/personal/occasion-slideshow.md A photo slideshow, or photo video, for an anniversary, a graduation, a retirement, a baby's first year or a family recap, with music, titles and an optional loop. You get a photo slideshow, also called a photo video or a photo montage, for an anniversary, a graduation, a retirement party, a baby's first year or a family year in review. The photos run in order with soft transitions and music, with a title at the start and short captions where you want them. For a party screen, the slideshow can loop for as long as the party runs. Use invideo for this when you have many photos and want to fix one later: every photo stays a clip on an editable timeline, so you swap a photo or a caption without starting over. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 16:9 photo slideshow for my parents' 40th anniversary from the photos in ./anniversary, oldest first. Five seconds a photo, soft fades, gentle music, and "40 years, Anna and Raj" at the start. Make a one hour loop for the party screen. Show me frames before you export. ``` In a chat app, you drag your photos into the project's Media panel in invideo, then name them in the chat. In a terminal, you name the folder and the agent uploads it. #### What you need Sort your photos into a folder first. File names like `01.jpg`, `02.jpg` keep the order you want. - **Photos.** JPG, PNG or HEIC, scans of old prints too. Short clips work as well. - **The order.** By file name, by date, or by chapter (school, wedding, kids). - **The words.** A title, an end line, and captions such as a year or a place. - **The music.** A mood for stock music, or your own licensed file. - **The shape and the screen.** 16:9 for a TV or a projector, 9:16 for a phone, 1:1 for a feed. - **A loop, if needed.** How long it must play at the event. #### Steps Your agent edits on a branch and tells you what changed at each step. The agent makes a project with `new_project`, a timeline with `new_timeline` in your shape, and a branch with `timeline_history`. It uploads each photo with `start_upload` and `add_media` on the branch URL. Expected result: a branch URL, and every photo in the media bin with an id. For a small or soft scan, the agent runs `find_models` with the job in words, like "upscale an old photo scan", and `get_model` on its pick. A good pick is `crystal_upscaler`. Your agent can search for others with `find_models`. It calls `generate` with `source_image` set to the scan's sequence URL, `scale_factor` 2 and `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. The original stays. Expected result: a sequence URL for the sharper image, which the agent reads with `read`, never with a second `generate`. The agent places the photos with `insert_media` and `ripple` true, then sets each one's length with `trim_clip`. It sends them in one `edit_timeline` call. Portrait photos in a wide frame get the `fit_with_blur` effect with `add_effect`, so there are no black bars. Expected result: one clip per photo, in order, each the length you asked. The agent adds a `fade` or `light_leak` transition between photos with `add_transition`. It adds the title, captions and the end line with `add_text`. Expected result: soft changes between photos and text on the right photos. The agent finds a track with `search_library` in `stock_music` and adds it with `add_media`. It reads the beats with `media` `audio.beats` if you want the changes on the beat, and fades the end with `set_audio_fades`. Expected result: music that ends with the last photo. For a party screen, the agent puts the whole slideshow into one clip with `nest_clips` in `mode` nest. It copies that clip with `duplicate_clip` until the timeline is long enough, and adds a `fade` between the copies with `add_transition`. Expected result: one timeline that plays as long as the event. The agent runs `capture` at the title, a few photos, a loop seam and the end, and `check_timeline`, and looks for every face in frame, readable text and no black frame at the seam. Then it runs `export` with `format` video and reads the card. In a terminal, it saves the file with `invideo notebook show` on the card's URL. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Anna and Raj, 40 years" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Slideshow" invideo asset upload ./anniversary/*.jpg invideo gen models --query "upscale an old photo scan" invideo gen model --model crystal_upscaler invideo gen run --model crystal_upscaler --dry-run \ -i source_image= -i scale_factor=2 invideo gen run --model crystal_upscaler \ --max-credits --idempotency-key scan-1 \ -i source_image= -i scale_factor=2 invideo library search --library stock_music \ --query "gentle piano" invideo asset add --stock invideo edit show invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 0,30,120,600 --out ./frames invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. `` comes from `library search`. - The `crystal_upscaler` lines are only for a small scan. `` is the URL `invideo asset upload` returns for that photo. `` is a notebook page; `invideo notebook show ` lists them. `` is the dry run's `.estimated_credits`. - `` comes from `invideo edit show`. `ops.json` holds a bare list of operations, like the `operations` list in the calls below. - `` is `.sequences[0]` of the export result. `invideo status` waits and saves nothing. `invideo notebook show` saves the file as `./out/export.mp4`. To loop a finished file instead of the timeline, the CLI runs `video.loop` on its sequence URL. The dry run shows its price before anything starts. ```bash invideo media video.loop --target-duration 3600 --dry-run invideo media video.loop --target-duration 3600 \ --max-credits --idempotency-key loop-1 ``` `` is an export's ``, or the URL `invideo asset upload` returns. `` is the `credits` value of the dry run. The key MCP calls are full calls. They nest the slideshow into one clip, copy it, and fade between the copies. `` is the `branch_url` that `timeline_history` returns, and each `` comes from `get_timeline` on that branch. The agent reads the timeline between calls, so each call uses the real id of the nested clip and its copy. The first call nests the photos: ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "nest_clips", "video_clips": ["c1", "c2", "c3", "c4"], "audio_clips": ["a1"], "name": "Slideshow", "mode": "nest" } ] } ``` The second call copies the nested clip, here `c9` from `get_timeline`: ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "duplicate_clip", "clip": "c9" } ] } ``` The third call adds the fade between `c9` and the copy, whose id, like `c10`, comes from `get_timeline`: ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "add_transition", "left_clip": "c9", "right_clip": "c10", "type": "fade", "in_f": 15, "out_f": 15 } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** uploads, the layout, transitions, text, the loop with `nest_clips` and `duplicate_clip`, and the export. - **Tool ops:** `audio.beats` and `video.loop`. The dry run shows its price before anything starts. - **Costs credits:** paid stock music, and a sharper scan with `crystal_upscaler`. Your own music file costs nothing. A slideshow of many photos takes the agent a few minutes. A long loop takes longer to export. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are the photo order, black bars, or a jump at the loop seam. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | A photo is missing from the media bin | The agent names the file and asks you for it, then uploads it with `add_media`. | | Photos are in the wrong order | Rename the files `01`, `02` and so on, or tell the agent the order. It moves clips with `reorder_clip`. | | Black bars beside a portrait photo | Add the `fit_with_blur` effect, or fill the frame with `fill_frame` if the crop is fine. | | The music stops before the loop ends | The agent nests the music with the photos, so each copy has its own music. | | A jump at the loop seam | Lengthen the `fade` at the seam with `resize_transition`, and `capture` the seam again. | | `add_transition` refused | The two clips must touch on one track with no gap. The agent closes the gap first. | | CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild the ops. | | Avoid: one `edit_timeline` call per photo | Instead: one call with all the photo ops. It lands all or none. | | Avoid: saying done without looking | Instead: `capture` the title, faces, and the loop seam. | #### Prompts to try Each prompt is a different occasion. ```text Make a graduation slideshow for Mia from ./mia, kindergarten to graduation day. A caption with the school year on each chapter, and "Congratulations, Class of 2027" at the end. 16:9. ``` ```text Make a baby's first year video, one photo per month from ./baby, with "Month 1" to "Month 12" on each. Soft lullaby music. Vertical for my phone. ``` ```text Make a retirement slideshow for Tom from the team photos in ./tom. Fun music, a light leak between photos, and a two hour loop for the party screen. ``` #### When to use something else invideo does not scan or restore damaged prints. Scan old photos with a phone scanning app first. For a sharper scan, the agent can run `media` `image.upscale`, which invents fine detail. The dry run shows its price before anything starts. To play the loop at the venue without the internet, see [Make a memorial slideshow that loops and plays offline at the venue](/how-to/personal/memorial-slideshow) for the download and player checks. #### Related - [Make a memorial slideshow that loops and plays offline at the venue](/how-to/personal/memorial-slideshow) - [Make a birthday montage from photos and clips](/how-to/personal/birthday-montage) - [Animate a photo, or make a pet memorial from one picture](/how-to/personal/animate-a-photo) - [Make a video with ChatGPT, Claude or Gemini](/how-to/personal/with-chatgpt-claude-gemini) - [Check your video before you say it is done](/how-to/check-your-video) ### Animate a photo Source: https://docs.invideo.io/how-to/personal/animate-a-photo.md Bring a still photo to life with gentle motion, for a family photo or a pet memorial, and keep the face as it was. You get a short video from one still photo: a grandparent who smiles and blinks, a dog whose ears lift in the wind, a slow drift of light across an old portrait. People call this "animate a photo", "photo to video" or "living photo". For a pet memorial, the clip can loop, with the pet's name and dates on screen. Use invideo for this when the face must stay the same: your agent picks an image-to-video model, asks it for small motion only, compares the frames with your photo, and you can fall back to a free slow zoom that changes nothing. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Animate ./biscuit.jpg, our dog Biscuit. Gentle motion only: his ears move, he blinks, soft light. Do not change his face or his markings. Add "Biscuit, 2012 to 2026" at the end. Tell me the price before you generate, and show me frames next to the photo. ``` In a chat app, you drag the photo into the project's Media panel in invideo, or attach it to the chat. In a terminal, you name the file and the agent uploads it. #### What you need One good photo matters more than anything else. - **One photo.** JPG or PNG, sharp, with the face clear and not cut at the edge. - **The motion you want.** Small and slow works best: a blink, a breath, hair in the wind, a slow camera push. - **The words, if any.** A name, dates, a short line. - **The shape.** The model keeps the photo's shape. Say if you need 9:16 or 16:9. - **Music or sound, if any.** Soft music from stock, or silence. #### Steps Your agent prices every generation first and tells you what it made. The agent makes a project with `new_project`, then brings the photo in with `start_upload` and `add_media`, or with `file` if you attached it to the chat. Expected result: a sequence URL for the photo. The agent runs `find_models` with `output` video and the job in words, like "animate one photo with small motion", then `get_model` on its pick. A good pick is `wan_27_alibaba.wan_27_i2v`. Your agent can search for others with `find_models`, such as `kling_v3_omni_video.frames` or `seedance_2_5.frames`, which also take the photo as the first frame. Expected result: the model's inputs. The agent runs `generate` with `dry_run` true, the photo as the first frame, and a short prompt for small motion. It asks for no change to the face, in the prompt or in a negative prompt where the model has one. Expected result: the price, which the agent tells you. For a price of 1 credit or more it waits for your yes. Then the agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. It reads the thread with `read`, and never calls `generate` again to check on it. Expected result: a thread URL, then the new video's sequence URL. The agent runs `media` `video.frames` on the new video at the start, the middle and the end, and compares each frame with the photo by eye. Expected result: the same face, eyes and markings. The agent makes a timeline with `new_timeline`, places the clip with `place_media`, and adds the name and dates with `add_text`. For a loop, it runs `media` `video.loop` with `target_duration`. Expected result: a timeline URL with the clip and the words. The agent runs `capture` at the start, the text and the end, and `check_timeline`. Then it runs `export` with `format` video. In a terminal, it waits with `invideo status` on the card's URL, then saves the file with `invideo notebook show --out ./out`. Expected result: an export card with status `completed`. The same job from a terminal. The dry run comes first and spends nothing. ```bash invideo project new --title "Biscuit" invideo agent register --name export INVIDEO_AS= invideo asset upload ./biscuit.jpg invideo gen models --query "animate one photo with small motion" invideo gen model --model wan_27_alibaba.wan_27_i2v invideo gen run --model wan_27_alibaba.wan_27_i2v --dry-run \ -i first_frame= -i duration=6 \ -i prompt="ears move gently in a breeze, he blinks once" invideo gen run --model wan_27_alibaba.wan_27_i2v \ --max-credits --idempotency-key biscuit-1 \ -i first_frame= -i duration=6 \ -i prompt="ears move gently in a breeze, he blinks once" invideo status --wait invideo media video.frames --at 0,3,5.9 --out ./frames ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`. `` is the URL `invideo asset upload` returns for the photo. - `` is a notebook page; `invideo notebook show ` lists them. `` is the dry run's `.estimated_credits`. - `` is the `url` the paid run returns. `` is the new video's sequence URL, which `invideo notebook show ` lists once it lands. The key MCP call is the dry run. The input names come from `get_model` for this model. `` is a notebook page from `read` on the project, and `` is the URL `add_media` returns. ```json { "url": "", "model": "wan_27_alibaba.wan_27_i2v", "dry_run": true, "inputs": { "first_frame": "", "prompt": "Ears move gently in a breeze, he blinks once, soft light", "negative_prompt": "face change, new markings, extra limbs", "duration": "6", "resolution": "1080p" } } ``` ##### The free option: a slow zoom When the face must not change at all, the agent does not generate. It places the photo on a timeline and adds the `dynamic_zoom` effect with `add_effect`, for a slow push in. This is free, and every pixel stays your photo. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** the image-to-video model, priced per second of video. A second try costs again. - **Free:** the upload, the slow zoom, text and the export. - **Tool ops:** `video.frames` and `video.loop`. The dry run shows its price before anything starts. A generation takes a few minutes. It can take a few tries before the motion feels right. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are too much motion or a face that changes. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `video.frames` shows the face or the markings change | Ask for less motion, add the change to the negative prompt, or use the free slow zoom. | | The motion looks wild | Shorten the prompt to one small action, and pick a shorter `duration`. | | The model refuses the photo | Read the refusal `message`. Small or odd-shaped photos fail; resize with `media` `image.resizeFit` and try again. | | CLI exit 5 | A credit limit. Use the free slow zoom, or check your balance. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | Avoid: the agent calls `generate` again to check on it | Instead: it reads the thread URL, or calls `status`. | | Avoid: saying done without comparing | Instead: `video.frames` next to the photo, then you look too. | #### Prompts to try Each prompt is a real variation of the job. ```text Animate this old wedding photo of my grandparents. Only a slow camera push and a soft light flicker. No change to their faces. 16:9. ``` ```text Make a 30 second memorial loop for our cat Luna from ./luna.jpg. A gentle blink and breathing, her name and "Forever in our hearts". Soft piano. Price first. ``` ```text Make three takes of ./portrait.jpg with different small motions, name them "Take 1 · blink", "Take 2 · smile", "Take 3 · breeze", and let me pick one. ``` #### When to use something else invideo does not restore torn or faded prints. Use a photo restoration tool first, then animate the restored file. If you want the person in the photo to talk, see [Make a personalized video message from Santa or an AI presenter](/how-to/personal/personalized-message-video). A talking photo needs a voice and an avatar model, not an image-to-video model. #### Related - [Make a personalized video message from Santa or an AI presenter](/how-to/personal/personalized-message-video) - [Make a memorial slideshow that loops and plays offline at the venue](/how-to/personal/memorial-slideshow) - [Make a photo slideshow for any occasion: anniversary, graduation, retirement, baby's first year, family recap](/how-to/personal/occasion-slideshow) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Models](/reference/models) ### Make a personalized video message from Santa or an AI presenter Source: https://docs.invideo.io/how-to/personal/personalized-message-video.md A personalized video message where Santa or an AI presenter says your child's or friend's name, with the name on screen too. You get a personalized video message, also called a custom greeting video or a video from Santa, where a talking Santa or an AI presenter says the person's name and a few lines you write. The name also shows on screen, so it reads right even if the voice says it a little off. It works for a Christmas message, a birthday shout-out, a trip reveal or a thank-you. Use invideo for this when you want to hear the voice and fix the name before you pay for the video: your agent makes the voice first, you listen, and only then does it make the talking presenter. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 30 second vertical video message from Santa for my son Arjun, age 6. Santa says he heard Arjun was kind to his little sister and that he should keep practicing piano. Use an original Santa, a warm older voice, and "Merry Christmas, Arjun" on screen. Let me hear the voice and tell me the price before you make the video. ``` In a chat app, you write the lines in the chat, and drag any photo into the project's Media panel in invideo. In a terminal, you name the files and the agent uploads them. #### What you need The words and the name matter most. Write the name the way it sounds if it is unusual. - **The script.** Four to six short sentences, with the name and one or two real details. - **The name and how to say it.** For example "Siobhan, said shi-VAWN". - **The presenter.** An original Santa, an AI presenter, or a photo of a person who agreed to it. - **The voice.** Warm, cheerful, calm, an accent. Not the voice of an actor or a film character. - **The shape.** 9:16 for a phone, 16:9 for a TV. invideo sets no rule of its own on likeness. Each model provider does: some models decline to clone a real person's voice or face, others allow it with consent. Characters from a film, a show or a brand belong to their owners, and the rights are yours to clear. The safe ask is an original Santa or presenter. #### Steps Your agent makes the voice first, so you hear the name before it makes the video. The agent writes the lines with the name in them, spelled by sound when it is unusual, and reads them back to you. Expected result: a script you approve. The agent runs `find_models` with the job in words, like "warm text to speech voice", and `get_model` on its pick. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, or `seed_tts_2_0`. Your agent can search for others with `find_models`. It searches that model's own voice library with `search_library`, for example "warm older man": `elevenlabs_text_to_speech_voices` for the ElevenLabs model, `seed_tts_2_0_voices` for Seed TTS. A voice id works only with its own model. You play the previews and pick one. Expected result: a voice id. The agent runs `generate` with the script, the voice id and `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. You listen to the name. Expected result: the voice's sequence URL, which the agent reads with `read`, never with a second `generate`. For an original Santa, the agent runs `find_models` with the job in words, like "portrait image of an original Santa", and `get_model` on its pick. A good pick is `nanobanana_pro`. Your agent can search for others with `find_models`. It calls `generate` with a `prompt`, `aspect_ratio` 9:16 and `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. For a real person, it brings in their photo with `start_upload` and `add_media` instead. Expected result: an image's sequence URL with a clear, front-facing face, which the agent reads with `read`. The agent runs `find_models` with the job in words, like "talking avatar from a photo and a voice", and `get_model` on its pick. A good pick is `heygen_photo_avatar`, which takes `image`, `audio` and `aspect_ratio`. Your agent can search for others with `find_models`, such as `kling_avatar.std`, which takes `image`, `audio` and a `prompt`. It calls `generate` with the image, the voice and `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: the talking video's sequence URL, as long as the voice, which the agent reads with `read`, never with a second `generate`. The agent makes a timeline with `new_timeline`, places the video with `place_media` and `linked_audio` true, and adds the name with `add_text`. It can add soft music from `stock_music` under the voice with the `ducker` audio effect. A new timeline ducks under `A1` by default. The agent sets `set_sidechain_source` only when the voice is on another track. Expected result: the name on screen while it is said. The agent runs `capture` at the start, the name and the end, and `media` `video.frames` on the talking video to check the mouth and eyes. Then it runs `export` with `format` video. In a terminal, it saves the file with `invideo notebook show` on the card's URL. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Santa for Arjun" invideo agent register --name export INVIDEO_AS= invideo gen models --query "warm text to speech voice" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo library search \ --library elevenlabs_text_to_speech_voices --query "warm older man" invideo gen run --dry-run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ -i prompt=@script.txt -i voice_id= invideo gen run --max-credits \ --idempotency-key arjun-voice-1 \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ -i prompt=@script.txt -i voice_id= invideo status --wait invideo gen models \ --query "talking avatar from a photo and a voice" invideo gen model --model heygen_photo_avatar invideo gen run --dry-run --model heygen_photo_avatar \ -i image= -i audio= \ -i aspect_ratio=9:16 invideo gen run --max-credits \ --idempotency-key arjun-video-1 --model heygen_photo_avatar \ -i image= -i audio= \ -i aspect_ratio=9:16 invideo status --wait invideo edit new --name "Message" --width 1080 --height 1920 invideo edit show invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. `` comes from the `library search` line. - `` is a notebook page; `invideo notebook show ` lists them. Each `` is the `.estimated_credits` of the dry run before it. - `` is the `url` each paid run returns. `` and the talking video's URL are the sequences `invideo notebook show ` lists once each lands. - `` is the presenter image: the URL `invideo asset upload` returns for a photo, or the sequence a `nanobanana_pro` run makes with the same dry run and paid run pattern. - `` comes from `invideo edit show`. `ops.json` holds a bare list of operations: `place_media` for the talking video and `add_text` for the name. - `` is `.sequences[0]` of the export result. `invideo status` waits and saves nothing. `invideo notebook show` saves the file as `./out/export.mp4`. The key MCP call is the full `generate` call that makes the talking video, as a dry run first. `` is a notebook page from `read` on the project. The two sequence URLs are the image and the voice the earlier steps made. ```json { "url": "", "model": "heygen_photo_avatar", "dry_run": true, "inputs": { "image": "", "audio": "", "aspect_ratio": "9:16", "expressiveness": "medium" } } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** the voice, a generated presenter image, the avatar video, priced per second of voice, and paid stock music. - **Free:** voice previews, the timeline, the name on screen, `capture` and the export. - **Tool ops:** `video.frames`. The dry run shows its price before anything starts. The voice takes under a minute. The avatar video takes a few minutes. Making the voice first saves money, because a wrong name costs a voice, not a video. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are the name, the mouth, or a model that declines a likeness. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The voice says the name wrong | Spell it by sound in the script and make the voice again. The name on screen stays right. | | The mouth does not match the words | Try the other avatar model, or a photo with the face straight on and the mouth closed. | | A model declines a voice or a face | That model's provider does not allow that likeness. Read the refusal `message`, try a model whose rules allow it, or ask for an original look. | | Status `needs_confirmation` | Only you can confirm it, in invideo. Open the URL the agent gives you. | | CLI exit 5 | A credit limit. Check your balance on the credits page. | | Avoid: making the video before you hear the voice | Instead: voice first, then the avatar. | | Avoid: the agent resends `generate` after a timeout | Instead: it reads the thread, or retries with the same `idempotency_key`. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a birthday shout-out from a friendly AI presenter for my friend Kofi. She says happy birthday and mentions his trip to Lisbon. 1:1, with "Happy birthday, Kofi" on screen. ``` ```text Make a trip reveal for my parents. A presenter says "Pack your bags, you are going to Kyoto in April". End on a photo of Kyoto from stock. Vertical. ``` ```text Make the same Santa message for three kids, Ava, Leo and Noor, one branch each. Only the name and one detail change. Let me hear each name first. ``` #### When to use something else For a message from a real celebrity, use a service where the person records it themselves. Cloning a real person's voice or face depends on the model provider's rules and on the person's consent, which is yours to get. For many messages from one recording, like sales videos, see [Make a personalized video for every prospect from one recording](/how-to/marketing/sales-outreach-video). This page is for a few personal messages. #### Related - [Animate a photo, or make a pet memorial from one picture](/how-to/personal/animate-a-photo) - [Make a video invitation for a birthday, wedding, baby shower or gender reveal](/how-to/personal/video-invitation) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Licensing and commercial use](/account/commercial-use) ### Make a wedding video from guest clips Source: https://docs.invideo.io/how-to/personal/wedding-video.md A wedding highlight video, or wedding film, from the clips your guests filmed, with the vows, the speeches, music and a new branch for each round of changes. You get a wedding highlight video, also called a wedding film or wedding recap, from the clips your guests filmed on their phones. Your agent finds the vows and the best lines of the speeches in a transcript, picks the cheers and the first dance by their sound, cuts them to music, and keeps each round of your changes on its own branch. Use invideo for this when the footage is many large files from many phones: your agent uploads them straight to your project, reads every word said, and you can ask for "shorter speeches" or "more of Grandma" without losing the cut before. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 4 minute wedding highlight video from the guest clips in ./wedding. Find our vows and the best lines from the speeches, keep the first kiss and the first dance, and add soft music under the rest. 16:9. Tell me the price of the transcripts first, and show me frames before you export. ``` In a chat app, you drag the clips into the project's Media panel in invideo, then name them in the chat. In a terminal, you name the folder and the agent uploads it. #### What you need Collect every guest clip in one folder first, from a shared album or a drive. - **The clips.** MP4 or MOV from phones and cameras, any size, any shape. - **The moments that must be in.** The vows, the kiss, the first dance, a speech, a name. - **The names.** Who gave which speech, so the agent can find them. - **The length.** A highlight of a few minutes, or a longer film. - **The music mood.** Romantic, upbeat, acoustic, or your own licensed song. - **The shape.** 16:9 for a TV, 9:16 for a phone teaser. #### Steps Your agent edits on a branch and starts a new branch for each round of changes. The agent makes a project with `new_project`. For each file, it calls `start_upload`, PUTs the bytes to the `upload_url`, then calls `add_media` with the `upload_id`. Large files upload this way with no link needed. Expected result: a sequence URL per clip. The agent prices `audio.transcript` with `dry_run` on each clip with speech and tells you the total. It starts each one with `max_credits`, and calls again after `retry_after_s` for the words. Only the first call spends credits. Expected result: every word said, with its time and speaker. The agent reads the transcripts for the vows and the best speech lines, and runs `media` `audio.content`, `audio.onsets` and `video.sceneSplit` to find cheers, claps, the glass clink and the cuts. It runs `video.frames` at each pick to check the picture: eyes open, not shaky, people in frame. Expected result: a shot list with clip, start and end, which the agent shows you. For a vow clip with wind or crowd noise, the agent runs `find_models` with the job in words, like "clean the voice in a video", and `get_model` on its pick. A good pick is `clean_voice.clean_video`. Your agent can search for others with `find_models`. It calls `generate` with `video` set to the clip's sequence URL, `keep_music` true and `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. The original stays. Expected result: a sequence URL for a new, cleaner video, which the agent reads with `read`, never with a second `generate`. The agent makes a timeline with `new_timeline` and creates a branch with `timeline_history`. It places each pick with `place_media`, the source range from the shot list, and `linked_audio` true for the vows and speeches. Vertical guest clips get the `fit_with_blur` effect. Expected result: a first cut on its own branch. The agent adds music from `stock_music` with `search_library` and `add_media`, with the `ducker` audio effect on the music track, so the music drops under speech. A new timeline ducks under `A1` by default. The agent sets `set_sidechain_source` only when the speech is on another track. It adds your names and the date with `add_text`. Expected result: music under the cut and quiet under every line. The agent runs `capture` at the vows, each speech, the kiss and the end, and `check_timeline`. It checks loudness with `media` `audio.loudness` on the speech clips. Then it runs `export` with `format` video and `target_lufs`. In a terminal, it saves the file with `invideo notebook show` on the card's URL. Expected result: an export card with status `completed`. For each round of changes you ask for, the agent saves a checkpoint with `timeline_history` and creates a new branch, like "round-2-shorter-speeches". You compare the branches in the editor, and the earlier round stays untouched. The same job from a terminal. `asset upload` sends each local file for you. ```bash invideo project new --title "Sara and Tom wedding" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Highlight" invideo asset upload ./wedding/* invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo media audio.transcript invideo media audio.content invideo media audio.onsets invideo media video.frames --at 312,318,325 --out ./frames invideo gen models --query "clean the voice in a video" invideo gen model --model clean_voice.clean_video invideo gen run --model clean_voice.clean_video --dry-run \ -i video= -i keep_music=true invideo gen run --model clean_voice.clean_video \ --max-credits --idempotency-key vows-clean-1 \ -i video= -i keep_music=true invideo edit show invideo branch new --name round-1 --token invideo edit show invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 10,60,120,230 --out ./frames invideo edit export --format video --quality 1080 \ --target-lufs -14 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. `` is the URL `invideo asset upload` returns for each clip. The third `audio.transcript` line is the call again after `retry_after_s`. - `` is a notebook page; `invideo notebook show ` lists them. Each `` is the `.estimated_credits` of the dry run before it. - `` comes from `invideo edit show ` for `branch new`, and from `invideo edit show ` for every command on the branch; the main token is stale there. `` is the `.branch_url` that `branch new` returns. - `ops.json` holds a bare list of operations, like the `operations` list in the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits and saves nothing. `invideo notebook show` saves the file as `./out/export.mp4`. The key MCP call is the full call. It places the vows from one guest clip with its sound, and the kiss from another. Source times are seconds from the transcript. `` is the `branch_url` that `timeline_history` returns. The `` and the bin ids, like `m3`, come from `get_timeline`. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "place_media", "asset": "m3", "track": "V1", "at_f": 0, "source_start_seconds": 312.4, "source_end_seconds": 341.0, "mode": "append", "linked_audio": true }, { "op": "place_media", "asset": "m7", "track": "V1", "at_f": 0, "source_start_seconds": 88.2, "source_end_seconds": 94.5, "mode": "append", "linked_audio": true } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** `audio.transcript` on each clip, `clean_voice.clean_video` on a noisy clip, and paid stock music. The agent transcribes only the clips with speech you want. - **Free:** uploads, every cut, the branches and the export. - **Tool ops:** `audio.content`, `audio.onsets`, `video.sceneSplit`, `video.frames`, `audio.loudness` and `audio.clean`. The dry run shows its price before anything starts. Uploads take as long as your connection needs. Transcripts take a few minutes. The first cut takes from a few minutes to under an hour, by the number of clips. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are uploads, quiet speeches, or wind noise on a phone mic. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | A direct link download is refused | Use `start_upload` and `add_media` with the `upload_id`. Large files and private drives go that way. | | The transcript call returns a status, not words | It is still running. Call it again after `retry_after_s`. Only the first call spends credits. | | An upload breaks | The agent starts a new `start_upload` for that file only. | | A speech is too quiet | Raise it with `set_audio_gain` on its audio clip, and add the `compressor` audio effect. | | Wind or crowd noise over the vows | Run `media` `audio.clean` on that clip, priced first. The original stays. | | A guest clip is sideways | The agent turns it with `set_rotation` and fills the frame. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: transcribing every clip | Instead: run `audio.content` first, and transcribe only clips with speech. | | Avoid: changing the approved cut in place | Instead: a new branch for each round from `timeline_history`. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 60 second vertical wedding teaser for Instagram from the highlight branch. The kiss, the first dance and the loudest cheer, cut on the beat. ``` ```text Make a 20 minute wedding film from ./wedding. Full vows, full speeches from the best man and the bride's mother, and the first dance. Name each speaker on screen. ``` ```text Round 3: cut the best man's speech to his three best lines, add more of Grandma dancing, and keep the rest as it is. New branch. ``` #### When to use something else invideo does not sync many cameras into one multicam edit. For a full ceremony from several pro cameras, use a desktop editor with multicam, like Premiere Pro or DaVinci Resolve. Your agent can export the cut as a project file for that editor with `export` and `format` `premiere`, `davinci` or `final_cut`. For a shared album where guests upload their own clips, use a photo sharing app. Then download the folder and bring it in. #### Related - [Make a sports highlight reel, including college recruiting videos](/how-to/personal/sports-highlight-reel) - [Make a photo slideshow for any occasion: anniversary, graduation, retirement, baby's first year, family recap](/how-to/personal/occasion-slideshow) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Make a memorial slideshow that loops and plays offline at the venue Source: https://docs.invideo.io/how-to/personal/memorial-slideshow.md A memorial or funeral slideshow, a celebration of life video, that loops for the whole service and plays from a file with no internet at the venue. You get a memorial slideshow, also called a funeral slideshow or a celebration of life video, from your photos and clips. It runs with soft music and the person's name and dates, loops for the whole visitation or reception, and plays from an MP4 file on a USB stick or a laptop, with no internet at the venue. Use invideo for this when you need it right the first time and on the day: every photo stays editable until the last minute, your agent makes one long looped file, and you download it to play offline. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a memorial slideshow for my father, James Okafor, 1948 to 2026, from the photos in ./dad, oldest first. Six seconds a photo, slow fades, gentle piano, "In loving memory" at the start. Make it loop for two hours, export it as an MP4 and save it to ./usb. Show me frames before you export. ``` In a chat app, you drag the photos into the project's Media panel in invideo, then name them in the chat. Then you download the file from the export card. In a terminal, you name the folder, and the agent saves the file for you. #### What you need Ask family for photos early. Scans of old prints work well. - **Photos and clips.** JPG, PNG, HEIC, MP4 or MOV. Name them `01.jpg`, `02.jpg` to keep the order. - **The words.** The full name, the dates, a short line or a verse, and captions if you want them. - **The music.** A gentle mood from stock music, or a favorite song you have the rights to play. - **The venue's screen.** A TV with a USB port, a projector with a laptop, or a media player. Ask the venue which. - **How long it must play.** The length of the visitation or the reception. - **The shape.** 16:9 for almost every TV and projector. #### Steps Your agent edits on a branch, so the family can review before anything is final. The agent makes a project with `new_project` and a 16:9 timeline with `new_timeline`, then creates a branch with `timeline_history`. It uploads the photos with `start_upload` and `add_media`, places them in order with `insert_media`, and sets each one's length with `trim_clip`. Expected result: one clip per photo, in order. For a small or soft scan, the agent runs `find_models` with the job in words, like "upscale an old photo scan", and `get_model` on its pick. A good pick is `crystal_upscaler`. Your agent can search for others with `find_models`. It calls `generate` with `source_image` set to the scan's sequence URL, `scale_factor` 2 and `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, and swaps the new image in on the timeline. The original stays. Expected result: a sequence URL for the sharper image, which the agent reads with `read`, never with a second `generate`. The agent adds the name, the dates and the opening line with `add_text`, and a `fade` between photos with `add_transition`. It adds a track from `stock_music` with `search_library` and `add_media`, and fades it out with `set_audio_fades`. Portrait photos get the `fit_with_blur` effect. Expected result: a slideshow that runs once from start to end. The agent runs `capture` at the title, at faces, and at the end, and `check_timeline`. It gives you the timeline URL to share for review. Expected result: frames you and the family approve. The agent runs `export` with `format` video, `quality` 1080 and an `idempotency_key`. It reads the export card until its status is `completed`. Expected result: a 1080p MP4 of one pass. The export card is a sequence, so the agent runs `media` `video.loop` on the card's URL as it is, with `target_duration` set to the event length in seconds and an `idempotency_key`. The dry run shows its price before anything starts. Expected result: one long MP4 sequence that repeats the slideshow. In a terminal, the agent saves the looped file with `invideo notebook show` and `--out`, then renames `export.mp4` to a name like `james-memorial.mp4`. In a chat app, you download it from the sequence, whose `file` link `read` returns. You copy it to a USB stick or the laptop, play it on the venue's TV or player from start to end, and turn on the player's repeat setting as a backup. Expected result: the file plays, the sound is right, and the text fits the screen. The same job from a terminal: ```bash invideo project new --title "James Okafor memorial" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Memorial" invideo asset upload ./dad/* invideo gen models --query "upscale an old photo scan" invideo gen model --model crystal_upscaler invideo gen run --model crystal_upscaler --dry-run \ -i source_image= -i scale_factor=2 invideo gen run --model crystal_upscaler \ --max-credits --idempotency-key scan-1 \ -i source_image= -i scale_factor=2 invideo edit show invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 0,30,90,300 --out ./frames invideo edit export --format video --quality 1080 \ --idempotency-key james-1 --json invideo status --wait invideo notebook show --out ./usb invideo media video.loop --target-duration 7200 --dry-run invideo media video.loop --target-duration 7200 \ --max-credits --idempotency-key james-loop-1 invideo status --wait invideo notebook show --out ./usb/loop ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. `` comes from `invideo edit show`. - The `crystal_upscaler` lines are only for a small scan. `` is the URL `invideo asset upload` returns for that photo. `` is a notebook page; `invideo notebook show ` lists them. `` is the dry run's `.estimated_credits`, or `credits` on the `video.loop` dry run. - `ops.json` holds a bare list of operations, such as `insert_media`, `trim_clip`, `add_text` and `add_transition`. - `` is `.sequences[0]` of the export result. `` is the URL the paid `video.loop` run returns. - `invideo notebook show` saves the export as `./usb/export.mp4`, whatever `--file-name` says. Rename each file after it lands. The key MCP call is the full `media` call that makes the long loop from the exported video. `` is the export card's URL, from the `export` result. ```json { "url": "", "op": "video.loop", "target_duration": 7200, "idempotency_key": "james-loop-1" } ``` To loop on the timeline instead, the agent nests the slideshow with `nest_clips`, copies it with `duplicate_clip`, and adds a `fade` at each seam with `add_transition`. Then one export has the whole loop. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** uploads, the slideshow, the export and the download. - **Tool ops:** `video.loop`. The dry run shows its price before anything starts. - **Costs credits:** paid stock music, and a sharper scan with `crystal_upscaler`. Your own music file costs nothing. The slideshow takes the agent a few minutes. A long export and loop take longer, so make the file well before the service. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems happen at the venue, so test the file there before the day. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The venue TV does not open the file | Try the laptop with a video player app, or ask the venue for a media player. Keep a second copy on the laptop. | | The file is too big for the USB stick | Use a larger stick, or loop for less time and turn on the player's repeat setting. | | The download link stopped working | Download links expire. `read` the export card or the sequence again for a new one. | | The music is too loud in the room | Export again with a lower `target_lufs`, or turn the venue volume down. | | A jump where the loop repeats | Add a fade to black at the start and the end with `add_edge_transition`, then export and loop again. | | Status `failed` on the export | The agent reads the card for the reason, fixes it, and exports once more with a new `idempotency_key`. | | Avoid: playing from the export page at the venue | Instead: play the downloaded file. Venue internet is often weak. | | Avoid: making the file on the morning of the service | Instead: make and test it well before the day. | | A photo in the review frames is wrong | The agent removes it with `delete_clip`, places the right photo with `insert_media`, then runs `capture` again. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a celebration of life video for Aunt Maria from ./maria. Bright, warm music, her favorite quote at the start, and a caption with the year on each photo. One hour loop. ``` ```text Make a short funeral slideshow, about five minutes, to play once during the service. Include the two video clips in ./clips with their sound, and "Forever loved" at the end. ``` ```text Make two versions on two branches: a 16:9 loop for the venue TV, and a vertical one minute version to share with family on WhatsApp. ``` #### When to use something else invideo does not burn DVDs. If the venue only has a DVD player, use a DVD burning app with the MP4 file. For a livestream of the service, use a streaming service. invideo makes files, not live broadcasts. #### Related - [Make a photo slideshow for any occasion: anniversary, graduation, retirement, baby's first year, family recap](/how-to/personal/occasion-slideshow) - [Animate a photo, or make a pet memorial from one picture](/how-to/personal/animate-a-photo) - [Make a video with ChatGPT, Claude or Gemini](/how-to/personal/with-chatgpt-claude-gemini) - [Check your video before you say it is done](/how-to/check-your-video) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) ### Make a video with ChatGPT Source: https://docs.invideo.io/how-to/personal/with-chatgpt-claude-gemini.md Make and edit a real video from a chat with ChatGPT or Claude, with no terminal: connect invideo, add your files in the browser, ask, and watch the edit land. You make a video by chatting with ChatGPT, Claude or the Gemini app, with no terminal and nothing to install. You connect invideo once, drop your files into an invideo project in the browser, and ask in plain words. The edit lands on a real timeline you watch live, and you can change any clip by hand after. The Gemini app takes invideo as a custom app. Gemini CLI takes it as an MCP server and runs in a terminal. Use invideo for this when you want your agent in the chat to do the editing: it cuts, adds music, text and captions on a timeline you own, and tells you the price before it spends any credits. #### Quickest path Connect invideo first. The steps for each app are on [Use invideo in ChatGPT](/start/chatgpt) and [Make a video with invideo without a terminal](/start/no-terminal). For how agents use invideo, see [invideo for AI agents](/agents). Then ask this in a new chat. ```text Use invideo. In my project "Summer 2026", use the clips I uploaded to make a 60 second vertical video with upbeat music and the title "Summer 2026". Tell me the price before you generate or add anything that costs credits. Show me frames before you export. ``` In ChatGPT, Claude or the Gemini app, you drag your files into the project's Media panel in invideo, or attach a file to the chat. In a terminal app like Gemini CLI, you name a folder and the agent uploads it. #### What you need You need an invideo account and one of the chat apps below. - **A chat app connected to invideo.** Claude on the web or the desktop app with the Claude connector, ChatGPT on the web with the official invideo plugin, or the Gemini app with a custom app. - **Your files.** Photos, clips or audio, from your phone or computer. - **An idea of the result.** The length, the shape (9:16 vertical, 16:9 wide, 1:1 square), the mood, the words to show. | App | How it connects | Terminal | | --- | --- | --- | | Claude | A custom connector, added once in settings | No | | ChatGPT | The official invideo plugin, installed once from Customize, then Plugins | No | | Gemini app | A custom app, added once in Connected Apps; Google limits who can add one | No, see [Use invideo in Gemini](/start/gemini) | | Gemini CLI | An MCP server, added with one command | Yes, see [Use invideo in Gemini](/start/gemini) | #### Steps These steps are for Claude and ChatGPT. ##### Connect once You do these steps once per app. In Claude, open **Customize**, then **Connectors**, click **Add**, choose the custom web connector, and name it `invideo` with the URL `https://mcp.invideo.io/mcp`. In ChatGPT, open **Customize**, then **Plugins**, and add invideo from the Creativity list. You see invideo under Installed. The app opens the invideo sign-in in your browser. Sign in and choose the workspaces the chat may use. You see invideo as connected. You never paste a code or a password into the chat. In Claude, open the + menu, choose Connectors and turn on invideo. In ChatGPT, the plugin is on once it is installed; name invideo in the prompt. Ask "Use invideo to show me my projects." You see a list of your projects with their URLs. In Claude only, open **Settings**, then **Capabilities**, and add m.invideo.io under **Allowed websites**. Claude needs this to upload the files you attach to a chat. You see m.invideo.io in the list. The full steps are on [How do I let Claude upload my files to invideo?](/ai-agents/how-do-i-let-claude-upload-my-files-to-invideo). ##### Make the video Then you make the video in a chat. Open the project in invideo, or ask the chat to make one with `new_project` and give you its URL. Drag your files into the Media panel. You can also attach a file to the chat, and the agent brings it in with `add_media`. In Claude, this needs m.invideo.io allowed first. You see each file in the Media panel when its upload ends. Describe the result, not the clicks. Name the files you want first, the length, the shape and the music. The agent reads the project with `read` and the timeline with `get_timeline`, works on a branch from `timeline_history`, and edits with `edit_timeline`. You get a timeline URL. Open the timeline URL in your browser. You see the agent's cursor under its name and each change as it lands. Change anything by hand, or ask the chat for a follow-up, like "make the title bigger". Before anything that costs credits, ask "What will this cost?" For a shot or a voice you do not have, the agent runs `find_models` with the job in words, reads the pick's inputs with `get_model`, and calls `generate` with `dry_run: true`. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. The full loop is in [invideo for AI agents](/agents). You see the price in the chat, then a sequence URL for what it made, which the agent reads with `read`, never with a second `generate`. Ask "Show me frames from the start, middle and end." The agent runs `capture` and `check_timeline`, then `export` with `format` video. The agent can also export a project file for Premiere Pro, DaVinci Resolve or Final Cut Pro with `format`. You see an export card in the project. Open it and download the MP4. The key call the agent makes to find the files you dragged into the Media panel is the full `get_timeline` call in `mode` collection. `` is the timeline's URL, from `new_timeline` or from `read` on the project: ```json { "url": "", "mode": "collection", "collection": "asset" } ``` If the files are not in the bin, the agent runs `read` on the project to list its sequences and files, then adds the ones you named to the timeline with `add_media`. To continue a project you already have, open it in invideo Editor, copy the URL from the address bar, and paste it into the chat. The agent opens it and lists its timelines. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** connecting, uploads, every edit, frame checks and the export. - **Costs credits:** generated images, video, voice and music, transcripts for captions, and paid stock music or footage. Setup takes a few minutes once. A simple video from your own files takes a few minutes of chat. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from invideo not being on in the chat, or files outside the project. | Symptom | Fix | | --- | --- | | The chat does not use invideo | In Claude, turn invideo on for this chat in the + menu. In ChatGPT, check that the plugin is installed and name invideo in the prompt. | | Claude says it cannot upload your files to invideo | Allow m.invideo.io in Claude under **Settings**, then **Capabilities**, then **Allowed websites**, and start a new chat. See [How do I let Claude upload my files to invideo?](/ai-agents/how-do-i-let-claude-upload-my-files-to-invideo). | | You do not see invideo in ChatGPT's plugin list | In a managed workspace your admin controls which plugins you can add. Ask them. | | The chat cannot find your files | Check they are in the project's Media panel, and name them in your message. | | The chat cannot see a workspace | Connect invideo again and choose that workspace in the sign-in. | | The chat says a job is still running | Generations and exports run in the background. Ask it to check the status again later. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | Avoid: the chat asks for a code or password | Instead: sign in on the invideo page that opens. | | Avoid: the chat says done without a link | Instead: ask for the timeline URL and frames from the video. | | Avoid: the chat generates before telling you the price | Instead: ask for a dry run and the price first. | #### Prompts to try Each prompt is a real job you can ask in a chat. ```text Use invideo. Make a birthday montage from the photos in my project "Leo 8". Cut on the beat of a happy song, add "Happy birthday, Leo". Tell me the price of the song first. ``` ```text Use invideo. Take my timeline "Trip v1", make a 30 second vertical version on a new branch, and add captions. Tell me the transcript price first. ``` ```text Use invideo. Look at my wedding clips and tell me which ones have the vows and the speeches, with times. Do not edit anything. ``` #### When to use something else ChatGPT agents that run in the cloud cannot use the plugin. They need the device sign-in, which is on [Run invideo in CI and on servers](/how-to/ci-and-servers). If you want no chat app at all, use Agent Two inside the invideo app. It needs no setup; see [Make a video with invideo without a terminal](/start/no-terminal). #### Related - [Make a video with invideo without a terminal](/start/no-terminal) - [Use invideo in ChatGPT](/start/chatgpt) - [Use invideo in Gemini](/start/gemini) - [Make a birthday montage from photos and clips](/how-to/personal/birthday-montage) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Make a trend edit like CapCut Source: https://docs.invideo.io/how-to/personal/trend-edit.md A vertical trend edit like a CapCut template: speed ramps and slow-mo on the drop, a freeze frame, a reverse, meme text, shake and glitch transitions. You get a vertical trend edit, the kind people make from a CapCut template: a velocity edit with speed ramps, slow-mo on the drop, a freeze frame with a caption, a quick reverse, meme text, and shake, flash or glitch transitions. Your agent times every move to the beat of the song. Use invideo for this when you want the effect timed to the music without a template: your agent finds the drop in the song, ramps the speed there, and every move stays editable on the timeline after. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 15 second vertical velocity edit from ./skate.mp4 to the song ./song.mp3. Ramp the speed down to slow-mo on the drop, freeze on the jump with the text "wait for it", then a shake zoom transition back to normal speed. Keep text clear of the TikTok buttons. Show me frames. ``` In a chat app, you drag your clip and song into the project's Media panel in invideo, then name them in the chat. In a terminal, you name the files and the agent uploads them. #### What you need A trend edit needs one strong clip and a song with a clear drop. - **Clips.** MP4 or MOV from your phone. Clips shot at a high frame rate give smoother slow-mo. - **The song.** Your own licensed file, or a track from stock music. Trending sounds from an app stay in that app. - **The moves.** Slow-mo, speed ramp, freeze frame, reverse, meme text, shake or glitch. - **The text.** The meme lines, top and bottom, or one caption. - **The shape.** 9:16 for TikTok, Reels and Shorts. #### Steps Your agent edits on a branch and tells you what changed at each step. The agent makes a project with `new_project`, a 9:16 timeline with `new_timeline`, and a branch with `timeline_history`. Expected result: a vertical timeline URL on the new branch. The agent uploads both with `start_upload` and `add_media`, or adds a stock song from `stock_music` with `search_library`. It places the clip with `place_media` and fills the frame with `fill_frame`, and the song on its own audio track. Expected result: the clip and the song on the timeline. The agent runs `media` `audio.markers` on the song for its tempo and drops, and `audio.beats` for the strong beats, and turns each time into a frame: seconds times the frame rate. Expected result: the frame of the drop, and the beats around it. The agent runs `retime` with `kind` ramp on the clip, from normal speed down to slow-mo across the drop, with `shape` ease_in_out. Later clips move to make room. The clip's own sound goes silent while its speed is changed, so the song carries the sound. Expected result: the clip slows on the drop. The agent runs `retime` with `kind` freeze at the peak frame for a short hold, and `kind` reverse on a short range for the rewind moment. Expected result: the picture holds, then plays back. At each cut, the agent adds a catalog transition with `add_transition`, such as `shake_zoom`, `flash`, `glitch` or `zoom`. On the clip, it can add an effect with `add_effect`, such as `wiggle` for camera shake or `pixel_glitch`. It adds meme text with `add_text`, white with a black stroke, and safe zone guides with `create_guide`. Expected result: transitions on the beats and text inside the guides. The agent runs `capture` before, on and after the drop, at the freeze and at each text, and `check_timeline`, and looks for the drop on the slow-mo and text that reads on a phone. Then it runs `export` with `format` video. In a terminal, it saves the file with `invideo notebook show` on the card's URL. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Skate edit" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Velocity" --width 1080 --height 1920 invideo asset upload ./skate.mp4 ./song.mp3 invideo media audio.markers invideo media audio.beats invideo edit catalog --ops retime,add_transition \ --transitions shake_zoom,flash invideo edit show invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 4,6,7.5,9 --out ./frames invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. `` is the URL `invideo asset upload` returns for the song. - `` comes from `invideo edit show`. `ops.json` holds a bare list of operations, like the `operations` list in the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits and saves nothing. `invideo notebook show` saves the file as `./out/export.mp4`. The key MCP call is the full call. It ramps to slow-mo on a drop at 6 seconds, freezes at the jump, and adds the meme text. At 30 fps, 6 seconds is frame 180. `` is the `branch_url` that `timeline_history` returns. The `` and the clip id `c1` come from `get_timeline`. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "retime", "clip": "c1", "kind": "ramp", "from_f": 165, "to_f": 195, "start_speed": 1, "end_speed": 0.25, "shape": "ease_in_out" }, { "op": "retime", "clip": "c1", "kind": "freeze", "at_f": 240, "duration_f": 30 }, { "op": "add_text", "track": "V2", "start_f": 240, "end_f": 270, "text": "wait for it", "style": { "font_size": 90, "color": "#ffffff", "stroke": true, "stroke_color": "#000000", "stroke_width": 6, "align": "center" } } ] } ``` Each `retime` moves the frames after it. The agent reads the timeline again with `get_timeline` before it places transitions after a ramp. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** every `retime`, transitions, effects, text, guides and the export. - **Tool ops:** `audio.markers` and `audio.beats`. The dry run shows its price before anything starts. - **Costs credits:** a paid stock song. Your own song file costs nothing. A trend edit takes the agent a few minutes. A few tries on the ramp timing are normal. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are timing and sound after a speed change. | Symptom | Fix | | --- | --- | | The clip goes silent after the ramp | That is how `retime` works. Put the song on its own audio track, or `retime` with `kind` reset to bring the sound back. | | The slow-mo looks choppy | The clip has few frames a second. Use a clip shot at a higher frame rate, or a smaller slow-down. | | The drop lands late | Each `retime` moves later frames. Read with `get_timeline`, then move the clip with `move_clip`. | | `retime` refused | Looping clips are refused. Place the clip again without the loop. | | `add_transition` refused | The two clips must touch on one track with no gap and no transition. | | Meme text sits under the app buttons | Move it inside the guides with `set_position`, and `capture` again. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild the ops. | | Avoid: guessing the drop by ear | Instead: read `audio.markers` and `audio.beats` and use their times. | | Avoid: saying done without looking | Instead: `capture` before, on and after the drop. | #### Prompts to try Each prompt is a different trend. ```text Make a meme edit from ./cat.mp4: top text "me at 3 am", bottom text "one more episode", freeze on his face, then reverse the last second. Vertical. ``` ```text Make a 20 second velocity edit from my gym clips in ./gym to this song. Speed up between beats, slow down on every fourth beat, and a flash transition on each slow-down. ``` ```text Make a glitch edit of my outfit clips in ./fits. A glitch transition on every beat, pixel glitch on the drop, and my handle at the end. ``` #### When to use something else invideo does not open CapCut templates or use trending sounds from inside TikTok or Instagram. Make the edit here with your own or stock music, then post it and add the trending sound in the app if you want it. invideo does not track a face to zoom on it. For a face-locked zoom, the agent keys the zoom by hand with `add_keyframe_lane` and `add_keyframes`, or you use an app with face tracking. #### Related - [Make Reels and Shorts from your footage: hook, captions, transitions, sound effects](/how-to/creators/reels-and-shorts-from-your-footage) - [Make a birthday montage from photos and clips](/how-to/personal/birthday-montage) - [Make a vertical travel video from phone clips](/how-to/personal/travel-video) - [When to use CapCut vs invideo](/compare/capcut) - [Timeline edit operations](/reference/edit-operations) ### Make a sports highlight reel Source: https://docs.invideo.io/how-to/personal/sports-highlight-reel.md A sports highlight reel or college recruiting video from game footage: the best plays found by sound and by eye, a player spotlight, stats on screen and slow-motion replays. You get a sports highlight reel, also called a highlight tape or a recruiting video, from your game footage. Your agent finds the big moments by the crowd, the whistle and the commentator, checks each one by eye, and cuts the best plays first. The reel opens with a title card of the player's name, position, jersey number, class year and stats, marks the player at the start of each play, and replays the best play in slow motion. Use invideo for this when you have hours of game film and want the plays pulled for you: your agent reads the sound and the frames of every file, and you can reorder or swap any play on the timeline after. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 3 minute recruiting video for my son Marcus Lee, #23, point guard, class of 2028, from the game films in ./games. Best plays first. Open with his name, position, number, height and stats, circle him at the start of each play, and replay the best dunk in slow motion. 16:9. Show me the plays you picked before you cut. ``` In a chat app, you drag the game films into the project's Media panel in invideo, then name them in the chat. In a terminal, you name the folder and the agent uploads it. #### What you need Coaches watch the first plays most, so know the best ones if you can. - **Game footage.** MP4 or MOV from a phone, a camera or a team video service, full games or clips. - **The player.** Name, jersey number, team colors, and where they are at the start of a play if the film is wide. - **The title card facts.** Position, class year, height and weight, school, stats, GPA, contact email. - **The plays you know are good.** A game and a rough time, if you have them. - **The shape.** 16:9 for recruiting sites and YouTube, 9:16 for a social cut. #### Steps Your agent edits on a branch and shows you its picks before it cuts. The agent makes a project with `new_project` and uploads each file with `start_upload` and `add_media`. Large game files go this way. Expected result: a sequence URL per game. The agent runs `media` `audio.content` on each game for speech, music, effects and silence spans, and `audio.onsets` for whistles, buzzers and crowd spikes. Expected result: a list of candidate times in seconds. With a commentator or a PA announcer, the agent prices `media` `audio.transcript` with `dry_run` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. It searches them for the player's name and calls like "three", "dunk" or "goal". Expected result: times where the player is named. The agent runs `media` `video.sceneSplit` on edited footage to find the cuts. It runs `video.frames` around each candidate time and looks for the player's number in the play. Expected result: a shot list with game, start and end, best first. The agent shows it to you before it cuts. The agent makes a timeline with `new_timeline`, creates a branch with `timeline_history`, and places each play with `place_media` in `mode` append. It adds a title card with `add_text`: name, position, number, class year and stats. Expected result: the plays in order after the title card. At the start of each play, the agent adds a ring around the player with `add_shape`, preset ellipse with a stroke and no fill, for about a second. For the best play, it copies the clip with `duplicate_clip` and slows the copy with `retime` `kind` section. Expected result: you can find the player at a glance, and the replay plays slow. The agent runs `capture` at the title card, at each ring and in the replay, and `check_timeline`, and looks for the ring on the right player and readable text. Then it runs `export` with `format` video and reads the card. In a terminal, it saves the file with `invideo notebook show` on the card's URL. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Marcus Lee recruiting" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Recruiting reel" invideo asset upload ./games/*.mp4 invideo media audio.content invideo media audio.onsets invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo media video.sceneSplit --dry-run invideo media video.sceneSplit \ --max-credits --idempotency-key game1-scenes invideo media video.frames --at 1204,1206,1208 \ --out ./frames invideo edit show invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 2,12,30,95 --out ./frames invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. `` is the URL `invideo asset upload` returns for each game. The transcript and `video.sceneSplit` take that URL, not a media bin id. - `` is the `credits` value of the dry run before it. Run the transcript only on a game with a commentator. - `` comes from `invideo edit show`. `ops.json` holds a bare list of operations, like the `operations` list in the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits and saves nothing. `invideo notebook show` saves the file as `./out/export.mp4`. The key MCP call is the full call. It places one play, rings the player, and adds the title card. The ring's `x` and `y` are pixels from the center of the canvas. `` is the `branch_url` that `timeline_history` returns. The `` and the bin ids, like `m2`, come from `get_timeline`. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "add_text", "track": "V2", "start_f": 0, "end_f": 150, "text": "Marcus Lee #23\nPoint guard, class of 2028\n18.4 PPG, 6.1 AST", "style": { "font_size": 64, "align": "center", "background_color": "#000000aa" } }, { "op": "place_media", "asset": "m2", "track": "V1", "at_f": 150, "source_start_seconds": 1203.5, "source_end_seconds": 1211.0, "mode": "append", "linked_audio": true }, { "op": "add_shape", "track": "V3", "at_f": 150, "duration_f": 30, "preset": "ellipse", "width": 160, "height": 160, "x": 220, "y": 140, "fill": "#00000000", "stroke": { "color": "#ffd400", "width": 8 } } ] } ``` The slow-motion replay is one more full call. The agent copies the play with `duplicate_clip` on its id, like `c5`, and slows the copy, like `c6`, with `retime`. A clip id made earlier in a call can be used later in the same call. The `` is the new one from `get_timeline`: ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "duplicate_clip", "clip": "c5" }, { "op": "retime", "clip": "c6", "kind": "section", "from_f": 900, "to_f": 1050, "speed": 0.5 } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** uploads, every cut, the rings, the replay and the export. - **Tool ops:** `audio.content`, `audio.onsets`, `video.sceneSplit` and `video.frames`. The dry run shows its price before anything starts. - **Costs credits:** `audio.transcript` for a commentator, and paid stock music if you add it. Most recruiting videos use no music. Finding plays takes the agent a few minutes a game. Your review of its picks takes longer, and matters most. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are wrong picks, a wide film where the player is small, or a silent file. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The film has no sound | The sound reads find nothing. The agent picks plays by `video.frames` alone, or uses the times you give. | | The agent picked a play by another player | Give it the jersey number and team color. It checks the number in `video.frames` before it cuts. | | The player is tiny in a wide shot | The agent zooms the play with `set_zoom` and `set_position`, and keeps the ring on the player. | | The ring is on the wrong spot | Move it with `set_position`, then `capture` again. | | `retime` refused on the replay | The clip may loop. The agent places it again without the loop. | | CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild the ops. | | Avoid: cutting before you review the picks | Instead: the agent shows you the shot list first. | | Avoid: the agent transcribes a game with no commentator | Instead: `audio.content` first; transcribe only files with speech. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 90 second soccer highlight reel for Ana Ruiz, #9, striker, from ./season. Goals first, then assists. A slow-motion replay of each goal. ``` ```text The game film in ./final.mp4 has no sound. Find every play where #14 touches the ball, from the frames, and make a list with times. ``` ```text Make a 30 second vertical version of the reel on a new branch for Instagram, with the three best plays and his handle at the end. ``` #### When to use something else A ring or arrow placed with `add_shape` sits where the player starts. For a mark that follows the player, the agent runs `object_track` or `sam_3_1_video` on the clip to get a mask that moves with them, then keys a highlight through it with `track_matte_key`. That is a mask, not a sports telestrator; for drawn plays and auto-detected jersey numbers, use a sports video tool. Recruiting sites and team video services have their own upload pages and rules. Export the MP4 here, then upload it there. #### Related - [Make a wedding video from guest clips](/how-to/personal/wedding-video) - [Make a trend edit like CapCut: slow-mo, meme, freeze frame](/how-to/personal/trend-edit) - [Make a gaming montage from your clips](/how-to/creators/gaming-montage) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Check your video before you say it is done](/how-to/check-your-video) ### Enhance doorbell or dashcam footage Source: https://docs.invideo.io/how-to/personal/enhance-doorbell-or-dashcam-footage.md invideo does not enhance doorbell, CCTV or dashcam footage to read a plate or a face. It trims the clip and pulls stills for your police or insurance report. invideo does not enhance doorbell, CCTV, security camera or dashcam footage to read a license plate, a number plate or a face. Its upscalers make a video look sharper by inventing detail, so a plate or a face they draw is a guess, not what the camera recorded. What invideo does is help you send the footage you have: a short trimmed clip, clear stills of the moments that matter, and a contact sheet, ready for the police or your insurer. Use invideo for this when you need a short clip and clear stills to send with a police or insurance report, and you want to keep the original file untouched. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text I have doorbell footage of a package theft in ./doorbell.mp4. Do not enhance or upscale it. Trim it to the theft, give me stills at the clearest moments, and a contact sheet of the whole clip, so I can send them to the police with the original file. ``` In a chat app, you drag the file into the project's Media panel in invideo, then name it in the chat. In a terminal, you name the file and the agent uploads it. #### What you need Keep the original file exactly as the camera or the app saved it. - **The original file.** Download it from the camera app at full quality. Keep a copy that nobody edits. - **The date, the time and the place.** Your report needs them. The camera app usually shows them. - **The moments that matter.** A rough time in the clip for each one. - **The report's address.** The police report number, or your insurer's claim number and upload page. #### Steps These are the steps your agent does. It does not run an upscale or an enhance step on this footage. The agent makes a project with `new_project` and uploads a copy of the file with `start_upload` and `add_media`. You keep the original. Expected result: a sequence URL for the copy. The agent runs `media` `metadata` for the file's length, size, frame rate and streams. Expected result: the details, which you can add to your report. The agent runs `media` `video.frames` at times across the clip, and `video.contactSheet` for one image of frames in a grid. It runs `audio.content` if the clip has sound, to find voices or a crash. Expected result: the times of the moments that matter. For each moment, the agent runs `media` `video.extractFrameAtTime` with `time_seconds`. Each still is the frame as recorded, with nothing added. It sends an `idempotency_key` with each one. Expected result: one image sequence per moment. The agent runs `media` `video.trim` with `start_time` and `end_time` around the event, a few seconds before and after, and an `idempotency_key`. It does not stabilize, sharpen, upscale or color the clip. Expected result: a short video sequence. The agent gives you the URLs of the trimmed clip, the stills and the contact sheet. You download them from the project and send them with the original file, which stays the evidence. Expected result: files you attach to the report. The same job from a terminal: ```bash invideo project new --title "Doorbell 12 May" invideo agent register --name export INVIDEO_AS= invideo asset upload ./doorbell.mp4 invideo media metadata invideo media video.frames --at 10,14,18,22 --out ./frames invideo media video.extractFrameAtTime --time-seconds 14.2 \ --dry-run invideo media video.extractFrameAtTime --time-seconds 14.2 \ --max-credits --idempotency-key doorbell-still-1 invideo media video.trim --start-time 8 --end-time 26 \ --dry-run invideo media video.trim --start-time 8 --end-time 26 \ --max-credits --idempotency-key doorbell-trim-1 invideo status --wait invideo notebook show --out ./report invideo notebook show --out ./report ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`. `` is the URL `invideo asset upload` returns for the copy. The stills and the trim make files, so they take that URL, not a media bin id. `` is the `credits` value of each dry run. - `` is the URL `video.extractFrameAtTime` returns, and `` the URL `video.trim` returns. - `invideo status` waits and saves nothing. `invideo notebook show` with `--out` saves each file to the folder. The key MCP call is the full `media` call. It pulls one still at the time the face or the plate is clearest, as recorded. `` is the URL `add_media` returns for the copy: ```json { "url": "", "op": "video.extractFrameAtTime", "time_seconds": 14.2, "idempotency_key": "doorbell-still-1" } ``` The contact sheet uses `video.contactSheet` on the same sequence URL. It needs all four of `columns`, `rows`, `resolution` and `style`, and `style` is `labeled` or `plain`. A `dry_run` shows its price before it starts. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the upload and the download. - **Tool ops:** `metadata`, `video.frames`, `video.contactSheet`, `audio.content`, `video.extractFrameAtTime` and `video.trim`. The dry run shows its price before anything starts. - **Costs credits:** a transcript of speech in the clip with `audio.transcript`, and the face masks with `sam_3_1_video` for the last prompt below. The whole job takes a few minutes. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most questions on this job are requests invideo turns down, and why. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | You ask to read a plate or a face that is a blur | The agent says no. An upscale invents the detail, and a made-up plate can name the wrong person. Ask the police or your insurer. | | You ask who the person is | The agent does not identify people from footage. Send the stills to the police. | | You ask to upscale "a little" for the report | The agent says no for evidence. It sends the frames as recorded. | | The camera app saves a low quality copy | Download the original again at full quality from the camera app or its cloud. | | A still is blurred by motion | The agent pulls the frames before and after with `video.frames`, and you pick the clearest. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: sending only the trimmed clip | Instead: send the original file too. Investigators need it as the camera saved it. | | Avoid: posting an "enhanced" still online | Instead: post the frame as recorded, or none. A wrong guess can harm someone. | #### Prompts to try Each prompt is a real version of the job. ```text My dashcam caught a car hitting mine in ./dashcam.mp4 at about 2:10. Trim from 2:00 to 2:30, pull stills every second of the impact, and a contact sheet. No enhancement. ``` ```text Make a contact sheet of my CCTV clip ./yard.mp4 and tell me the times when someone is in the frame. Do not upscale anything. ``` ```text I want to share the doorbell clip in my neighborhood group. Trim it, and blur the faces of my neighbors who walk past, but not the person at the door. ``` For the last prompt, the agent masks the neighbors with `sam_3_1_video` or `object_track`, then blurs them with `track_matte_key` and `gaussian_blur`, priced first. It does not sharpen the person at the door. #### When to use something else Forensic video enhancement and identification are jobs for the police and for the forensic lab your insurer uses. They work from the original file, record every step, and their findings stand up in a claim or in court. Give them the original file and your report number. If the camera company holds a cloud copy, ask them for the original export too. It can have more detail than the copy on your phone. #### Related - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [MCP tools](/reference/mcp-tools) - [Security and data](/account/security-and-data) - [Make a video with ChatGPT, Claude or Gemini](/how-to/personal/with-chatgpt-claude-gemini) ## Creators ### Intro, outro or logo animation Source: https://docs.invideo.io/how-to/creators/intro-outro-logo-animation.md A short channel intro, welcome video, outro or logo animation, with your logo moving in, your name in animated text and a sound hit. You get a channel intro, a welcome video, an outro or a logo animation (also called a logo sting or logo reveal). Your logo flies or fades in, your name appears in animated text, and a whoosh or a hit lands with it. The result is an MP4 you can put at the start or end of every video. Use invideo for this when you want to change the intro later without starting over: every logo move, text line and sound sits on an editable timeline, so a new tagline is one edit, not a new order. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 5 second intro for my cooking channel "Maya Cooks". Use the logo in ./brand/logo.png. Zoom the logo in from small, then show the channel name under it in white. Add a soft whoosh when the logo lands. 16:9. Price any generation first and show me frames before you export. ``` In a chat app, you drag the logo into the project's Media panel in invideo, then name it in the chat. In a terminal, you name the file and the agent uploads it. #### What you need Have these ready before you start. The agent asks for anything that is missing. - **Your logo.** A PNG, best with a transparent background. A JPG works too; the agent can remove a white box around it. - **The text.** The channel or business name, and a tagline if you want one. - **The length.** Intros are short. Give a number of seconds. - **The shape.** 16:9 for YouTube, 9:16 for Shorts, Reels and TikTok, 1:1 for a feed. - **The mood.** Clean, playful, glitchy or cinematic. This picks the motion, the effects and the sound. - **Your font, if you have one.** A TTF, OTF, WOFF or WOFF2 file. #### Steps Your agent edits on a branch and tells you what changed at each step. The agent makes a project with `new_project` and a timeline with `new_timeline` in the shape you asked for. It creates a branch with `timeline_history`. Expected result: a timeline URL on the new branch. The agent calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id` and the timeline URL. A font file goes in the same way, and its id is the `font` that `add_text` takes. For a logo with a white box around it, the agent runs `media` `image.removeBackground` on the logo's sequence URL from `add_media`, with `dry_run: true`, then with `max_credits` and an `idempotency_key`. Expected result: the logo and the font in the media bin. The agent places the logo with `insert_media` and sets its length with `trim_clip`. For a fade or a spin, it uses `set_keyframes` on `opacity` or `rotation`. For a zoom or a fly-in, it adds a lane with `add_keyframe_lane` (`zoom_x` and `zoom_y`, or `position_x` and `position_y`) and fills it with `add_keyframes`. Expected result: the logo moves when you play the timeline. The agent adds the name with `add_text` and styles it with `set_text_style`. It fades the text in with `set_keyframes` on `opacity`. For a more designed look, it runs `find_models` with "animated title" and reads its pick with `get_model`. A good pick is `dynamic_text.diy`, which makes a motion graphic from a `prompt`. For a styled text overlay on a clip, a good pick is `dynamic_text.styles`, which takes the clip as `video` and a style such as `text_style: "NEON_COUNTDOWN"`. Your agent can search for others with `find_models`. The agent calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: the name appears after the logo lands, or a sequence URL for the motion graphic, which the agent reads with `read`. The agent picks effects and transitions from `timeline_catalog` by name. It adds an effect such as `lens_flare` or `pixel_glitch` with `add_effect`, and a start or end from black with `add_edge_transition` and a type such as `fade`, `light_leak` or `glitch`. Expected result: the look you asked for. The agent runs `find_models` with "whoosh sound effect" and reads its pick with `get_model`: a `prompt` and a `duration` within the range `get_model` gives. A good pick is `elevenlabs_sfx`. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true` for a whoosh, hit or chime, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, reads the sequence URL with `read`, and places the sound with `insert_media` at the frame where the logo lands. Expected result: a sequence URL for the sound, and the sound lands with the logo. The agent runs `capture` at the start, the moment the logo lands, and the last frame, and runs `check_timeline`. Then it runs `export` with `format` video and reads the export card until its status is `completed`. For a 4K copy, it runs `media` `video.upscale` on the export card's URL, with `dry_run` first, then `max_credits` and an `idempotency_key`. Expected result: frames with the logo sharp and the text inside the frame, and a 1080p MP4. The same job from a terminal: ```bash invideo project new --title "Maya Cooks intro" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Intro" --width 1920 --height 1080 invideo asset upload ./brand/logo.png ./brand/font.otf invideo gen models --query "whoosh sound effect" invideo gen model --model elevenlabs_sfx invideo gen run --model elevenlabs_sfx --dry-run \ -i prompt="soft whoosh into a warm hit" -i duration=3 invideo gen run --model elevenlabs_sfx --max-credits \ --idempotency-key intro-hit -i prompt="soft whoosh into a warm hit" \ -i duration=3 invideo status --wait invideo edit show --json invideo branch new --name intro-v1 --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @ops.json invideo edit capture --at 0,1,2.5,4.9 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is the dry run's `.estimated_credits`. `` is the `url` the paid run returns. - `` comes from `invideo edit show ` for the branch command. `` is the `.branch_url` that `invideo branch new` returns. For `edit change`, `` is read again with `invideo edit show `. - `@ops.json` reads a bare JSON list of ops, the `operations` list of the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The key MCP call adds the name, spins the logo in, starts its zoom lane, adds a flare and fades the logo out. This is the full call. `` is the branch URL that `timeline_history` returns, and `` comes from `get_timeline` on it. `c1` is the logo clip's id from `get_timeline`. At 30 fps, one second is 30 frames. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "set_keyframes", "clip": "c1", "property": "rotation", "points": [ { "at_f": 0, "value": -90, "ease": "ease_out" }, { "at_f": 20, "value": 0 } ] }, { "op": "add_keyframe_lane", "parent": "c1", "parent_kind": "video_clip", "property": "zoom_x", "default_value": 1 }, { "op": "add_effect", "clip": "c1", "effect": "lens_flare" }, { "op": "add_text", "track": "V2", "start_f": 30, "end_f": 150, "text": "Maya Cooks", "style": { "font_size": 120, "font_weight": 700, "align": "center", "color": "#ffffff" } }, { "op": "add_edge_transition", "clip": "c1", "edge": "tail", "type": "fade", "in_f": 0, "out_f": 15 } ] } ``` The lane id comes back from `add_keyframe_lane`. The agent sends `add_keyframes` with that `lane` in a second call, with points such as `time_seconds` 0 at `value` 0.2 and `time_seconds` 0.7 at `value` 1. It does the same for `zoom_y`, so the logo keeps its shape. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the upload, the logo motion, the text, the effects, the transitions, the checks and the 1080p export. - **Costs credits:** a sound from `elevenlabs_sfx`, a motion graphic from `dynamic_text.diy` or `dynamic_text.styles`, and a 4K upscale with `video.upscale`. An upscale is priced per second of the source video. - **Tool ops:** `image.removeBackground`. The dry run shows its price before anything starts. An intro takes the agent a few minutes. A 4K upscale adds a few more. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a logo that is blurry when it is large, or motion that is too fast. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | `image.removeBackground` or `video.upscale` refused with `code: "not_found"` | The call named a media bin asset. Pass the file's sequence URL, from `add_media` or the export card. | | The logo looks soft at full size | Use a larger PNG, or an SVG turned into a large PNG. A zoom past the file's own size looks soft. | | The logo has a white box | Run `media` `image.removeBackground` on it, then place the new image. | | `set_keyframes` refused for zoom or position | It takes `opacity` and `rotation` only. Use `add_keyframe_lane` and `add_keyframes` for zoom and position. | | The text is cut off at the edge | The agent moves it with `set_position`, then runs `capture` again. | | The motion feels too fast | Ask for a longer move. The agent moves the last keyframe later. | | The sound lands early or late | The agent moves the sound clip with `move_clip` to the frame where the logo lands. | | `edit_timeline` refused as stale | Someone edited since the read. Read with `get_timeline` and send again with the new `state_token`. | | CLI exit 5 | A limit: credits or quota. Lower the generation, or add credits, then run it again. | | Avoid: generating the sound again to check on it | Instead: `read` the sequence URL, or run `invideo status --wait`. | | Avoid: saying done without looking | Instead: `capture` frames at the start, the landing and the end. | #### Prompts to try Each prompt is a real variation of the job. ```text Make an outro for my channel: "Thanks for watching" with my logo in the corner, room for two end-screen videos on the right, and a soft chime. 10 seconds, 16:9. ``` ```text Make a logo reveal for my bakery from ./logo.png. Glitch the logo in, add a light leak, and a bass hit when it settles. Then make a 9:16 version on its own branch for Reels. ``` ```text Make a welcome video for my YouTube channel page. My logo, then three lines: "New recipes every Friday", "Real kitchens", "Subscribe". Slow fades, warm music from stock, 20 seconds. ``` #### When to use something else invideo exports MP4 at 1080p. For a 4K file, the agent exports, then upscales. - **A GIF.** Convert the MP4 with FFmpeg or any GIF converter. - **A transparent version.** An intro with a see-through background, to lay over other footage in another app, needs a tool that exports alpha, such as After Effects or DaVinci Resolve. invideo burns the logo and text into the video. - **A template you bought.** An After Effects or CapCut template file does not open in invideo. The agent rebuilds the look on the timeline instead. #### Related - [Make a lyric video or text animation for your song](/how-to/creators/lyric-video) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Repurpose one video for every platform, one branch each](/how-to/creators/repurpose-for-every-platform) - [Customize a template you bought](/how-to/creators/customize-a-template-you-bought) - [Check your video before you say it is done](/how-to/check-your-video) - [Timeline edit operations](/reference/edit-operations) ### Make a quote video Source: https://docs.invideo.io/how-to/creators/quote-and-nature-loop-videos.md A quote video, a calm nature loop or a welcome video from stock footage, with your text on screen and music that clears rights. You get a quote video, a motivational video, a nature or background loop, or a welcome video for your page. Stock footage of a forest, the sea or rain plays under your words, soft music runs under it, and the loop runs as long as you need with no hard jump at the seam. Use invideo for this when you want licensed stock and music in the same place as the edit: your agent finds the footage, loops it to the length you need, and every word stays editable on the timeline. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 30 second quote video, 9:16. Find calm stock footage of a misty forest and soft piano music. Show "Small steps every day." in the center, with "Maya Sen" under it, smaller. Fade the words in and out. Price the stock first and show me frames before you export. ``` In a chat app, you watch the stock previews in the chat and pick one. In a terminal, the agent lists the results with their preview links, and you open them. #### What you need Most of this job is words and a mood. You do not need your own footage. - **The text.** The quote and the author, or the welcome lines for your page. - **The scene.** Forest, ocean, rain on a window, clouds, a fire, a city at night. - **The music or the mood.** Calm, uplifting, cinematic, or no music. - **The length.** A number of seconds for a post, or a longer loop for a background screen. - **The shape.** 9:16 for Reels, Shorts and TikTok, 1:1 for a feed, 16:9 for YouTube. #### Steps Your agent edits on a branch and tells you what changed at each step. ##### Build the loop The agent gets the footage to the length you want first. The agent makes a project with `new_project` and a timeline with `new_timeline` in the shape you asked for. It creates a branch with `timeline_history`. Expected result: a timeline URL on the new branch. The agent searches `stock_video` and `stock_music` with `search_library`, using words such as "misty forest morning" or "soft piano". Each result has a low-resolution preview. It can look closer with `media` `video.frames` and the `stock` id. Expected result: a short list of results with previews for you to pick. The agent runs `find_models` with the scene in words. A good pick is `seedance_2_5.frames`. Your agent can search for others with `find_models`. The agent reads its inputs with `get_model`. It passes one still of the scene as both `first_frame` and `last_frame`, so the clip loops cleanly, and sets `generate_audio` false. The clip takes the still's shape, so the agent first fits the still to your shape with `media` `image.resizeAspectRatio` on the still's sequence URL from `add_media`. It calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It gets a thread URL, and reads the result with `read`, never with a second `generate`. Expected result: a sequence URL for the scene. The agent adds each pick with `add_media` and `stock`, on the timeline URL. Paid stock shows invideo's stock mark on the timeline, and the export renders it clean. Expected result: a sequence URL and a media bin id for each one. The agent runs `media` `video.loop` on the clip's sequence URL with `target_duration` in seconds. It makes a new looped file beside the clip. For a softer seam on the timeline, the agent instead copies the clip with `duplicate_clip` and adds a `fade` at the cut with `add_transition`. Expected result: footage that runs the full length. ##### Finish and export Then the agent adds the words and the music, and checks the loop. The agent adds the quote with `add_text` and the author as a second text clip, smaller. It sets the style with `set_text_style`, colors one word with `style_text_range` if you ask, and fades each line in and out with `set_keyframes` on `opacity`. Expected result: the words appear and leave gently. The agent places the music with `insert_media` on an audio track, sets its level with `set_audio_gain`, and fades it in and out with `set_audio_fades`. Expected result: music that starts soft and ends soft. The agent runs `capture` at the start, each line of text, the seam of the loop and the end, and runs `check_timeline`. It checks that the text is readable on a phone. Expected result: clean frames with no jump at the seam. The agent runs `export` with `format` video and reads the export card until its status is `completed`. Expected result: a 1080p MP4. The same job from a terminal: ```bash invideo project new --title "Quote: small steps" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Quote" --width 1080 --height 1920 invideo library search --library stock_video \ --query "misty forest morning" invideo library search --library stock_music \ --query "soft piano" invideo asset add --stock invideo asset add --stock invideo asset upload ./still.jpg invideo gen models --query "seamless looping nature scene" invideo gen model --model seedance_2_5.frames invideo gen run --model seedance_2_5.frames --dry-run \ -i prompt="mist drifting through a pine forest" \ -i first_frame= -i last_frame= \ -i generate_audio=false invideo gen run --model seedance_2_5.frames \ --max-credits --idempotency-key forest-1 \ -i prompt="mist drifting through a pine forest" \ -i first_frame= -i last_frame= \ -i generate_audio=false invideo media video.loop --target-duration 30 \ --dry-run invideo media video.loop --target-duration 30 \ --max-credits --idempotency-key quote-loop-30 invideo edit show --json invideo branch new --name quote-v1 --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @ops.json invideo edit capture --at 0,3,10,20,29.9 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` and `` are stock result ids from `invideo library search`. - `` in the `gen run` lines is the still's: the `url` that `invideo asset upload` returns, a `…/notebook/seq-N.M` URL. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is the dry run's `.estimated_credits`. - `` in the `video.loop` lines is the footage's: the `url` that `invideo asset add` returns for stock, or the generated scene that `invideo notebook show` lists on the `gen run` thread. `video.loop` refuses a bin `--asset`. - `` comes from `invideo edit show`: on `` for the branch, then on `` for the change. `` is the `.branch_url` that `invideo branch new` returns. - `@ops.json` reads a bare JSON list of ops, the `operations` list of the `edit_timeline` call below. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The loop as one `media` call. The agent sends it first with `dry_run: true`, then with `max_credits` set to the price. `` is the footage's sequence URL from `add_media`. ```json { "url": "", "op": "video.loop", "target_duration": 30, "idempotency_key": "quote-loop-30" } ``` The key `edit_timeline` call, shown as the full call, places the loop, adds the quote and lays the music. `` is the branch URL `timeline_history` returns, and `` comes from `get_timeline` on it. `m3` is the looped file's bin id and `m2` the music's, from `get_timeline`. At 30 fps, one second is 30 frames. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "insert_media", "asset": "m3", "track": "V1", "at_f": 0, "ripple": false }, { "op": "add_text", "track": "V2", "start_f": 30, "end_f": 840, "text": "Small steps every day.", "style": { "font_size": 88, "align": "center", "color": "#ffffff", "shadow": true } }, { "op": "insert_media", "asset": "m2", "track": "A2", "at_f": 0, "ripple": false } ] } ``` The agent also sends `set_keyframes` on the text clip's `opacity`, `set_audio_gain` with `gain_db` on the music clip, and `set_audio_fades` with `fade_in_f` and `fade_out_f`. These can go later in the same call, with the clip ids the call makes, or in a second call after `get_timeline`. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** searching stock, looking at previews, the text, the fades, the checks and the export. - **Tool ops:** `video.frames`, `video.loop`, `image.resizeAspectRatio`. The dry run shows its price before anything starts. - **Costs credits:** each paid stock clip and stock song you add, and a scene made with `seedance_2_5.frames`. Your own footage and music cost nothing. A quote video takes the agent a few minutes. Picking the footage takes you longer. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a hard jump at the loop seam, or text that is hard to read on a busy background. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | The seam shows in the check frames | Make the crossfade longer with `resize_transition`, then `capture` the seam again. | | A jump where the loop starts again | Use `duplicate_clip` and a `fade` with `add_transition` at the cut, or pick footage with little motion. | | The text is hard to read | Add `shadow` or a `background_color` with `set_text_style`, or pick a calmer clip. | | `media` with `stock` refused for `video.loop` | A stock result has no thread. Add it with `add_media` first, then loop its sequence URL. | | The music ends before the video | Ask for a longer song, or loop the song on the timeline the same way. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: the agent edits main | Instead: it works on a branch from `timeline_history`, and you accept the change. | | Avoid: saying done without looking at the seam | Instead: `capture` a frame at the seam and one a second after it. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a one hour rain-on-a-window loop for a study stream, 16:9. No music, only the rain sound from the stock clip. Loop it so the seam does not show. ``` ```text Make five quote videos for this week from the quotes in ./quotes.txt. Ocean footage, the same font and layout on each, one timeline per quote. 9:16. ``` ```text Make a welcome video for my yoga studio's page: sunrise over hills, the lines "Breathe", "Move", "Rest", then our name. Soft music, 20 seconds, 1:1. ``` #### When to use something else invideo exports an MP4 that plays once. A screen at a venue or a stream has to repeat the file itself. Set the player or the streaming tool, such as OBS, to loop the file. For many quote videos at once, see the bulk sleep and meditation page, which runs one timeline per row. #### Related - [Make sleep, rain and meditation videos for a faceless channel, in bulk](/how-to/creators/sleep-and-meditation-videos-in-bulk) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Make an intro, welcome video, outro or logo animation for your channel or business](/how-to/creators/intro-outro-logo-animation) - [Make a Spotify Canvas and a music visualizer](/how-to/creators/spotify-canvas-and-visualizer) - [Licensing and commercial use](/account/commercial-use) - [Check your video before you say it is done](/how-to/check-your-video) ### Make a lyric video or text animation for your song Source: https://docs.invideo.io/how-to/creators/lyric-video.md A lyric video, karaoke video or kinetic typography for your song, with each line timed to the singing and the beat. You get a lyric video for your song, also called a karaoke video, a text animation or kinetic typography. Each line of the lyrics builds up word by word as it is sung, and big lines land on the beat. You can make it in one step with `lyrical_videos.audio`, or line by line on a timeline you can still edit. Use invideo for this when you want the lyrics timed to your own recording: your agent reads when each word is sung, puts the lines on the timeline, and you can fix a word or move a line after. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a lyric video for my song ./song.wav, 16:9. The lyrics are in ./lyrics.txt. Show one line at a time, build each line up word by word as it is sung, and put the chorus lines on the beat. Use my cover art ./cover.jpg as the background. Price it first and show me frames. ``` In a chat app, you drag the song, the lyrics and the art into the project's Media panel in invideo. In a terminal, you name the files and the agent uploads them. #### What you need The song is the only thing you must have. The rest makes the result better. - **The song.** WAV or MP3, a mix you have the rights to. - **The lyrics as text.** The agent checks the timed words against them, so names and slang come out right. - **A background.** Your cover art, a clip of the band, stock footage, or a plain color. - **The shape.** 16:9 for YouTube, 9:16 for Reels, Shorts and TikTok, 1:1 for a feed. - **The look.** Clean, karaoke, bold and moving, or handwritten. #### Steps Your agent edits on a branch and tells you what changed at each step. Steps two and three are the one-step model path. Steps four to six are the timeline path, which you can edit word by word. The agent makes a project with `new_project`, a timeline with `new_timeline` in the shape you asked for, and a branch with `timeline_history`. It calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id` and the branch URL. Expected result: a sequence URL and a media bin id for the song and the art. The agent runs `find_models` with "lyric video from a song" and reads its pick with `get_model`. A good pick is `lyrical_videos.audio`. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true`, the song as `audio`, a `lyrical_style` of `ULTRA_BASIC`, `KARAOKE` or `POP_ANIMATION`, and an `aspect_ratio`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL for the finished lyric video, which the agent reads with `read`. For a video with the song in it, the agent runs `find_models` with "lyrics over a video" and reads its pick with `get_model`. A good pick is `lyrical_videos.video`, with the clip as `video` and a `lyrical_style` such as `KINETIC_LYRICS`, `MULTISIZE`, `PAPER_CUTOUT` or `SUBTITLE`. It calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL for your footage with the lyrics moving over it, which the agent reads with `read`. The agent sends one `edit_timeline` call with two `insert_media` ops, `at_f` 0 and `ripple` false: the song's bin id on `A2` and the art's bin id on `V1`. It reads the art clip's end with `get_timeline`. In a second call, it stretches the art to the song's end with `trim_clip` on the `tail`, and covers the frame with `fill_frame`. Expected result: `capture` shows the art and the song starts at frame 0. The agent prices `media` `audio.transcript` on the song with `dry_run`, starts it, and calls again after `retry_after_s` for the words with their times. It checks the words against your lyrics text and keeps your spelling. It runs `audio.beats` for the beats, `audio.markers` for the drops and phrases, and `audio.sections` for the chorus. Expected result: each lyric word with a start and end in seconds. The agent adds the lyrics with `add_captions`: one slide per line, with `words` inside each slide, so the words of each line build up as they are sung. It turns seconds into frames at the timeline's rate. It sets the font, size and color with `set_text_style`, and fixes a misheard word with `set_caption_slide_text`. For big chorus lines, it adds `add_text` clips that start on a beat, and moves them with `set_keyframes` on `opacity` or `rotation`. Expected result: the lyrics on the timeline in your style, in time with the song. The agent runs `capture` at the first line, a chorus line and the last line, and runs `check_timeline`. Then it runs `export` with `format` video and reads the card. Expected result: each captured line matches the words sung at that time, and the card's status is `completed`. The same job from a terminal, with the one-step model: ```bash invideo project new --title "Lyric video" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Lyric video" invideo asset upload ./song.wav ./cover.jpg invideo gen models --query "lyric video from a song" invideo gen model --model lyrical_videos.audio invideo gen run --model lyrical_videos.audio --dry-run \ -i audio= -i lyrical_style=KARAOKE \ -i aspect_ratio=16:9 invideo gen run --model lyrical_videos.audio \ --max-credits --idempotency-key lyric-1 \ -i audio= \ -i lyrical_style=KARAOKE -i aspect_ratio=16:9 invideo status --wait invideo notebook show ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the `url` that `invideo asset upload` returns for the song, a `…/notebook/seq-N.M` URL. - `` is a notebook page of the project, listed by `invideo notebook show `. - `` is the dry run's `.estimated_credits`. - `` is the `url` the paid `gen run` returns. `notebook show` on it gives the finished video's sequence URL. The timeline path from a terminal: ```bash invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo media audio.beats invideo edit show --json invideo branch new --name lyrics --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 12,48,95 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` `` is the song's, as above, and `` is the dry run's `credits`. `` comes from `invideo edit show ` for the branch command, then from `invideo edit show ` for `edit change`. `` is the `.branch_url` that `invideo branch new` returns. `ops.json` holds a bare JSON list of ops, the `operations` list of the call below. `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The key MCP call, in full, places the song and the art, then two lines with word timing, and styles them. `m1` and `m2` are the bin ids that `add_media` returns for the song and the art. At 30 fps, a word sung at 12.4 seconds starts on frame 372. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "insert_media", "asset": "m1", "track": "A2", "at_f": 0, "ripple": false }, { "op": "insert_media", "asset": "m2", "track": "V1", "at_f": 0, "ripple": false }, { "op": "add_captions", "track": "V2", "slides": [ { "text": "Hold the light", "start_f": 372, "end_f": 450, "words": [ { "text": "Hold", "start_f": 372, "end_f": 390 }, { "text": "the", "start_f": 390, "end_f": 400 }, { "text": "light", "start_f": 400, "end_f": 450 } ] }, { "text": "till the morning", "start_f": 456, "end_f": 540 } ], "style": { "font_size": 84, "align": "center", "color": "#ffffff" } } ] } ``` `` is the branch URL that `timeline_history` returns, and `` comes from `get_timeline` on it. A text clip moves as one piece. For each word to move on its own, the agent makes one `add_text` clip per word. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the upload, the captions, the text, the checks and the export. - **Tool ops:** `audio.beats`, `audio.markers`, `audio.sections`, `audio.separate`. The dry run shows its price before anything starts. - **Costs credits:** a run of `lyrical_videos.audio` or `lyrical_videos.video`, and the transcript of the song. Only the first call spends credits. The one-step model takes a few minutes to render. The timeline path takes longer to set up, and you can change any word after. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Sung words are harder to hear than speech. Most problems come from a misheard word or a line that shows too early. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | The export has no song, or a black background | The song or the art was never placed. Run the place step: `insert_media` on `A2` and `V1`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | A word in the lyrics is wrong | Fix it with `set_caption_slide_text`. Words that did not change keep their timing. | | Lines show before they are sung | The transcript times are in seconds of the song. Check the song starts at frame 0, or add its start to every time. | | The transcript is missing words in a loud part | Run `media` `audio.separate` on the song for the vocal stem, then transcribe the stem. | | `audio.transcript` returns a status, not words | It is still working. Call it again with the same file after `retry_after_s`. | | A line shows a little early or late | The agent moves that slide with `move_caption_slide` and `delta_seconds`, or moves one edge with `trim_caption_slide`. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | Avoid: running `generate` again to check on it | Instead: `read` the thread URL, or run `invideo status --wait`. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 9:16 lyric clip of the chorus of ./song.mp3, from 0:45 to 1:15, for a TikTok teaser. Big bold words, one or two at a time, each one landing on a beat. ``` ```text Put the lyrics over my band's live video ./live.mp4 in a kinetic style. Price lyrical_videos.video first and show me the styles I can pick. ``` ```text Make a karaoke version: the words of each line in white, building up as they are sung, two lines on screen at once, on a dark blurred version of my cover art. 16:9. ``` #### When to use something else invideo burns the lyrics into the video. For a synced lyrics file on Spotify or Apple Music, submit the lyrics through your distributor or a lyrics service such as Musixmatch. The agent can write the line times out of the caption slides for you. #### Related - [Make a Spotify Canvas and a music visualizer](/how-to/creators/spotify-canvas-and-visualizer) - [Make a music video with lip sync and beat sync](/how-to/film/music-video-lip-sync) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Make an intro, welcome video, outro or logo animation for your channel or business](/how-to/creators/intro-outro-logo-animation) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Add music and sound effects that clear rights Source: https://docs.invideo.io/how-to/creators/music-and-sound-effects.md Background music and sound effects from licensed stock or generated for your video, placed, faded and ducked under the voice. You get background music and sound effects (SFX) on your video that you can post without the video being muted or flagged for a song you do not own. The music sits under your voice and dips when you talk, the whooshes and hits land on your cuts, and everything fades in and out cleanly. Use invideo for this when you want music that clears rights in the same place as the edit: licensed stock music and generated music land on your timeline, and your agent sets the levels so the voice stays clear. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Add background music to my timeline. Find an upbeat, light stock track, put it under the whole video, and duck it under my voice. Add a whoosh on each cut and a soft hit on the title. Price the stock and the sound effects first, and let me pick the track. ``` In a chat app, you listen to the previews in the chat and pick one. In a terminal, the agent lists the results with their preview links, and you open them. #### What you need You need a video on a timeline, or a plan for one. Then pick where the sound comes from. - **The mood.** Upbeat, calm, cinematic, lo-fi, dramatic, or a genre. - **Stock or generated.** Stock music is a real recording you pick from a list. Generated music is new, made to your prompt and length. - **The sound effects.** Whoosh, pop, hit, click, crowd, rain, or "the sound of what is on screen". - **Your own music, if you have one.** A file you have the rights to. #### Steps Your agent edits on a branch and tells you what changed at each step. ##### Find or make the music The agent finds stock music first, and generates music or sounds only when stock has no fit. The agent searches `stock_music` with `search_library`, with words like "upbeat acoustic" or "calm piano". Each result has a preview for you to hear. The agent can read a track's tempo with `media` `audio.markers` and the `stock` id. Expected result: a short list of tracks with previews. The agent runs `find_models` with `output` audio and the job in words, like "instrumental background music". A good pick for music with no voice is `elevenlabs_music_v2_5_instrumental`. For a song with vocals it is `elevenlabs_music_v2_5_song`, and for your own lyrics `minimax_music_3` with `lyrics`. For a sound from words it is `elevenlabs_sfx`. Your agent can search for others with `find_models`. The agent reads the inputs of its pick with `get_model`. Expected result: the model's inputs. The agent calls `generate` with `elevenlabs_music_v2_5_instrumental`, a `prompt` and a `duration` in seconds, and `dry_run: true`. It tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It gets a thread URL, and reads the result with `read`, never with a second `generate`. Expected result: a sequence URL for the track. For a sound from words, the agent uses `elevenlabs_sfx` with a `prompt`, a `duration` within the range `get_model` gives, and `loop` true for a sound bed like rain. For a sound that matches a clip, it reads `pixverse_sfx` or `mmaudio_v2.mmaudio_v2_video_to_audio` with `get_model` and passes the clip as `video`. These two return a video with new sound. The agent takes the sound out with `media` `audio.extract` on that video's sequence URL. Each sound gets the same calls: `get_model` on the pick, `generate` with `dry_run: true` and the price told to you, then `generate` with `max_credits` and an `idempotency_key`. The agent reads each result with `read`. Expected result: a sequence URL per sound. ##### Mix and export The agent places the audio, sets the levels and checks the mix before export. The agent adds stock with `add_media` and `stock`, and generated sound with `add_media` and the sequence URL, on the timeline URL. It places each one on an audio track with `insert_media` at the frame where it belongs, and puts the sound effects on a track of their own. Expected result: music under the video and each effect on its cut. The agent sets the music's level with `set_audio_gain` in dB, and fades it in and out with `set_audio_fades`. Expected result: the music starts and ends soft. The agent adds the `ducker` audio effect to the music track with `add_audio_effect`. A new timeline ducks under `A1` by default, so the agent sets `set_sidechain_source` only when the voice is on another track. It sets how far the music drops with `set_audio_effect_parameter` and `reduction`. Expected result: the music dips each time you talk and comes back after. The agent runs `media` `audio.loudness` on the voice and music sources, `capture` at a few cuts, and `check_timeline`. Expected result: a clear voice over the music, and no issues from `check_timeline`. The agent runs `export` with `format` video and `target_lufs` for the platform, and reads the export card. Expected result: a card with status `completed`. The same job from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo edit show --json invideo branch new --name music --token invideo library search --library stock_music \ --query "upbeat acoustic" invideo asset add --stock invideo gen models --query "instrumental background music" invideo gen model --model elevenlabs_music_v2_5_instrumental invideo gen run --model elevenlabs_music_v2_5_instrumental \ --dry-run -i prompt="warm upbeat acoustic guitar" -i duration=60 invideo gen run --model elevenlabs_music_v2_5_instrumental \ --max-credits --idempotency-key music-1 \ -i prompt="warm upbeat acoustic guitar" -i duration=60 invideo gen model --model elevenlabs_sfx invideo gen run --model elevenlabs_sfx --dry-run \ -i prompt="fast air whoosh" -i duration=3 invideo gen run --model elevenlabs_sfx --max-credits \ --idempotency-key whoosh-1 -i prompt="fast air whoosh" -i duration=3 invideo status --wait invideo notebook show invideo asset add --media-url invideo edit show --json invideo edit change --timeline T1 \ --token --operations @ops.json invideo edit check invideo edit export --format video --quality 1080 \ --target-lufs -14 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` is your video's timeline URL, from `invideo edit new`, or the URL the editor shows. `` is its project, from `invideo project new`. - `` comes from `invideo edit show`: on `` for the branch, then on `` for the change. `` is the `.branch_url` that `invideo branch new` returns. - `` is a stock result's id from `invideo library search`. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is each dry run's `.estimated_credits`. - `` is the `url` the paid `gen run` returns. `` is the sound's sequence URL, listed by `invideo notebook show `. - `@ops.json` reads a bare JSON list of ops, the `operations` list of the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The key MCP call, shown as the full call, places the music and a whoosh, sets the level, and ducks the music under the voice on `A1`, the default duck source on a new timeline. `` is the branch URL `timeline_history` returns, and `` comes from `get_timeline` on it. `m5` and `m6` are the bin ids `add_media` returns for the music and the whoosh. The track ids come from `get_timeline`. At 30 fps, a cut at 4 seconds is frame 120. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "insert_media", "asset": "m5", "track": "A2", "at_f": 0, "ripple": false }, { "op": "insert_media", "asset": "m6", "track": "A3", "at_f": 110, "ripple": false }, { "op": "set_audio_gain", "target": "A2", "gain_db": -6 }, { "op": "add_audio_effect", "target": "A2", "target_kind": "track", "effect": "ducker" } ] } ``` In a second call, the agent sets `set_audio_fades` on the new music clip with `fade_in_f` and `fade_out_f`, and the ducker's `reduction` with `set_audio_effect_parameter`. #### Rights, in plain words Stock music and stock footage in invideo are licensed. Paid stock shows invideo's stock mark on the timeline, and the export renders it clean. Searching and listening cost nothing. Placing a paid stock track charges it. Some stock is not paid. Generated music and sound effects are made new for you. What you may do with each kind is on [Licensing and commercial use](/account/commercial-use). A song you did not make or license is not covered. A platform can mute or block a video that carries it. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** searching stock, previews, placing, levels, fades, ducking and the export. - **Tool ops:** `audio.markers`, `audio.extract`, `audio.loudness`. The dry run shows its price before anything starts. - **Costs credits:** each paid stock track you place, and each run of a music or sound model. Music and sound for one video take the agent a few minutes. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from music that is too loud under the voice, or a sound that lands off the cut. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The voice is hard to hear | Lower the music with `set_audio_gain`, or raise the ducker's `reduction`. | | The music does not duck | Check the `ducker` is on the music track. If the voice is not on `A1`, point `set_sidechain_source` at the voice track. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | A sound effect is late | Move it with `move_clip` to the frame of the cut. | | The music model refuses the prompt | It names a real artist or band. Describe the style instead: "warm 70s soul with horns". | | The music ends before the video | Ask for a longer `duration`, or crossfade two copies with `apply_audio_crossfade`. | | The platform mutes the video | The music is not licensed. Swap it for stock or generated music. | | CLI exit 5 | A credit limit. Pick fewer generations, or add credits. | | Avoid: setting levels by ear from the export only | Instead: run `audio.loudness` on each source, so you know which clip to fix. | #### Prompts to try Each prompt is a real variation of the job. ```text Make 60 seconds of calm lo-fi with no vocals for my study vlog, with elevenlabs_music_v2_5_instrumental. Fade it in, duck it under my voice and fade it out at the end. ``` ```text Add sound to my silent drone clips: wind, birds and a far-off river. Use mmaudio_v2.mmaudio_v2_video_to_audio on each clip and keep the levels low. ``` ```text Add a pop on each caption, a whoosh on each cut and a bass hit on the last line. Put the effects on their own track so I can mute them. ``` #### When to use something else invideo does not clear a song you do not own. For a famous song, license it through the label or a music licensing service, then bring in the file. For a full custom score with a composer's control over every note, use a music app such as Logic Pro or Ableton Live, then add the file. #### Related - [Licensing and commercial use](/account/commercial-use) - [Make Reels and Shorts from your footage: hook, captions, transitions, sound effects](/how-to/creators/reels-and-shorts-from-your-footage) - [Edit a long YouTube video](/how-to/creators/edit-a-long-youtube-video) - [Use ElevenLabs with invideo](/integrations/elevenlabs) - [Clean up the dialogue and keep the original](/how-to/film/dialogue-cleanup) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Repurpose one video for every platform Source: https://docs.invideo.io/how-to/creators/repurpose-for-every-platform.md Repurpose and resize one video for YouTube, Shorts, Reels, TikTok and LinkedIn, each shape on its own branch with its own crop and captions. You repurpose one video for every platform: resize it to each aspect ratio (16:9, 9:16, 4:5, 1:1), keep the face in frame, and move the captions clear of each app's buttons. Each version lives on its own branch of the same timeline, so a fix to one shape never breaks another. Use invideo for this when you want every version to stay editable: each platform gets a branch, you review each one in the editor, and a late change is the same operations list sent to each branch, not an export per platform to redo by hand. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Repurpose my timeline for YouTube, Shorts, Reels, TikTok and LinkedIn. Make one branch per platform in the right shape, keep my face in frame, put captions where each app's buttons do not cover them, and export each one. Show me frames from each branch before you export. ``` In a chat app, you open each branch's URL in invideo to review it. In a terminal, the agent saves frames for each branch to a folder with `--out`, and you open the folder. #### What you need Start from a finished cut. The agent works from it and never changes it. - **The master timeline.** The finished 16:9 cut, on main or on its own branch. - **The platforms.** YouTube, YouTube Shorts, Instagram Reels, TikTok, LinkedIn, a feed post. - **The shape for each.** 16:9 for YouTube, 9:16 for Shorts, Reels and TikTok, 4:5 or 1:1 for a feed or LinkedIn. - **Captions or not.** Most vertical posts are watched with the sound off. - **What to cut, if anything.** A shorter version for a platform that favors short posts. #### Steps Your agent works on one branch per platform and tells you what changed on each. ##### Prepare the branches The agent prepares the master and one branch per platform first. The agent reads the timeline with `get_timeline` and lists the branches with `timeline_history`. Expected result: the timeline's tracks and clips, and a `state_token`. If you want captions, the agent prices `audio.transcript` on the voice's sequence URL with `dry_run`, starts it with `max_credits`, and calls again after `retry_after_s` for the words. Then it sends `add_captions`, one slide per phrase with `words`. Captions added before branching carry into every branch. Expected result: a caption clip on the master. See the word-by-word captions page for the details. The agent runs `timeline_history` with `create_branch` and a `name` for each platform, such as "tiktok-9x16". Each call returns the branch's URL. Expected result: one branch URL per platform. The master stays as it was. On each branch, the agent runs `set_timeline_settings` with the `width`, `height` and `fps` for that shape. Each clip now fits inside the new frame. Expected result: the timeline in the new shape, with bars around the picture. ##### Reframe and export Then the agent reframes and checks each branch on its own. The agent fills the frame with `fill_frame` on each clip, then moves it with `set_position` so the face or the product stays in view. It zooms with `set_zoom` where a shot needs it. For a shot where a crop loses too much, it uses a model that fills the new area with generated picture. The agent runs `find_models` with "reframe to vertical". A good pick is `ltx_2_3_pro.reframe`, and `luma_ray_32.reframe` is another. Your agent can search for others with `find_models`. The agent reads the pick with `get_model`, then calls `generate` with `dry_run: true`, the source clip's sequence URL as `video` and `aspect_ratio` 9:16. It tells you the price, which goes by source length. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, reads the new sequence URL with `read`, and places it over the old shot. Expected result: every shot full frame, the subject in view. The agent adds guide lines with `create_guide` where the app's buttons, caption bar and profile name sit, from the platform's own safe-zone guide. Guides show in the editor and do not render. It moves the caption clip above the bottom zone with `set_position`, and resizes the text with `set_text_style`. Expected result: captions and titles clear of the guides. The agent runs `capture` on each branch at the start, each cut and the end, and runs `check_timeline`. It looks for a face cut at an edge and text under a guide. Expected result: frames that look right on every branch. The agent runs `export` with `format` video on each branch's URL, with an `idempotency_key` per branch, and reads each card until its status is `completed`. Expected result: one 1080p MP4 per platform. The same job from a terminal, for one platform: ```bash invideo agent register --name export INVIDEO_AS= invideo branch list invideo edit show --json invideo branch new --name tiktok-9x16 --token invideo edit show --json invideo gen models --query "reframe to vertical" invideo gen model --model ltx_2_3_pro.reframe invideo gen run --model ltx_2_3_pro.reframe --dry-run \ -i video= -i aspect_ratio=9:16 invideo gen run --model ltx_2_3_pro.reframe \ --max-credits --idempotency-key reframe-c1 \ -i video= -i aspect_ratio=9:16 invideo status --wait invideo notebook show invideo edit change --timeline T1 \ --token --operations @tiktok-ops.json invideo edit capture --at 0,5,12,29 --out ./tiktok invideo edit check invideo edit export --format video --quality 1080 \ --idempotency-key tiktok-v1 --json invideo status --wait invideo notebook show --out ./exports/tiktok ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` is the master timeline's URL, from `invideo edit new` or the editor. `` is its project, from `invideo project new`. - `` comes from `invideo edit show`: on `` for the branch, then on `` for the change. The main token is stale on the branch. - `` is the `.branch_url` that `invideo branch new` returns, here the TikTok branch. - `` is the source clip's sequence URL, `…/notebook/seq-N.M`, from `invideo asset upload` or `invideo notebook show `. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is the dry run's `.estimated_credits`. `` is the `url` the paid `gen run` returns, and `invideo notebook show` on it lists the new shot's sequence URL. - `@tiktok-ops.json` reads a bare JSON list of ops, the `operations` list of the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./exports/tiktok/export.mp4`, and the agent renames it. The key MCP call for a 9:16 branch, shown as the full call, sets the shape, fills and moves one shot, adds two guides and lifts the captions. `` is the URL `timeline_history` returns for the branch, and `` comes from `get_timeline` on it. `c1` is a shot and `c9` the caption clip, ids from `get_timeline`. The guide positions here are examples. The agent takes them from the platform's guide. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "set_timeline_settings", "timeline": "T1", "width": 1080, "height": 1920, "fps": 30 }, { "op": "fill_frame", "clip": "c1" }, { "op": "set_position", "clip": "c1", "x": -140, "y": 0 }, { "op": "create_guide", "timeline": "T1", "orientation": "horizontal", "position": 0.1, "locked": true }, { "op": "create_guide", "timeline": "T1", "orientation": "horizontal", "position": 0.8, "locked": true }, { "op": "set_position", "clip": "c9", "x": 0, "y": 420 } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the branches, the new shapes, the manual reframe, the guides, the checks and every export. - **Costs credits:** the transcript for the captions, once, and any shot reframed with `ltx_2_3_pro.reframe` or `luma_ray_32.reframe`. A reframe is priced per second of the source clip. Each platform version takes the agent a few minutes. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a face that falls out of the new frame, or captions under the app's buttons. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | CLI exit 3 on the first change after `invideo branch new` | The main token is stale on the branch. Run `invideo edit show ` and use its `state_token`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | A face is cut off in the vertical version | Move the clip with `set_position`, or zoom out with `set_zoom`, then `capture` again. | | `fill_frame` is refused | The clip's zoom is animated. Remove the zoom lane, or set the size with `set_zoom`. | | The reframe model refuses the clip | The clip is too long or in a format it does not take. Read its limits with `get_model`, or split the clip and reframe the parts. | | Captions sit under the app's buttons | Move the caption clip up with `set_position`, inside the guides. | | A fix seems to show on the wrong branch | Branches are separate. Read the branch URL you mean with `get_timeline` and check its name. | | `create_branch` refused as stale | Someone edited since your read. Read again and use the new `state_token`. | | CLI exit 3 | The timeline changed since your read. Run `invideo edit show` again. | | Avoid: the agent edits main to make the vertical cut | Instead: one branch per platform, and the master stays as it is. | | Avoid: running `export` again to check on it | Instead: `read` the export card, or run `invideo status --wait`. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 9:16 and a 1:1 version of this cut, on two branches. On the 9:16 one, put the captions in the upper middle, and keep the speaker's face in the top half. ``` ```text Make a LinkedIn version of my YouTube video: 1:1, the first 60 seconds only, bold captions on, no end screen. Leave the YouTube cut as it is. ``` ```text My main cut changed at 0:42. Apply the same change to every platform branch and export them all again. ``` #### When to use something else invideo does not post to the platforms. Upload each export in the app, or use a scheduler such as Buffer or Later. A reframe model does not track a face. It fills new picture around the shot. For a crop that follows a moving face shot by shot, the agent sets `set_position` per shot, or you finish that shot in an editor with face tracking, such as CapCut or DaVinci Resolve. #### Related - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Make Reels and Shorts from your footage: hook, captions, transitions, sound effects](/how-to/creators/reels-and-shorts-from-your-footage) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Test hooks on one ad, with branches](/how-to/marketing/test-hooks-on-branches) - [Check your video before you say it is done](/how-to/check-your-video) ### Make Reels and Shorts from your footage Source: https://docs.invideo.io/how-to/creators/reels-and-shorts-from-your-footage.md Turn your raw footage into vertical Reels, Shorts and TikToks with a strong hook, word-by-word captions, quick transitions and sound effects. You turn your raw footage or a long video into short vertical clips (Reels, Shorts, TikToks) that open on a hook. The best line comes first, captions pop word by word, cuts land with a quick transition, and a whoosh or a pop marks each beat. Dead air, "um" and long pauses are gone. Use invideo for this when you want your agent to pick the moments from what you said: it reads a transcript of your footage, finds the hook and the best lines, and builds each clip on a timeline you can still change. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make three 9:16 Shorts from ./talk.mp4. Read the transcript, pick the three strongest moments, and start each one with its best line as the hook. Word-by-word captions, a quick transition and a whoosh on each cut, no pauses. Price the transcript first, show me the picks and frames before you export. ``` In a chat app, you drag the footage into the project's Media panel in invideo, then name it in the chat. In a terminal, you name the file or the folder and the agent uploads it. #### What you need Raw footage works best when you talk to the camera. The agent finds the moments in your words. - **Your footage.** A talking-head video, a vlog, a podcast clip, a stream or a long YouTube video. - **How many clips.** One, or a set of clips from one video. - **The length.** Short and punchy, or a longer story. - **The style.** Caption look, transitions, sound effects, music or none. - **The platforms.** Reels, Shorts, TikTok, LinkedIn. The shape is 9:16 for all of them, or 1:1 or 4:5 for a feed. #### Steps Your agent edits on a branch and tells you what changed at each step. ##### Cut the clips The agent finds the hook and cuts each clip first. The agent uploads the footage with `start_upload` and `add_media`. It makes a timeline with `new_timeline` at 9:16 and a branch with `timeline_history`. Expected result: a timeline URL and a media bin id for the footage. The agent runs `media` `audio.transcript` on the footage's sequence URL from `add_media`, after a `dry_run` and the price told to you, then with `max_credits`. A transcript refuses a media bin `asset_id`. The agent calls again after `retry_after_s` for the words. Expected result: every word with its time. The agent reads the transcript for lines that stand alone: a strong claim, a surprise, a question, a short story with an end. It picks the best line of each moment as the hook. It tells you its picks with timecodes before it edits. Expected result: a list of moments and hooks for you to approve. The agent places the hook first and the rest of the moment after it, with `place_media` and the source start and end in seconds, with `linked_audio` true. Inside each part, it finds pauses with `audio.content` and the "um" and "uh" in the transcript, cuts them with `split_clip`, and removes them with `delete_clip` in `close_gap` mode. Expected result: a tight clip that opens on the hook. ##### Finish and export Then the agent fills the frame, adds captions and sound, and checks each clip. The agent runs `fill_frame` on each clip and moves it with `set_position` so your face stays in view. For a wide shot that loses too much, it runs `find_models` with "reframe to vertical". A good pick is `ltx_2_3_pro.reframe`. Your agent can search for others with `find_models`. The agent reads the pick's inputs with `get_model`, then calls `generate` with `dry_run: true`, the clip's sequence URL as `video` and `aspect_ratio` 9:16, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, and reads the new sequence URL with `read`. Expected result: your face in frame in every shot. The agent adds word-by-word captions with `add_captions`, using the transcript's word times, and styles them with `set_text_style`. It adds a short transition such as `slide_blur`, `shake_zoom` or `flash` at each cut with `add_transition`. For a whoosh or a pop, it runs `find_models` with "whoosh sound effect". A good pick is `elevenlabs_sfx`, which the agent reads with `get_model`. It calls `generate` with `dry_run: true`, a `prompt` and a short `duration` within the range `get_model` gives, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, reads the new sequence URL with `read`, and places it at each cut with `insert_media`. For music, it adds the `ducker` to the music track with `add_audio_effect`. A new timeline ducks under `A1` by default, so the agent sets `set_sidechain_source` only when your voice is on another track. Expected result: captions on every word, a sound on each cut, and music that dips when you talk. The agent runs `capture` at the hook, each cut and the end, and runs `check_timeline`. It checks that the captions sit above the app's buttons. Expected result: the hook shows in the first frames, and the captions are readable. The agent runs `export` with `format` video, one call per clip with `start` and `end`, or one timeline per clip. It reads each card until its status is `completed`. Expected result: one 1080p MP4 per clip. The same job from a terminal: ```bash invideo project new --title "Shorts from the talk" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Short 1" --width 1080 \ --height 1920 invideo asset upload ./talk.mp4 invideo media audio.transcript --dry-run invideo media audio.transcript \ --max-credits invideo media audio.content --asset m1 invideo gen models --query "whoosh sound effect" invideo gen model --model elevenlabs_sfx invideo gen run --model elevenlabs_sfx --dry-run \ -i prompt="short fast whoosh" -i duration=3 invideo gen run --model elevenlabs_sfx --max-credits \ --idempotency-key whoosh-1 -i prompt="short fast whoosh" -i duration=3 invideo status --wait invideo notebook show invideo edit show --json invideo branch new --name short-1 --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @ops.json invideo edit capture --at 0,1.5,8,20 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the `url` that `invideo asset upload` returns, and `m1` is the bin id in the same result. Reads like `audio.content` take `--asset m1`. A transcript refuses it. - `` is each dry run's `.estimated_credits`. `` is a notebook page of the project, listed by `invideo notebook show `. `` is the `url` the paid `gen run` returns, and `invideo notebook show` on it lists the sound's sequence URL. - `` comes from `invideo edit show`: on `` for the branch, then on `` for the change. `` is the `.branch_url` that `invideo branch new` returns. - `@ops.json` reads a bare JSON list of ops, the `operations` list of the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The key MCP call, shown as the full call, places the hook, then the moment. `` is the branch URL `timeline_history` returns, and `` comes from `get_timeline` on it. `m1` is the footage's bin id from `add_media`. The hook is 312.4 to 316.0 seconds in the source. The moment runs from 290.0 to 312.0 seconds. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "place_media", "asset": "m1", "track": "V1", "at_f": 0, "source_start_seconds": 312.4, "source_end_seconds": 316.0, "mode": "append", "linked_audio": true }, { "op": "place_media", "asset": "m1", "track": "V1", "at_f": 108, "source_start_seconds": 290.0, "source_end_seconds": 312.0, "mode": "append", "linked_audio": true } ] } ``` The agent also sends `fill_frame` on each clip, `add_transition` with `left_clip`, `right_clip`, `type`, `in_f` and `out_f`, and `add_captions` with the slides and words. These can go later in the same call, with the clip ids the call makes, or in a second call after `get_timeline`. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Tool ops:** `audio.content`. The dry run shows its price before anything starts. - **Free:** the upload, the cuts, the reframe by hand, the captions, the transitions, the checks and the exports. - **Costs credits:** the transcript, once per file, the sound effects from `elevenlabs_sfx`, paid stock music, and any shot run through `ltx_2_3_pro.reframe`. A set of clips from one video takes the agent a few minutes once the transcript is back. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a weak hook, captions under the app's buttons, or a cut in the middle of a word. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the footage's sequence URL from `add_media` or `invideo asset upload`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | The hook is weak | Ask for three hook options. The agent puts each on its own branch so you can compare. | | A cut lands in the middle of a word | The agent moves the cut to the word's end time in the transcript with `trim_clip`. | | Captions are behind the app's buttons | Move the caption clip up with `set_position`. Add safe-zone guides with `create_guide`. | | A face is cut off | Move the clip with `set_position`, or zoom out with `set_zoom`. | | `audio.transcript` returns a status, not words | It is still working. Call it again after `retry_after_s`. Only the first call costs credits. | | The transition feels slow | Shorten it with `resize_transition`, or use `cut`. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: transcribing the file again for each clip | Instead: the transcript is kept on the file. Call `audio.transcript` again for the words. Only the first call spends credits. | | Avoid: saying done without looking | Instead: `capture` the first frames, where the hook is. | #### Prompts to try Each prompt is a real variation of the job. ```text Make one LinkedIn clip from my webinar recording ./webinar.mp4: 1:1, the single best tip, a clear title card on top, clean captions, no sound effects. Professional, not flashy. ``` ```text Make five TikToks from my podcast episode. Each one opens on a question someone asks. Big yellow captions, a pop on each caption change, and a light leak transition between parts. ``` ```text Cut my vlog ./day.mp4 into one 9:16 Short. Start with the funniest line, cut every pause longer than half a second, add a whoosh on each cut and upbeat stock music ducked under my voice. ``` #### When to use something else invideo does not post or schedule. Upload each clip in the app, or use a scheduler such as Buffer or Later. invideo does not score clips for "virality". The agent picks moments by reading what you said. For an automatic score, a clip tool such as OpusClip does that. #### Related - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Cut ums, pauses and retakes](/how-to/creators/cut-ums-and-retakes) - [Repurpose one video for every platform](/how-to/creators/repurpose-for-every-platform) - [Edit a podcast episode and pull clips from it](/how-to/creators/podcast-edit-and-clips) - [When to use OpusClip or Descript vs invideo](/compare/opusclip-descript) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) ### Add word-by-word captions Source: https://docs.invideo.io/how-to/creators/word-by-word-captions.md Word-by-word captions, or subtitles, on your video: each word appears as it is said, in your font and colors, and you can fix any word. You add word-by-word captions, also called subtitles or karaoke captions, to your video. Each line builds up word by word as it is said, in your font and color, and the captions sit where the app's buttons do not cover them. The captions stay editable: fix a misheard name, change the style, or turn them off for one export. Use invideo for this when you want captions you can still edit after they are made: they are a caption track on your timeline, not text burned into the file, until you export. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Add word-by-word captions to my timeline. Three or four words per line, white text with a black outline, building up as I speak, in the lower middle. My name is spelled "Siobhan". Price the transcript first and show me frames before you export. ``` In a chat app, you drag the video into the project's Media panel in invideo, then ask in the chat. In a terminal, you name the file and the agent uploads it. #### What you need The video with speech is all you must have. The rest sets the look. - **The video.** Any video where someone talks: a talking head, a podcast, a tutorial, an interview. - **Names and words to spell right.** Your name, brand names, slang. - **The look.** Font, size, text color, an outline or a box behind. - **Words per line.** One word at a time for punchy Shorts, a few words for most videos. - **Where on screen.** Lower middle, center, or upper middle for vertical video. #### Steps Your agent edits on a branch and tells you what changed at each step. ##### Add the captions The agent makes the captions from the transcript first. The agent uploads the video with `start_upload` and `add_media` onto the timeline URL, and creates a branch with `timeline_history`. Expected result: a sequence URL and a media bin id for the video, and a branch URL. The agent prices `media` `audio.transcript` on the video's sequence URL from `add_media` with `dry_run`, tells you the price, and starts it with `max_credits`. A transcript refuses a media bin `asset_id`. The agent calls again after `retry_after_s` for the words. Each word has a start, an end and a speaker. Expected result: the full list of words with times. The agent splits the words into short lines at pauses and at the end of each phrase, with the number of words you asked for. It fixes names you gave it. It turns the times from seconds in the file into frames on the timeline. Expected result: a list of slides, each with its words and times. The agent runs `add_captions` with the slides, each with its `words`, and a `style` with your font, size, `color`, and `stroke` or `background_color`. Expected result: a caption clip on a video track, each line building up word by word as it is said. ##### Style, fix and export Then the agent styles the captions, fixes words and checks them. The agent moves the caption clip with `set_position`, and changes the look later with `set_text_style`. For a font of your own, it brings in the font file with `add_media` and uses its id as `font`. Expected result: captions in your style, where you want them. The agent fixes a line with `set_caption_slide_text`. Words that did not change keep their timing. It splits a word in two with `split_caption_fragment`, or joins two pieces with `merge_caption_fragment`. Expected result: every word spelled right. The agent runs `capture` at a few lines, checks that the text is readable on a phone, and runs `check_timeline`. Expected result: the captured lines match the words said at those times. The agent runs `export` with `format` video. For an export with no captions, it turns the caption clip off with `set_clip_enabled` and exports again. Expected result: an export card with status `completed` for each export. The same job from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo asset upload ./talk.mp4 invideo media audio.transcript --dry-run invideo media audio.transcript \ --max-credits invideo edit show --json invideo branch new --name captions --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @captions.json invideo edit capture --at 2,10,30 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. `` is your project's URL, from `invideo project list`. - `` is your video's timeline URL, from `invideo edit new` or the editor. - `` is the `url` that `invideo asset upload` returns, a `…/notebook/seq-N.M` URL. A transcript refuses a bin `--asset`. - `` is the dry run's `.estimated_credits`. - `` comes from `invideo edit show`: on `` for the branch, then on `` for the change. `` is the `.branch_url` that `invideo branch new` returns. - `@captions.json` reads a bare JSON list of ops, the `operations` list of the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The key MCP call, shown as the full call, adds two lines of captions with word timing and the style. `` is the branch URL `timeline_history` returns, and `` comes from `get_timeline` on it. At 30 fps, a word said at 1.2 seconds starts on frame 36. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "add_captions", "track": "V2", "slides": [ { "text": "Hi, I'm Siobhan", "start_f": 36, "end_f": 75, "words": [ { "text": "Hi,", "start_f": 36, "end_f": 48 }, { "text": "I'm", "start_f": 48, "end_f": 57 }, { "text": "Siobhan", "start_f": 57, "end_f": 75 } ] }, { "text": "and this is my kitchen", "start_f": 80, "end_f": 132 } ], "style": { "font_size": 72, "font_weight": 800, "color": "#ffffff", "stroke": true, "stroke_color": "#000000", "stroke_width": 6, "align": "center" } } ] } ``` #### Burned-in styles from a model For a designed caption look in one step, the agent can run a subtitle model on the video instead. These burn the captions into a new video file, so you edit them by running the model again, not on the timeline. - **`invideo_subtitles`.** Pick a `subtitle_style` such as `SUBTITLE_HIGHLIGHT` or `BOLD_TEXT_BEHIND`, and a `safe_zone` of `tiktok` or `instagram`. - **`veed_subtitles`.** Pick a `preset`, a `position`, a `vocabulary` list for names, and a `translation_language` for translated subtitles, which costs more. The agent runs `find_models` with "burned-in subtitles" to pick one, and reads its inputs with `get_model`. It calls `generate` with `dry_run: true`, the video's sequence URL as `video` and the style, and tells you the price, which goes by video length. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL for the new video, read with `read`. The agent never calls `generate` again to check. ```bash invideo gen models --query "burned-in subtitles" invideo gen model --model invideo_subtitles invideo gen run --model invideo_subtitles --dry-run \ -i video= -i subtitle_style=SUBTITLE_HIGHLIGHT \ -i safe_zone=tiktok invideo gen run --model invideo_subtitles \ --max-credits --idempotency-key subs-1 \ -i video= -i subtitle_style=SUBTITLE_HIGHLIGHT \ -i safe_zone=tiktok invideo status --wait invideo notebook show ``` `` is the video's project. `` is a notebook page of the project, listed by `invideo notebook show `. `` is the video's sequence URL, from `invideo asset upload` or an export card. `` is the dry run's `.estimated_credits`. `` is the `url` the paid `gen run` returns, and `invideo notebook show` on it lists the new video's sequence URL. #### Captions file out invideo exports video, not a captions file. For an SRT or VTT file, the agent reads the caption slides with `get_timeline` in mode `collection` and writes the file itself. See the page on an SRT captions file for an LMS. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the captions, the style, the fixes, turning captions on and off, and the export. - **Costs credits:** the transcript, once per file, or a run of `invideo_subtitles` or `veed_subtitles`, priced by the length of the video. Captions take the agent a few minutes once the transcript is back. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a misheard word, lines that are too long, or captions under the app's buttons. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | A name is spelled wrong | Fix the line with `set_caption_slide_text`. Words that did not change keep their timing. | | Lines are too long to read | Ask for fewer words per line. The agent builds the slides again. | | `add_captions` refused | A word sits outside its slide, or a slide's text is empty. Each word's times must fall inside its slide. | | Captions are behind the app's buttons | Move the caption clip with `set_position`, or add guides with `create_guide`. | | A line shows all at once, not word by word | The slide has no `words`. Add them with their times from the transcript. | | `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the video's sequence URL from `add_media` or `invideo asset upload`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | Avoid: promising the spoken word in its own color on the timeline | Instead: the words build up as spoken. For a burned-in highlight look, try a subtitle model style such as `SUBTITLE_HIGHLIGHT`. | | `audio.transcript` returns a status, not words | It is still working. Call it again after `retry_after_s`. Only the first call spends credits. | | Avoid: burning in captions when you may change them | Instead: use `add_captions` on the timeline, and export when they are right. | | Avoid: saying done without looking | Instead: `capture` a few lines and read them against the transcript. | #### Prompts to try Each prompt is a real variation of the job. ```text Add one-word-at-a-time captions to my Short, big and bold in the center, each word popping in. Use my font ./fonts/brand.otf. ``` ```text Add clean captions to my tutorial, two lines at most, white on a dark box at the bottom. Then export two versions: one with captions and one without. ``` ```text Add Spanish subtitles to my video with veed_subtitles. Price it first, and keep my brand name "Lumio" spelled as it is. ``` #### When to use something else invideo makes captions in the picture, not a closed caption track inside the file. For SCC files, or broadcast closed captions, use a captioning service such as Rev or 3Play Media. For a sidecar SRT or VTT, the agent writes it from the caption slides. #### Related - [Make an SRT captions file for an LMS](/how-to/training/srt-for-an-lms) - [Make Reels and Shorts from your footage: hook, captions, transitions, sound effects](/how-to/creators/reels-and-shorts-from-your-footage) - [Cut ums, pauses and retakes](/how-to/creators/cut-ums-and-retakes) - [Repurpose one video for every platform](/how-to/creators/repurpose-for-every-platform) - [Make closed captions and audio description for ADA Title II and Section 508](/how-to/training/captions-for-ada-508) - [Check your video before you say it is done](/how-to/check-your-video) ### Cut ums Source: https://docs.invideo.io/how-to/creators/cut-ums-and-retakes.md Remove filler words, ums, long pauses and bad takes from your talking video, as cuts on a branch you can undo, with the original kept. You cut the filler words and ums from your talking video: every "um", "uh", long pause and false start, and the takes you redid. Each cut is a real edit on a branch of your timeline, so you can see every one, put any of them back, and your original recording is never changed. Use invideo for this when you want to check the cuts before you keep them: your agent finds the ums and retakes in a transcript, makes the cuts on a branch, and the original stays in the media bin and on main. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Clean up my talking video on a new branch. Cut every um and uh, every pause longer than 0.7 seconds, and every retake: when I say a line twice, keep the last one. List the cuts with timecodes before you make them. Price the transcript first. ``` In a chat app, you drag the recording into the timeline's media bin in invideo, then ask in the chat. In a terminal, you name the file and the agent uploads it. #### What you need A recording where you talk is enough. Tell the agent how tight you want it. - **The recording.** A talking head, a tutorial, a voice-over, a podcast. - **What counts as filler.** Um and uh only, or also "like", "you know", "so". - **How long a pause can be.** Short for a fast Short, longer for a calm tutorial. - **Retakes.** Say if you redid lines. The agent keeps the last take unless you say another. #### Steps Your agent cuts on a branch and tells you what it cut, with timecodes. The agent reads the timeline with `get_timeline` for its `timeline_id`, its `state_token` and the recording's asset id in the media bin. It calls `timeline_history` with `action: "create_branch"` and a `name`, then `action: "checkpoint"` with the new `branch_slug` and a `title`. Each call takes the latest `expected_state_token`. Expected result: a branch URL and a checkpoint. Main stays as it was. The agent prices `media` with `op: "audio.transcript"` and `dry_run: true`, on the recording's sequence URL as `url`, the one `add_media` returned, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. Expected result: every word with its start and end, the ums and uhs included. The agent calls `media` with `op: "audio.content"` on the same file. It returns the spans of speech, music, effects and silence. The agent keeps the silences longer than the pause you set. Expected result: a list of silent spans with times. The agent reads the transcript for lines you said twice, or a sentence you stopped and started again. It keeps the last take and marks the earlier ones to cut. Expected result: a list of retakes, each with the take it keeps. The agent lists every cut with its time, its kind (filler, pause or retake) and the words around it. You approve the list, or take items off it. Expected result: an approved list of cuts. The agent turns each span from seconds in the file into frames on the timeline, with a few frames of room so no word is clipped. It cuts each span with `edit_time_range` in `close_gap` mode, from the last cut to the first, so the times of the cuts still to make do not move. To keep the music in place, it locks the music track first with `set_track_locked`. For a cut on one clip only, it uses `split_clip` and `delete_clip` instead. Expected result: a tighter timeline on the branch. The agent runs `capture` around a few cuts and `check_timeline`, and gives you the branch URL to watch. Expected result: no clipped words and no jumps you did not want. The same job from a terminal. The CLI calls a timeline an edit. ```bash invideo agent register --name export INVIDEO_AS= invideo edit show --json invideo branch new --name clean-up --token invideo edit show --json invideo branch checkpoint --title "before cuts" \ --token invideo media audio.transcript --dry-run invideo media audio.transcript \ --max-credits invideo media audio.content --asset m1 invideo edit show --json invideo edit change --timeline T1 --token \ --operations @cuts.json invideo edit capture --at 10,42,95 --out ./frames invideo edit check ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. `` is your project's URL, from `invideo project list`. - `` is the timeline's URL from `invideo edit new`. `invideo edit show` on it gives the main ``, the timeline id `T1` and the recording's bin id `m1`. - `` is the `.branch_url` that `invideo branch new` returns. Every later command uses it. - After the branch, `` is the branch's own token from `invideo edit show `. The main token is stale on the branch, so the agent reads the branch again before each change. - `` is the `url` that `invideo asset upload` returned for the recording. A transcript refuses `--asset`. - `` is the dry run's `.estimated_credits`. - `@cuts.json` reads a file that holds a bare JSON list of ops, the `operations` list of the call below. The full `timeline_history` call for the branch, before any cut. `` is the timeline's URL from `new_timeline` or `list_projects`, and `` comes from `get_timeline`. ```json { "url": "", "action": "create_branch", "name": "clean-up", "expected_state_token": "" } ``` The key MCP call, in full, locks the music and makes three cuts, last first. `` is the branch URL that `timeline_history` returns, and `` is the branch's own token from `get_timeline` on it. `A2` is the music track id from `get_timeline`. At 30 fps, a pause from 95.2 to 96.8 seconds is frames 2856 to 2904. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "set_track_locked", "track": "A2", "locked": true }, { "op": "edit_time_range", "timeline": "T1", "start_f": 2856, "end_f": 2904, "mode": "close_gap" }, { "op": "edit_time_range", "timeline": "T1", "start_f": 1250, "end_f": 1262, "mode": "close_gap" }, { "op": "edit_time_range", "timeline": "T1", "start_f": 300, "end_f": 480, "mode": "close_gap" } ] } ``` The list lands all or none. If one cut is refused, nothing changes, and the agent reads the refusal and fixes that cut. #### Nothing is lost Every cut is on the branch. Main keeps the uncut timeline, and the recording stays whole in the media bin. To undo all of it, the agent calls `timeline_history` with `action: "restore"`, the `branch_slug` and the `checkpoint_slug` that `action: "list"` names. To undo one cut, it sends two ops in one `edit_timeline` call, shown below as a bare list of ops. `edit_time_range` with `mode: "insert"` opens empty time at the cut, as long as the cut. `place_media` puts the missing part of the file back in that time, with `source_start_seconds` and `source_end_seconds` from the transcript. `m1` is the recording's asset id from `get_timeline`. ```json [ { "op": "edit_time_range", "timeline": "T1", "start_f": 1250, "end_f": 1262, "mode": "insert" }, { "op": "place_media", "asset": "m1", "track": "V1", "at_f": 1250, "source_start_seconds": 52.1, "source_end_seconds": 52.5, "mode": "overwrite", "linked_audio": true } ] ``` You keep the branch by accepting it in the editor. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the branch, the checkpoint, every cut, the checks and the export. - **Tool ops:** `audio.content`. The dry run shows its price before anything starts. - **Costs credits:** the transcript with `audio.transcript`, once per file. Only the first call spends credits. The cuts take the agent a few minutes once the transcript is back. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from cuts that are too tight, or cuts made in the wrong order. | Symptom | Fix | | --- | --- | | `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 "What the command names is not there" | The call named a media bin asset. Pass the recording's sequence URL, from `add_media` or `invideo asset upload`. | | CLI exit 3 on the first command after `invideo branch new` | The main token is stale on the branch. Run `invideo edit show ` and use its `state_token`. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | A word sounds clipped | Leave more room around each cut. The agent widens the span by a few frames. | | Cuts land in the wrong place | The cuts were made first to last, so later times moved. Restore the checkpoint and cut from last to first. | | The music jumps at each cut | The music track was not locked. Lock it with `set_track_locked`, then cut. Trim the music's end to the new length with `trim_clip`. | | It sounds too rushed | Raise the pause length you allow, and keep short breaths. | | One cut is wrong | Undo that one cut as under "Nothing is lost", or restore the checkpoint. | | The wrong take was kept | Tell the agent which take to keep. It restores the checkpoint and cuts again. | | `set_track_locked` refused | Check the `track` is a track id from `get_timeline`. | | Refusal `code: "revision_conflict"`, or CLI exit 3 | Someone changed the timeline since your read. Read it again with `get_timeline` or `invideo edit show`, and send the cuts with the new `state_token`. | | Avoid: cutting on main | Instead: cut on a branch, with a checkpoint first. | | Avoid: cutting before you approve | Instead: the agent lists the cuts first, with timecodes. | #### Prompts to try Each prompt is a real variation of the job. ```text Only cut the ums and uhs in my podcast, nothing else. Keep the pauses. Show me how many you found and where. ``` ```text I recorded my course lesson with lots of retakes. Keep the last take of each line, cut the false starts, and leave a short breath between sentences. ``` ```text Make my vlog tight for a Short: cut every pause, every um, and the word "basically". Then add word-by-word captions on the cut version. ``` #### When to use something else invideo cuts the sound and the picture together. To remove an um from the sound alone while the picture runs on, with a crossfade inside a word, use an audio editor such as Audacity or Adobe Audition, then bring the cleaned file back in. #### Related - [Edit a long YouTube video](/how-to/creators/edit-a-long-youtube-video) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Edit a podcast episode and pull clips from it](/how-to/creators/podcast-edit-and-clips) - [Build an assembly cut from a script by matching lines to takes](/how-to/creators/assembly-cut-from-a-script) - [Check your video before you say it is done](/how-to/check-your-video) ### Edit a long YouTube video Source: https://docs.invideo.io/how-to/creators/edit-a-long-youtube-video.md Edit your long YouTube recording: cut the dead air and ums, add b-roll over the talk, music under it, captions, chapters and a thumbnail still. You get your long YouTube recording edited into a video people watch to the end. The dead air, ums and false starts are cut, b-roll covers the long talking stretches, music runs under your voice and dips when you talk, captions are on, chapters are marked, and you get a still for the thumbnail. Use invideo for this when you want an editor that reads your whole recording: your agent works from a transcript of every word, makes each change on a branch, and you can review and undo any cut on the timeline. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Edit my YouTube video ./episode-12.mp4 on a branch. Cut dead air and ums, add stock b-roll over long talking parts, calm music ducked under my voice, and captions. Mark chapters and give me the chapter list. Price the transcript and stock first, and show me frames before export. ``` In a chat app, you drag the recording into the project's Media panel in invideo. In a terminal, you name the file and the agent uploads it, which works for large files. #### What you need Your recording is the main input. The rest shapes the edit. - **The recording.** The full take from your camera or screen recorder, MP4 or MOV, as large as it is. - **Your own b-roll, if you have it.** Clips of the product, the place, your screen. - **The music or the mood.** Stock, generated, or your own track. - **The caption look.** Or no captions. - **What must stay.** Jokes, a sponsor read, a call to action. #### Steps Your agent edits on a branch and tells you what changed at each step. The agent calls `start_upload` with the `file_name`, sends the bytes with one PUT to the `upload_url`, then calls `add_media` with the `upload_id` and the timeline URL. Expected result: a sequence URL and a media bin id. The agent makes a 16:9 timeline with `new_timeline`, creates a branch with `timeline_history`, saves a `checkpoint` on it, and places the recording with `place_media` and `linked_audio` true. Expected result: the recording on the timeline, with its sound. The agent prices `media` `audio.transcript` with `dry_run` on the recording's sequence URL from `add_media`, starts it with `max_credits`, and calls again after `retry_after_s` for the words. It runs `audio.content` for the silent spans. It shows you a cut list of pauses, ums and false starts. Once you approve, it cuts each span with `edit_time_range` in `close_gap` mode, from the last to the first. Expected result: a tighter cut on the branch. The agent reads the transcript for long stretches on one topic. It searches `stock_video` with `search_library` using the words you say there, and adds your picks with `add_media` and `stock`. It places each one on a track above with `place_media` in `place_on_top` mode and `linked_audio` false, so your voice keeps playing. For a shot stock does not have, it runs `find_models` with the shot in words and reads its pick with `get_model`. A good pick is `seedance_2_5.r2v`, where a `prompt` alone is enough. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: b-roll over the talking parts, your voice under it, and a sequence URL for each generated shot, read with `read`. The agent adds a stock track from `stock_music`. For music made to the episode's length, it runs `find_models` with "instrumental music bed" and reads its pick with `get_model`. A good pick is `elevenlabs_music_v2_5_instrumental`. It calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, and reads the sequence URL with `read`. It places the track with `insert_media` on its own audio track, and sets its level with `set_audio_gain`. It adds the `ducker` to the music track with `add_audio_effect`. A new timeline ducks under `A1` by default, so the agent sets `set_sidechain_source` only when your voice is on another track. Expected result: music that dips when you talk. The agent adds captions with `add_captions` from the transcript's word times. It marks each topic change with `add_marker` and a `name`, then writes the chapter list with timecodes for your YouTube description. Expected result: captions on the timeline, and a chapter list you can paste. The agent runs `capture` at the start, a few cuts, the b-roll and the end, and runs `check_timeline`. Then it runs `export` with `format` video and a `target_lufs` for YouTube, and a second `export` with `mode` image and `still_at` the frame you want for the thumbnail. Expected result: a 1080p MP4 and a still image, each on a card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Episode 12" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Episode 12" invideo asset upload ./episode-12.mp4 invideo edit show --json invideo branch new --name first-cut --token invideo media audio.transcript --dry-run invideo media audio.transcript \ --max-credits invideo media audio.content --asset m1 invideo library search --library stock_video \ --query "coffee beans roasting" invideo asset add --stock invideo gen models --query "b-roll shot from a prompt" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ -i prompt="close up of coffee beans tumbling in a roaster" invideo gen run --model seedance_2_5.r2v \ --max-credits --idempotency-key broll-roast \ -i prompt="close up of coffee beans tumbling in a roaster" invideo status --wait invideo edit show --json invideo edit change --timeline T1 \ --token --operations @ops.json invideo edit capture --at 0,60,300,900 --out ./frames invideo edit check invideo edit export --format video --quality 1080 \ --target-lufs -14 --json invideo status --wait invideo notebook show --out ./out invideo edit export --format video --mode image \ --still-at 312 --json invideo status --wait invideo notebook show --out ./out/still ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the `url` that `invideo asset upload` returns. `m1` is the recording's bin id from the same result, and works for reads like `audio.content`. A transcript refuses `--asset`. - `` comes from `invideo edit show ` for the branch command. `` is the `.branch_url` that `invideo branch new` returns. For `edit change`, `` is read again with `invideo edit show `. The main token is stale on the branch. - `` is each dry run's `.estimated_credits`. `` is a stock result's id from `invideo library search`. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is the `url` the paid `gen run` returns. - `@ops.json` reads a bare JSON list of ops, the `operations` list of the call below. - `` is `.sequences[0]` of each export result, one for the video and one for the still. `invideo status` waits but saves nothing. `invideo notebook show` saves the files, the video as `./out/export.mp4`, and the agent renames them. The key MCP call puts one b-roll shot over the talk, marks a chapter and ducks the music under `A1`, the default source on a new timeline. This is the full call. `` is the branch URL that `timeline_history` returns, and `` comes from `get_timeline` on it. `m4` is the b-roll's bin id, from the `add_media` result. At 30 fps, 4 minutes 10 seconds is frame 7500. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "place_media", "asset": "m4", "track": "V2", "at_f": 7500, "source_start_seconds": 2.0, "source_end_seconds": 8.0, "mode": "place_on_top", "linked_audio": false }, { "op": "add_marker", "at_f": 7440, "name": "Roasting", "color": "#ffd23f" }, { "op": "add_audio_effect", "target": "A2", "target_kind": "track", "effect": "ducker" } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the upload, every cut, your own b-roll, captions, markers, ducking, the export and the thumbnail still. - **Tool ops:** `audio.content`. The dry run shows its price before anything starts. - **Costs credits:** the transcript with `audio.transcript`, once per file, each paid stock clip and track you place, and any shot from `seedance_2_5.r2v` or track from `elevenlabs_music_v2_5_instrumental`. A long video takes the agent longer than a Short, from a few minutes for the cuts to under an hour with b-roll picked and checked. The export of a long video takes a while; the agent follows the card and does not export again. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a big file, cuts in the wrong order, or b-roll that covers a moment you wanted on camera. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the recording's sequence URL from `add_media` or `invideo asset upload`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | `add_media` with a link fails on a big file | Use `start_upload`, PUT the bytes, then `add_media` with the `upload_id`. | | The export takes a long time | Follow the card with `read` or `invideo status --wait`. For a very long video, export in parts with `start` and `end`, then join them with `media` `video.stitch`. | | B-roll covers a face you wanted | Move or shorten the b-roll clip with `move_clip` or `trim_clip`. | | The b-roll has its own sound | It was placed with `linked_audio` true. Mute it with `set_audio_muted`, or place it again with `linked_audio` false. | | Cuts land in the wrong place | They were made first to last. Restore the checkpoint and cut from last to first. | | Chapters are off after more cuts | Markers sit at frames. The agent reads them with `get_timeline` after the last cut and writes the list again. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: running `export` again to check on a slow one | Instead: `read` the export card, or `invideo status --wait`. Pass an `idempotency_key` so a retry finds the first. | | Avoid: editing main | Instead: work on a branch, and you accept it in the editor. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a first cut of my two hour stream VOD for YouTube. Cut every part where I am away or silent, keep the chat reactions, and mark a chapter at each game change. ``` ```text Edit my tutorial ./lesson.mp4: cut the mistakes and long pauses, zoom in on my screen when I click, captions on, no music. Give me a thumbnail still where I show the result. ``` ```text Add b-roll from my own folder ./broll to every part where I talk about the trip for more than 20 seconds. Use stock only where my clips do not fit. ``` #### When to use something else invideo does not upload to YouTube or set the chapters there. Paste the chapter list into the video's description in YouTube Studio. For a designed thumbnail with big text and a cut-out face, see the thumbnail page; the still from `export` is its starting frame. #### Related - [Cut ums, pauses and retakes, as reversible timeline edits](/how-to/creators/cut-ums-and-retakes) - [Make a thumbnail for the video](/how-to/creators/thumbnail) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Make a faceless YouTube video yourself, with AI help](/how-to/creators/faceless-youtube-video) - [Check your video before you say it is done](/how-to/check-your-video) ### Edit a podcast episode and pull clips from it Source: https://docs.invideo.io/how-to/creators/podcast-edit-and-clips.md Your podcast episode edited, with dead air and rough sound fixed, plus vertical clips with captions of the best moments, all on one timeline. You get a cleaned-up podcast episode and a set of short clips, also called podcast clips, highlights or audiograms. Long pauses, false starts and "um" moments come out of the episode. The best moments become vertical clips with captions for Reels, Shorts and TikTok. Use invideo for this when you want every cut to stay editable: your agent reads the transcript, makes the cuts on a timeline, and you can undo or move any cut after. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Edit my podcast episode in ./episode-42. There are two speakers. Cut the long pauses and the false starts, clean my mic, then find the five best moments and make each one a vertical clip with captions. Work on a branch and show me the moments before you export. ``` In a chat app, you drag the episode files into the project's Media panel in invideo, then name them in the chat. In a terminal, you name the folder and the agent uploads it. #### What you need One recording per camera or mic is fine. The agent lines them up on the timeline. - **The episode.** A video file (MP4 or MOV) or an audio file (WAV or MP3). Separate files per speaker also work. - **The speaker names.** So the agent can tell you who said what. - **What makes a good moment.** A strong opinion, a story, a laugh, a tip. Name the topics you want, or let the agent pick. - **The shape of the clips.** 9:16 for Reels, Shorts and TikTok, 1:1 for a feed. The full episode stays 16:9. - **Your caption style.** Font, color, and where the words sit. #### Steps Your agent edits on a branch and tells you what changed at each step. ##### Edit the episode The agent cleans up the full episode first. The agent makes a timeline with `new_timeline` and a branch with `timeline_history`. For a big local file, it calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id` and the timeline URL. Expected result: a sequence URL and a media bin id for each file. The agent runs `media` with `audio.transcript` on the episode's sequence URL from `add_media`, with `dry_run` first, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. Expected result: every word with its time and its speaker. The agent runs `media` with `audio.content`. It returns spans of speech, music, effects and silence, and turns each silent span into frames: seconds times the frame rate. Expected result: a list of silent spans. The agent removes each long pause with `edit_time_range` and mode `close_gap`, so every track moves together. For a false start, it reads the transcript, then cuts with `split_clip` and `delete_clip`. It sends all the cuts in one `edit_timeline` call. Expected result: a new `state_token` and a shorter episode. For a mic with hum or room echo, the agent runs `media` with `audio.clean` on that file's sequence URL, with `dry_run` first, then with `max_credits` and an `idempotency_key`. The `model` is `clean_voice.clean_audio`, or `clean_voice.clean_video` for a video file. This makes a new, cleaned file. The original stays. The agent places the clean file on its own track and mutes the old one with `set_audio_muted`, so you can compare. Expected result: a new sequence with the cleaned voice. ##### Pull the clips Then the agent cuts vertical clips from the edited episode. The agent reads the transcript and picks the moments that stand on their own: a clear start, one idea, a strong last line. It marks each one with `add_marker` and a note, and tells you the timecodes. Expected result: markers on the timeline. You approve or change the list. For each moment, the agent copies the timeline with `duplicate_timeline`. On the copy, it sets the shape to 9:16 with `set_timeline_settings`, keeps only the moment with `edit_time_range`, and fills the frame with `fill_frame`. It adds the words with `add_captions`, with slides and word times from the transcript. Expected result: one timeline per clip, each with its own `timeline_id`. The agent runs `capture` on each clip at the start, the middle and the end, and `check_timeline`. Expected result: the speaker's face in frame and the captions above the app buttons. The agent runs `export` with the `timeline_id` of the episode and of each clip. Expected result: one export card per timeline, each with status `completed`. The same job from a terminal: ```bash invideo project new --title "Episode 42" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Episode 42 edit" invideo asset upload ./episode-42/* invideo edit show --json invideo branch new --name episode-cut --token invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo media audio.content invideo media audio.clean --model clean_voice.clean_audio \ --dry-run invideo media audio.clean --model clean_voice.clean_audio \ --max-credits --idempotency-key ep42-clean invideo edit show --json invideo edit change --timeline T1 \ --token --operations @cuts.json invideo edit capture --timeline T2 \ --at 0,15,29 --out ./frames invideo edit check invideo edit export --format video --quality 1080 \ --timeline T2 --json invideo status --wait invideo notebook show --out ./clips/clip-1 ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the `url` that `invideo asset upload ` returns for each file, a `…/notebook/seq-N.M` URL. A transcript and a clean refuse a bin `--asset`. - `` is each dry run's `.estimated_credits`. - `` comes from `invideo edit show`: on `` for the branch, then on `` for the cuts. The main token is stale on the branch. `` is the `.branch_url` that `invideo branch new` returns. - `@cuts.json` reads a bare JSON list of ops, the `operations` list of the call below. - `T2` is the first clip's timeline id, which `invideo edit show ` lists after `duplicate_timeline`. Each clip has its own id. - `` is `.sequences[0]` of each export result. `invideo status` waits but saves nothing. `invideo notebook show` saves each clip in its own folder, like `./clips/clip-1/export.mp4`, and the agent renames it. The key MCP call, shown as the full call, cuts two pauses on every track and marks a moment. `` is the branch URL `timeline_history` returns, and `` comes from `get_timeline` on it. At 30 fps, 61.2 seconds is frame 1836. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "edit_time_range", "timeline": "T1", "start_f": 3690, "end_f": 3780, "mode": "close_gap" }, { "op": "edit_time_range", "timeline": "T1", "start_f": 1836, "end_f": 1911, "mode": "close_gap" }, { "op": "add_marker", "at_f": 5400, "duration_f": 900, "name": "Clip 1", "note": "The pricing story, ends on the laugh" } ] } ``` The agent sends the later cut first. Then the earlier cut does not move the frames of the later one. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** the transcript with `audio.transcript`, and the cleaned voice with `audio.clean`. - **Free:** uploads, the cuts, the markers, the captions, frame checks and every export. - **Tool ops:** `audio.content`. The dry run shows its price before anything starts. The transcript of a long episode takes a few minutes. The cuts and the clips take the agent a few minutes more. Picking the moments with you takes the longest. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from cuts that land mid-word, or a clip that starts without context. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `audio.transcript` or `audio.clean` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the file's sequence URL from `add_media` or `invideo asset upload`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | A cut clips the first or last word | Move the cut a few frames out with `trim_clip`, then listen again. | | The transcript call returns status running | Call `audio.transcript` again with the same file after `retry_after_s`. Only the first call costs credits. | | Two speakers have the same label | Tell the agent who speaks first. It renames the speakers in its notes. | | `edit_timeline` refused with an old token | Someone edited first. Read with `get_timeline`, then rebuild the ops. | | CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild. | | CLI exit 5 | A limit on credits or quota. Check the balance before the transcript. | | The face is cut off in the vertical clip | Move the picture with `set_position`, then `capture` again. | | Avoid: deleting the original noisy track | Instead: mute it with `set_audio_muted`. The clean file is a new file, and the original stays. | | Avoid: editing main | Instead: work on a branch from `timeline_history`, and you accept the change. | #### Prompts to try Each prompt is a real variation of the job. ```text Cut every pause longer than a breath from this interview, keep the laughs, and give me a clean episode plus an audio-only export. ``` ```text Find three moments where my guest tells a story. Make each a 9:16 clip with word-by-word captions and the guest's name at the top. ``` ```text My mic has a hum. Clean only my track, keep the guest's track as it is, and let me hear both before you mute the old one. ``` #### When to use something else invideo does not publish to podcast hosts like Spotify for Podcasters or Apple Podcasts. Export the audio with `export` mode `audio`, then upload it to your host. For a live show with many cameras switched on the fly, record in a tool built for live switching, like OBS Studio or Riverside. Then bring the recordings in for the edit. #### Related - [Cut ums, pauses and retakes, as reversible timeline edits](/how-to/creators/cut-ums-and-retakes) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Make Reels and Shorts from your footage: hook, captions, transitions, sound effects](/how-to/creators/reels-and-shorts-from-your-footage) - [Repurpose one video for every platform](/how-to/creators/repurpose-for-every-platform) - [Check your video before you say it is done](/how-to/check-your-video) ### Make a faceless YouTube video yourself Source: https://docs.invideo.io/how-to/creators/faceless-youtube-video.md A faceless YouTube video from your own script: an AI voiceover, b-roll, captions and music under the voice, on a timeline you review. You get a faceless YouTube video, also called a no-face or voiceover video, from a script you wrote. An AI voice reads your script, stock or generated b-roll plays under it, captions follow the words, and music sits under the voice. You review every cut on the timeline before it goes out. Use invideo for this when you want to stay the editor: your agent builds the first cut from your script, and you change any line, shot or caption after on the timeline. This page makes the video. It does not promise views, subscribers or money from a channel. Those depend on your ideas, your script and your audience. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a faceless YouTube video from my script in ./script.md. Use a calm male narrator voice, stock b-roll for each paragraph, word-by-word captions, and soft music that ducks under the voice. 16:9. Work on a branch and show me frames before you export. ``` In a chat app, you paste the script into the chat. In a terminal, you name the file and the agent reads it. #### What you need Write the script yourself, or edit a draft until it sounds like you. - **The script.** Plain text, one paragraph per scene. - **The voice.** A mood ("calm", "warm", "energetic"), or a voice you pick from the previews. Your own voice also works: give the agent a short clean clip of you, and it clones it with `seed_audio_1_0.ta2a`, with the clip as `reference_audio_1` and your lines tagged `@Audio1` in the prompt. - **The b-roll.** Your own clips, stock footage, or shots to generate from a prompt. - **The music.** A mood, a track from stock music, or your own file if you have the rights. - **The shape.** 16:9 for YouTube. Add a 9:16 version for Shorts later. #### Steps Your agent edits on a branch and tells you what changed at each step. The agent runs `find_models` with "narration voice" and reads its pick with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. Your agent can search for others with `find_models`. It searches `elevenlabs_text_to_speech_voices` with `search_library`, for example "calm male narrator", and you pick a voice from the previews. It calls `generate` with `dry_run: true`, your script as `prompt` and the voice as `voice_id`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, one file per section for a long script. Expected result: a sequence URL for each voice file, which the agent reads with `read`. The agent prices `audio.transcript` with `dry_run` on each voice file's sequence URL, starts it with `max_credits`, and calls again after `retry_after_s` for the words. Expected result: every word with its start and end time, for the captions and the b-roll cuts. For each paragraph, the agent searches `stock_video` with `search_library` and looks at the results with `media` and `video.frames`. For a shot stock does not have, it runs `find_models` with the shot in words and reads its pick with `get_model`. A good pick is `seedance_2_5.r2v`, where a `prompt` alone is enough. It calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: one or more sequence URLs for each paragraph, which the agent reads with `read`. The agent makes a 16:9 timeline with `new_timeline` and a branch with `timeline_history`. It places the voice files in order with `insert_media`, then the b-roll with `place_media`, each cut on the first word of its paragraph. Expected result: a first cut where the pictures change with the script. The agent adds the words with `add_captions`, with slides and the word times from the transcript. It styles them with `set_text_style`: font, size and color. The words of each line build up as they are spoken. Expected result: a caption clip that follows the voice word by word. The agent adds a track from `stock_music` with `add_media` and `stock`, after you pick it from the previews. It adds the `ducker` effect to the music track with `add_audio_effect`. A new timeline ducks under `A1` by default, so the agent sets `set_sidechain_source` only when the voice is on another track. Expected result: the music drops when the voice speaks and comes back in the gaps. The agent runs `capture` at each paragraph, `check_timeline`, and `audio.loudness` on the voice. Then it gives you the timeline URL. You watch it, change what you want, and ask for the export. The agent runs `export` with `target_lufs` for YouTube. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Faceless: ocean facts" invideo agent register --name export INVIDEO_AS= invideo library search \ --library elevenlabs_text_to_speech_voices --query "calm narrator" invideo gen models --query "narration voice" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@part1.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key part1 \ -i prompt=@part1.txt -i voice_id= invideo status --wait invideo notebook show invideo media audio.transcript --dry-run invideo media audio.transcript \ --max-credits invideo library search --library stock_video \ --query "deep ocean whale" invideo edit new --name "Ocean facts v1" invideo edit show --json invideo branch new --name first-cut --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @ops.json invideo edit capture --at 0,12,40,75 --out ./frames invideo edit check invideo edit export --format video --quality 1080 \ --target-lufs -14 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` comes from the `elevenlabs_text_to_speech_voices` search. It works only with `elevenlabs_text_to_speech.elevenlabs_tts_v4`. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is each dry run's `.estimated_credits`. - `` is the `url` the paid `gen run` returns. `` is the voice file that `notebook show` on it lists. - `` comes from `invideo edit show ` for the branch command. `` is the `.branch_url` that `invideo branch new` returns. For `edit change`, `` is read again with `invideo edit show `. - `@ops.json` reads a bare JSON list of ops, the `operations` list of the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The key MCP call puts the music under the voice. The voice is on `A1`, the default duck source on a new timeline, so no `set_sidechain_source` is needed. This is the full call. `` is the branch URL that `timeline_history` returns, and `` comes from `get_timeline` on it. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "add_audio_effect", "target": "A2", "target_kind": "track", "effect": "ducker" }, { "op": "set_audio_gain", "target": "A2", "gain_db": -12 } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** the voice with `elevenlabs_text_to_speech.elevenlabs_tts_v4`, the transcript of the voice, paid stock clips and music, and any b-roll from `seedance_2_5.r2v`. - **Tool ops:** `video.frames`, `audio.loudness`. The dry run shows its price before anything starts. - **Free:** searching stock, the edits, the captions, the ducking and the export. The first cut takes the agent a few minutes. Your review takes longer, and it is the part that makes the video yours. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from b-roll that does not match the words, or a voice that reads a name wrong. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The voice says a name wrong | Spell it the way it sounds in the script, then make that section again. | | The b-roll does not match a line | Name the shot you want. The agent swaps it with `place_media` mode `replace`. | | The music is too loud under the voice | Lower it with `set_audio_gain` on the music track. | | The music does not duck | The voice is not on `A1`. Point `set_sidechain_source` at the voice track, not the music track. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | `generate` refused for `max_credits` | The price is above the cap. Run the dry run again and agree a new cap. | | CLI exit 5 | A limit on credits or quota. Check the balance. | | Avoid: calling `generate` again to check on the voice | Instead: `read` the sequence URL, or call `status`. | | Avoid: exporting before you watch it | Instead: you review the timeline first. The agent exports when you say so. | #### Prompts to try Each prompt is a real variation of the job. ```text Turn my history script into a faceless video with a deep, slow voice, old map and archive stock footage, and captions at the bottom. ``` ```text Use my cloned voice for this script. Generate b-roll for the two scenes stock cannot show, and use stock for the rest. Show me each shot first. ``` ```text Make a 9:16 Shorts version of the first minute of my faceless video, with big captions in the middle and the same music. ``` #### When to use something else invideo does not upload to YouTube or pick titles and tags. Export the MP4 and upload it in YouTube Studio. YouTube asks you to label realistic AI-made content when you upload. Read its rules in YouTube Studio before you publish. For a thumbnail, see the thumbnail page below. For a voice actor's own recording, record it in a tool like Audacity, then bring the file in with `add_media`. #### Related - [Make a thumbnail for the video](/how-to/creators/thumbnail) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Edit a long YouTube video](/how-to/creators/edit-a-long-youtube-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Make sleep Source: https://docs.invideo.io/how-to/creators/sleep-and-meditation-videos-in-bulk.md Long sleep, rain and meditation videos made in bulk: a looped scene, a calm sound bed, one timeline per variant, exported in parts. You get long sleep videos, rain sounds, ambient and meditation videos, also called relaxing or study-with-me videos, for a faceless channel. Each one is a calm scene that loops without a jump, with rain, waves or soft music under it. You make one, then your agent makes the variants: rain on a window, ocean at night, a forest at dawn. Use invideo for this when you want many long videos from one setup: the agent loops the scene, joins the sound bed, copies the timeline for each variant, and exports each one in parts. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make three long sleep videos for my channel: rain on a window, ocean waves at night, and a quiet forest. Loop a calm stock clip for each, put matching ambient sound under it, fade in and out, and make one timeline per video. Show me the loop seam before you export. ``` In a chat app, you name the scenes and the length in the chat. In a terminal, you can also give the agent a folder of your own clips. #### What you need Pick a few calm scenes first. The agent repeats the setup for each one. - **The scenes.** Your own clips, stock footage, or a shot to generate. Slow, steady motion loops best: rain, waves, fire, clouds. - **The sound.** Rain, waves, wind, soft piano, or a drone. From stock music, generated, or your own file if you have the rights. - **The length.** How long each video runs, in hours or minutes. - **The title text.** Optional. A short line like "Rain for sleep" for the first seconds. - **The shape.** 16:9 for YouTube. #### Steps Your agent edits on a branch and tells you what changed at each step. The agent searches `stock_video` with `search_library`, for example "rain on window night". It looks at the first and last moments of each result with `media` and `video.frames`, to find a clip whose ends look alike. For a scene stock does not have, it runs `find_models` with the scene in words. A good pick is `seedance_2_5.frames`. Your agent can search for others with `find_models`. The agent reads the pick with `get_model`, and passes one still as both `first_frame` and `last_frame`, with `generate_audio` false, so the clip loops cleanly. It calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, and reads the result with `read`. Expected result: a sequence URL per scene, in the project. The agent runs `media` with `video.loop` on the clip's sequence URL and sets `target_duration` to the length you asked for, in seconds. The dry run shows its price before anything starts. Then the agent runs it with `max_credits` and an `idempotency_key`. Expected result: a new, long sequence beside the clip. The agent searches `stock_music` with `search_library`, for example "rain ambience". You pick from the previews. For rain, waves or wind that stock does not have, it runs `find_models` with the sound in words. A good pick is `elevenlabs_sfx`, read with `get_model`, with `loop` true and the longest `duration` it allows. For a soft piano or a drone, a good pick is `elevenlabs_music_v2_5_instrumental`. A music model is a poor fit for rain. Each gets `generate` with `dry_run: true` first, with the price told to you. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, and reads the sequence URL with `read`. Then it joins copies into one long file with `media` and `audio.concat`, the sequence URLs in `audio_array`. Expected result: one sound file as long as the video. The agent makes a 16:9 timeline with `new_timeline` and a branch with `timeline_history`. It places the long loop with `insert_media` and the sound bed on an audio track. It fades the picture in and out with `add_edge_transition` and type `fade`, and the sound with `set_audio_fades`. Expected result: one full video on the timeline. For each other scene, the agent copies the timeline with `duplicate_timeline`. On the copy, it swaps the picture and the sound with `place_media` mode `replace`, and changes the title with `set_text`. Expected result: one timeline per video, each with its own `timeline_id`. The agent runs `capture` a moment before and a moment after each loop seam, and `check_timeline`. It runs `audio.content` on the sound bed to find any silent gap at a join, and `audio.loudness` to keep it soft and even. Expected result: no jump at the seam and no gap in the sound. For a very long video, the agent exports it in parts with `export`, each with its own `start` and `end` in seconds. Then it joins the parts with `media` and `video.stitch`, the parts' sequence URLs in `video_array`. Expected result: one long MP4. The same job from a terminal: ```bash invideo project new --title "Sleep channel, batch 1" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Rain for sleep" invideo library search --library stock_video \ --query "rain on window night" invideo asset add --stock invideo media video.frames --at 0,9.5 --out ./seam invideo media video.loop --target-duration \ --dry-run invideo media video.loop --target-duration \ --max-credits --idempotency-key rain-loop-1 invideo gen models --query "steady rain sound bed" invideo gen model --model elevenlabs_sfx invideo gen run --model elevenlabs_sfx --dry-run \ -i prompt="steady soft rain on a window" -i duration=30 -i loop=true invideo gen run --model elevenlabs_sfx --max-credits \ --idempotency-key rain-1 -i prompt="steady soft rain on a window" \ -i duration=30 -i loop=true invideo media audio.concat \ --audio-array ,, invideo edit show --json invideo branch new --name rain-v1 --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @ops.json invideo edit capture --at , --out ./frames invideo edit check invideo edit export --format video --quality 1080 \ --start 0 --end --json invideo status --wait invideo media video.stitch --video-array , invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is a stock result's id from `invideo library search`. `` is the `url` that `invideo asset add` returns for it, a `…/notebook/seq-N.M` URL. `video.loop` refuses a bin `--asset`. - `` is the length you asked for, in seconds. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is each dry run's `.estimated_credits`. - `` is the sound's sequence URL, from `invideo notebook show` on the thread URL the paid `gen run` returns. - `` comes from `invideo edit show`: on `` for the branch, then on `` for the change. `` is the `.branch_url` that `invideo branch new` returns. - `@ops.json` reads a bare JSON list of ops, like `insert_media` for the loop on `V1` and the sound bed on `A2`. - `` and `` are times, in seconds, a moment before and after a loop seam. - `` is where the part ends, in seconds. The next part starts there. - `` and `` are `.sequences[0]` of each part's export result, the export cards. The agent waits on each with `invideo status`. - `` is the sequence URL `video.stitch` returns. `invideo status` waits but saves nothing. `invideo notebook show` saves the joined video in `./out`, and the agent renames it. The key MCP call loops the scene. The agent sends it first with `dry_run: true`, then with `max_credits` set to the price. `` is the scene's sequence URL, from `add_media` or the `generate` result. `` is the length you asked for, as a number. ```json { "url": "", "op": "video.loop", "target_duration": "", "idempotency_key": "rain-window-loop-1" } ``` The parts join the same way, with `op` set to `video.stitch` and the parts in `video_array`, in order. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** paid stock clips and music, and any generated scene or sound. - **Tool ops:** `video.frames`, `video.loop`, `video.reverse`, `video.stitch`, `audio.concat`, `audio.content`, `audio.loudness`. The dry run shows its price before anything starts. - **Free:** the edits, the checks and every export. A long export takes a while to render. Exporting in parts keeps each job shorter, and the agent can run a failed part again by itself. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a loop that jumps, or a sound bed with a click at the join. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out ` on the card or the stitched sequence. | | `video.loop` or `video.stitch` refused with `code: "not_found"` | The call named a media bin asset. Pass the file's sequence URL, from `add_media`, `generate` or the export card. | | The picture jumps at each loop | Pick a clip whose ends look alike, or loop a forward-then-backward clip made with `video.reverse` and `video.stitch`. | | A click or a gap at a sound join | Set `gap_duration` to 0 on `audio.concat`, or crossfade the copies on the timeline with `apply_audio_crossfade`. | | The sound is too loud for sleep | Lower it with `set_audio_gain`, then check with `audio.loudness`. | | A long export fails | Export it in shorter parts with `start` and `end`, then join them with `video.stitch`. | | `video.stitch` does not join the parts | It joins videos of the same aspect ratio. Export every part from the same timeline. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: calling `export` again to check on it | Instead: `read` the export card, or run `invideo status` with `--wait`. | | Avoid: one huge export for every variant at once | Instead: run it in parts, a few timelines at a time. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a long fireplace video with crackling fire sound, no music, no title, and a slow fade in. Then make a version with soft piano. ``` ```text Generate a slow drifting nebula scene, loop it for a long meditation video, and put a deep, calm drone under it. ``` ```text Make one timeline per row of ./scenes.csv, each with its scene, its sound and its title. Export them in parts, a few at a time. ``` #### When to use something else invideo does not upload or schedule videos on YouTube. Export the MP4 and upload it in YouTube Studio. Ambient videos that repeat the same clip can count as repetitive content under YouTube's rules. Read those rules in YouTube Studio before you build a channel on them. For a live stream of a loop that never stops, use a streaming tool like OBS Studio with the exported file. #### Related - [Make a quote video, nature loop or welcome video](/how-to/creators/quote-and-nature-loop-videos) - [Make a faceless YouTube video yourself, with AI help](/how-to/creators/faceless-youtube-video) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Turn a CSV into many videos with a script](/how-to/developers/csv-to-videos) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Make a Spotify Canvas and a music visualizer Source: https://docs.invideo.io/how-to/creators/spotify-canvas-and-visualizer.md A Spotify Canvas loop for your track, and a music visualizer video where shapes and effects pulse on the beat of your song. You get two things for a song. A Spotify Canvas is a short vertical loop that plays behind your track in the Spotify app. A music visualizer, also called an audio visualizer or audio-reactive video, is a full-length video where shapes and effects pulse on the beat, ready for YouTube. Use invideo for this when you want the motion to follow your song without timing it by hand: your agent reads the beats and the levels of the track, and turns them into keyframes you can still change on the timeline. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Here is my song, ./night-drive.wav, and the cover art, ./cover.png. Make a Spotify Canvas: a short vertical loop from the cover, slow neon motion, no text. Then make a 16:9 visualizer for YouTube where a glowing circle pulses on every beat. Show me both before you export. ``` In a chat app, you drag the song and the cover into the project's Media panel in invideo. In a terminal, you name the files and the agent uploads them. #### What you need Use files you own or have the rights to. - **The song.** WAV or MP3, the final master. - **The art.** Your cover art, a photo, or a clip. The agent can also generate the scene. - **The look.** Colors, mood and motion: "slow neon", "grainy film", "bright and fast". - **The Canvas spec.** Spotify wants a vertical 9:16 video that is a few seconds long and loops. Read the exact spec in Spotify's Canvas guidelines. - **The visualizer shape.** 16:9 for YouTube, or 1:1 or 9:16 for a social post. #### Steps The first three steps make the Canvas. The rest make the visualizer. Your agent edits on a branch and tells you what changed at each step. ##### Make the Canvas The Canvas is a short looping video for the Spotify track page. The agent brings in the cover with `add_media`. With a first frame, `seedance_2_5.frames` takes the shape of that image and ignores `aspect_ratio`. So the agent first makes a 9:16 copy of the cover with `media` `image.resizeAspectRatio` on the cover's sequence URL from `add_media`, and looks at it with `video.frames` to see whether the op cropped or padded the art before it spends anything. It runs `find_models` with "looping video from an image". A good pick is `seedance_2_5.frames`. Your agent can search for others with `find_models`. The agent reads the pick with `get_model`. It calls `generate` with `dry_run: true`, the 9:16 cover as both `first_frame` and `last_frame`, so the clip starts and ends on the same picture, and `generate_audio` false, because the Canvas plays over your song. It tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, and reads the result with `read`, never with a second `generate`. Expected result: a sequence URL for a short vertical clip that loops. The agent makes a 9:16 timeline with `new_timeline` and places the clip with `insert_media`. If the clip is short, it repeats it with `media` and `video.loop` on the clip's sequence URL, with `target_duration`, after a dry run. It runs `capture` on the last frame and the first frame to check the seam. Expected result: a vertical loop with no jump at the seam. The agent runs `export` with `format` video and `quality` 1080. Expected result: an MP4 you upload in Spotify for Artists. ##### Make the visualizer The visualizer is a full-length video that pulses with the song. The agent runs `media` with `audio.beats` on the song for the strong and weak beats, and `audio.waveform` for the level over time. For the drops and phrases, it reads `audio.markers`. Expected result: lists of beat times and level peaks, in seconds. The agent makes a 16:9 timeline and a branch with `timeline_history`. It places the song on an audio track, and the art or a generated background on `V1`. It adds a circle with `add_shape` and preset `ellipse` on `V2`. Expected result: the song, the background and the shape on the timeline. The agent adds keyframe lanes for `zoom_x` and `zoom_y` on the shape with `add_keyframe_lane`. Then it adds a point on each beat with `add_keyframes`: bigger on the beat, back to normal a moment after. It can size each pulse by the `audio.waveform` peak at that time. Expected result: the circle grows on every beat and shrinks between them. The agent adds effects from the catalog with `add_effect`, for example `beat_rock` for color bursts, `aurora` for moving light, or `kaleidoscope` on the background. In a later call, with the effect ids from `get_timeline`, it sets `beat_rock`'s `interval` or `kaleidoscope`'s `speed` with `set_effect_parameter` to match the tempo from `audio.markers`. Expected result: the effects move with the song. The agent runs `capture` on a few beats and between them, and `check_timeline`. Expected result: the pulse lands on the beat, not after it. The agent runs `export` with `format` video and reads the export card. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Night Drive visuals" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Visualizer" --width 1920 --height 1080 invideo asset upload ./night-drive.wav ./cover.png invideo media image.resizeAspectRatio --aspect-ratio 9:16 \ --dry-run invideo media image.resizeAspectRatio --aspect-ratio 9:16 \ --max-credits --idempotency-key cover-9x16 invideo gen models --query "looping video from an image" invideo gen model --model seedance_2_5.frames invideo gen run --model seedance_2_5.frames --dry-run \ -i prompt="slow neon light drifting over the cover, seamless loop" \ -i first_frame= -i last_frame= \ -i generate_audio=false invideo gen run --model seedance_2_5.frames \ --max-credits --idempotency-key canvas-1 \ -i prompt="slow neon light drifting over the cover, seamless loop" \ -i first_frame= -i last_frame= \ -i generate_audio=false invideo media audio.beats --asset m1 invideo media audio.waveform --asset m1 invideo edit show --json invideo branch new --name visualizer --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @ops.json invideo edit capture --at 1.5,1.62,3.0 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the cover's `url` that `invideo asset upload` returns, a `…/notebook/seq-N.M` URL. `image.resizeAspectRatio` refuses a bin `--asset`. `m1` is the song's bin id from the same upload. Reads like `audio.beats` take `--asset m1`. - `` is the sequence URL that `image.resizeAspectRatio` returns. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is each dry run's `.estimated_credits`. - `` comes from `invideo edit show`: on `` for the branch, then on ``, read again before each change. `` is the `.branch_url` that `invideo branch new` returns. - `@ops.json` reads a bare JSON list of ops, like the `operations` list of the first call below. Each later call is its own `edit change`. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The key MCP calls make the pulse. The first, shown as the full call, adds the shape. `` is the branch URL `timeline_history` returns, and `` comes from `get_timeline` on it. At 30 fps, a song of 180 seconds is 5400 frames. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "add_shape", "track": "V2", "at_f": 0, "duration_f": 5400, "preset": "ellipse", "width": 400, "height": 400, "x": 0, "y": 0, "fill": "#7cf6ff" } ] } ``` The lanes come next, shown as the bare op list that `--operations @ops.json` takes. They can also go later in the first call, since a clip id made earlier in a call can be used later in it. `` is the shape clip's id, read with `get_timeline` after the first call. ```json [ { "op": "add_keyframe_lane", "parent": "", "parent_kind": "video_clip", "property": "zoom_x", "default_value": 1 }, { "op": "add_keyframe_lane", "parent": "", "parent_kind": "video_clip", "property": "zoom_y", "default_value": 1 } ] ``` The points need the lane ids, so they go in their own call, shown as a bare op list. `` is the `zoom_x` lane's id, read with `get_timeline` after the lanes land. `time_seconds` counts from the clip's start, and the shape starts at 0, so the beat times go in as they are. ```json [ { "op": "add_keyframes", "lane": "", "points": [ { "time_seconds": 1.5, "value": 1.3 }, { "time_seconds": 1.62, "value": 1 }, { "time_seconds": 2.0, "value": 1.3 }, { "time_seconds": 2.12, "value": 1 } ] } ] ``` The agent sends the same points to the `zoom_y` lane, so the circle keeps its shape. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** the generated Canvas loop or background, and any paid stock clip. - **Tool ops:** `image.resizeAspectRatio`, `video.frames`, `video.loop`, `audio.beats`, `audio.waveform`, `audio.markers`. The dry run shows its price before anything starts. - **Free:** the shapes, keyframes, effects and every export. The Canvas takes a few minutes, most of it the generation. The visualizer takes the agent a few minutes more. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a loop that jumps, or a pulse that lands late. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | `image.resizeAspectRatio` or `video.loop` refused with `code: "not_found"` | The call named a media bin asset. Pass the file's sequence URL from `add_media` or `invideo asset upload`. | | The Canvas jumps at the loop | Generate again with the same image as `first_frame` and `last_frame`, or crossfade a copy with `duplicate_clip` and `add_transition`. | | The pulse feels late | Move each point a frame or two earlier, so the peak lands on the beat. | | Too many pulses | Use only the strong beats from `audio.beats`, or every second beat. | | `audio.beats` finds few beats | The track has a soft beat. Use `audio.onsets` for hits, or `audio.markers` for tempo. | | An effect hides the art | Lower its strength with `set_effect_parameter`, or put it on the background only. | | CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild. | | Avoid: one `set_keyframes` call for the zoom | Instead: `set_keyframes` takes opacity and rotation only. Use `add_keyframe_lane` and `add_keyframes` for zoom. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a Spotify Canvas from my live clip ./stage.mp4: the best few seconds, slowed down, vertical, looping with no jump. ``` ```text Make a visualizer for my lo-fi track: rain on a window as the background, a soft white bar that grows with the level, and a gentle aurora effect. ``` ```text Make a 1:1 audio visualizer for Instagram with my cover in the middle, spinning slowly with set_keyframes on rotation, and flashing on the drop. ``` #### When to use something else invideo does not upload to Spotify. Upload the Canvas in Spotify for Artists. invideo has no live audio-reactive effect that listens to the sound by itself. The agent reads the beats and writes the keyframes, so a new mix needs a new read. For a lyric video, see the lyric video page below. #### Related - [Make a lyric video or text animation for your song](/how-to/creators/lyric-video) - [Make a quote video, nature loop or welcome video](/how-to/creators/quote-and-nature-loop-videos) - [Repurpose one video for every platform](/how-to/creators/repurpose-for-every-platform) - [Timeline edit operations](/reference/edit-operations) - [Check your video before you say it is done](/how-to/check-your-video) ### Make a book trailer or a game trailer Source: https://docs.invideo.io/how-to/creators/book-or-game-trailer.md A book trailer from generated scenes, text and music, or a game trailer cut from your gameplay's best moments, with title cards. You get a trailer, also called a teaser or promo video, for a book or a game. A book trailer shows scenes from your story as generated shots, with short lines of text, music and a voice. A game trailer cuts your captured gameplay down to its best moments, with title cards and a hit on every cut. Use invideo for this when you want a trailer you can keep changing: every shot, line and cut sits on a timeline, so a new tagline or a new build means a small edit, not a new video. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it the prompt for your kind of trailer. ```text Make a book trailer for my fantasy novel. Read ./blurb.md, pick four scenes, generate a shot for each, and put three short lines of text between them. Dark orchestral music, a deep voice for the last line, and the cover at the end. 16:9. Show me each shot before you use it. ``` ```text Make a game trailer from my gameplay in ./captures. Find the best fights and the big moments, cut them on the music, and add title cards with the game's name and "Wishlist on Steam". 16:9. ``` In a chat app, you drag the files into the project's Media panel in invideo. In a terminal, you name the folder and the agent uploads it. #### What you need The book trailer and the game trailer need different inputs. - **For a book.** The blurb, three to five scenes in a sentence each, the cover image, and the look (dark, cozy, cinematic). - **For a game.** Your gameplay recordings, the game's logo, and the store you send people to. - **The text.** Short lines for the cards: a hook, a tagline, the title, the call to action. - **The music.** A mood, a track from stock music, or your own file if you have the rights. - **The shape.** 16:9 for YouTube and store pages, 9:16 for a Shorts version. #### Steps Step 1 and step 2 are for a book. Step 3 is for a game. The rest are for both. Your agent edits on a branch and tells you what changed at each step. The agent reads your blurb and writes one prompt per scene: the place, the light, the motion of the camera. It saves the list as a brief with `new_brief`, then adds the scenes with `write`, so you can change them. Expected result: a brief URL with one note per scene. The agent runs `find_models` with `output` video and the job in words, like "cinematic scene from a prompt", and reads its pick with `get_model`. A good pick is `seedance_2_5.r2v`. Your agent can search for others with `find_models`. It takes a `prompt` and, to keep a character the same in every shot, the cover or a character image in `reference_images`. For a shot that must start on the cover, `seedance_2_5.frames` takes it as `first_frame`. For each scene, the agent calls `generate` with `dry_run: true`, the scene prompt, `aspect_ratio` 16:9 and a `duration`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key` per scene, and names each take with `rename`. Expected result: a sequence URL per take, which the agent reads with `read`. You pick the takes to use. For each big recording, the agent calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id`. The agent runs `media` with `audio.onsets` and `audio.content` on each recording to find the loud spans: shots, explosions, a crowd. It runs `video.sceneSplit` to find the cuts, and looks at each span with `video.frames`. Expected result: a list of moments, in seconds. The agent makes a 16:9 timeline with `new_timeline` and a branch with `timeline_history`. It adds the music, reads its beats with `audio.beats`, and places each shot or moment with `place_media` so the cuts land on beats. It adds a hit with `add_transition` and type `impact` or `flash` at the big cuts. Expected result: a cut that moves with the music. The agent adds each line with `add_text` and fades it in and out with `set_keyframes` on `opacity`. At the end, it places the cover or the logo and the call to action. Expected result: readable cards between the shots. The agent runs `find_models` with "voice line" and with "sound effect", and reads each pick with `get_model`. Good picks are `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a `voice_id` from `search_library`, and `elevenlabs_sfx`, with a `prompt` and a `duration` within the range `get_model` gives. Your agent can search for others with `find_models`. Each one gets a `generate` with `dry_run: true`, and the agent tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It reads each sequence URL with `read` and places the sound. It puts `ducker` on the music track with `add_audio_effect`; a new timeline ducks under `A1` by default. Expected result: a sequence URL for each sound, and the voice clear over the music. The agent runs `capture` at each card and a few shots, `check_timeline`, and `audio.loudness` on the music and voice. Then it runs `export` with `format` video. Expected result: an export card with status `completed`. The same job from a terminal, for a game trailer: ```bash invideo project new --title "Starfall trailer" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Trailer v1" invideo asset upload ./captures/*.mp4 invideo media audio.onsets invideo media audio.content invideo media video.sceneSplit --dry-run invideo media video.frames --at 42,43.5,45 --out ./look invideo edit show --json invideo branch new --name trailer-v1 --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @ops.json invideo edit capture --at 0,8,20,58 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the `url` that `invideo asset upload ` returns for each recording, a `…/notebook/seq-N.M` URL. - `` comes from `invideo edit show ` for the branch command. `` is the `.branch_url` that `invideo branch new` returns. For `edit change`, `` is read again with `invideo edit show `. - `@ops.json` reads a bare JSON list of ops, the `operations` list of the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. For a book trailer, the shots are generated. Find and read the model, price one scene, then run it with the price as the cap: ```bash invideo gen models --query "cinematic scene from a prompt" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ -i prompt="slow push through a foggy harbor at dawn" \ -i aspect_ratio=16:9 -i duration=6 invideo gen run --model seedance_2_5.r2v \ --max-credits --idempotency-key scene-1 \ -i prompt="slow push through a foggy harbor at dawn" \ -i aspect_ratio=16:9 -i duration=6 invideo status --wait ``` `` is a notebook page of the project, listed by `invideo notebook show `. `` is the dry run's `.estimated_credits`. `` is the `url` the paid run returns. The key MCP call, in full, places a moment on a beat, adds a hit, and adds a title card. `` is the branch URL that `timeline_history` returns, and `` comes from `get_timeline` on it. `` is the sequence URL that `add_media` returns for the recording. `c3` and `c4` are the clip ids on each side of the cut, from `get_timeline`. The fight starts 42 seconds into the recording. It goes on the timeline at frame 96, a beat at 3.2 seconds at 30 fps. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "place_media", "asset": "", "track": "V1", "at_f": 96, "source_start_seconds": 42, "source_end_seconds": 45.5, "mode": "overwrite", "linked_audio": true }, { "op": "add_transition", "left_clip": "c3", "right_clip": "c4", "type": "impact", "in_f": 4, "out_f": 4 }, { "op": "add_text", "track": "V2", "start_f": 300, "end_f": 360, "text": "Wishlist on Steam", "style": { "font_size": 88, "align": "center", "shadow": true } } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** the shots from `seedance_2_5.r2v` for a book, the voice from `elevenlabs_text_to_speech.elevenlabs_tts_v4`, sounds from `elevenlabs_sfx`, and paid stock music. - **Tool ops:** `audio.onsets`, `audio.content`, `audio.beats`, `audio.loudness`, `video.sceneSplit`, `video.frames`. The dry run shows its price before anything starts. - **Free:** uploads, the cuts, the text and the export. A game trailer from your own footage takes the agent a few minutes. A book trailer takes longer, because each shot is generated and you pick the takes. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from shots that do not match each other, or gameplay with no sound to read. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | The hero looks different in each shot | Generate with a reference image and `seedance_2_5.r2v`, and keep the same words for the character in every prompt. | | A shot has text or a logo in it | Generate it again with "no text" in the prompt, or cover it with a card. | | The recording has no sound | `audio.onsets` finds nothing. The agent picks moments from `video.frames` and `video.sceneSplit`, and you check them. | | An upload by link fails | Upload the file with `start_upload` instead of a link. | | `generate` returns status `held` | A safety review. It is not over. `read` the URL again later. | | CLI exit 5 | A limit on credits or quota. Check the balance before more shots. | | Avoid: calling `generate` again to check on a shot | Instead: `read` the thread URL, or call `status`. | | Avoid: using every take | Instead: you pick the takes. The agent marks them with `mark_sequence` only when you agree. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 9:16 book trailer for TikTok from my thriller. Three fast shots, one line of text each, a heartbeat sound, and the cover at the end. ``` ```text Cut a short teaser from my game's boss fight in ./boss.mp4. Slow motion on the last hit, a glitch on the cuts, and the logo at the end. ``` ```text My recordings have no sound. Find the action by looking at the frames, cut them to this track, ./theme.mp3, and show me the moments first. ``` #### When to use something else invideo does not record gameplay. Capture it with OBS Studio, the Xbox Game Bar, or your console's capture. Store pages like Steam have their own trailer rules. Read them before you export. For a book cover itself, work with a designer, or ask your agent to generate one with a model it finds with `find_models`. The trailer uses the cover you bring. #### Related - [Make a gaming montage from your clips](/how-to/creators/gaming-montage) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Make an intro, welcome video, outro or logo animation for your channel or business](/how-to/creators/intro-outro-logo-animation) - [Make a thumbnail for the video](/how-to/creators/thumbnail) - [Models](/reference/models) ### Build an assembly cut from a script by matching lines to takes Source: https://docs.invideo.io/how-to/creators/assembly-cut-from-a-script.md An assembly cut, or string-out, of your takes in script order: your agent matches each script line to its take and lays them out on a branch. You get an assembly cut, also called a rough cut, string-out or selects reel, from your script and your takes. Your agent finds where each line of the script was said in your footage, picks the take to use, and lays the takes out in script order. You then watch it and choose the takes you like better. Use invideo for this when you have many takes and no time to log them: your agent reads every take's transcript, matches it to the script, and puts the result on a branch you can change clip by clip. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make an assembly cut of my short film. The script is ./script.pdf and the takes are in ./footage. Match each line to its takes, use the last full take of each line, put them in script order with a marker per scene, and work on a branch. Give me a list of the takes you picked. ``` In a chat app, you drag the script and the takes into the project's Media panel in invideo. In a terminal, you name the folder and the agent uploads it. #### What you need The agent needs the words of the script and the sound of every take. - **The script.** A PDF, a Word file, or plain text, with scene headings and the speaker of each line. - **The takes.** MP4 or MOV from the camera. Each take needs sound, from the camera or a separate recorder. - **Separate sound, if you have it.** WAV files from the recorder. The agent lines them up with the camera sound. - **Your rule for the take.** The last full take, the take the slate marks as good, or the take you name. - **The shape.** The shape of your camera files. The assembly keeps it. #### Steps Your agent edits on a branch and tells you what changed at each step. For each big file, the agent calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id` and the timeline URL. For a PDF script, it runs `media` with `document.pages` if it needs to look at the pages. Expected result: a sequence URL for each take, and the script in the project's files. The agent prices `audio.transcript` on each take with `dry_run` and tells you the total price. It starts each transcript, and calls again after `retry_after_s` for the words. Expected result: every word of every take, with times and speakers. The agent reads the script and each transcript and finds where each line was said, in which take and at what time. It picks one take per line by your rule: the last full take, by default. It writes the match into a brief made with `new_brief`, as a table with `write`: line, take, start, end. Expected result: a brief URL with one take per line, the other takes as options, and the lines with no match at the top. For sound recorded apart from the camera, the agent finds the same words in the camera sound and the recorder file with `audio.transcript`. It checks the line-up with `audio.waveform`. It places the recorder file at the same time and mutes the camera sound with `set_audio_muted`. Expected result: the clean sound plays with each picture, in sync. The agent makes a timeline with `new_timeline` and a branch with `timeline_history`. It places each picked take in script order with `place_media`, from the line's start to its end, with its sound. For a take used whole, it uses `insert_media`. It adds a marker per scene with `add_marker`, named after the scene heading. Expected result: the full script in order, scene by scene. The agent runs `find_models` with "scratch voice line", picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. Your agent can search for others with `find_models`. It picks a `voice_id` with `search_library`, calls `generate` with `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, and names the clip "TEMP" with `rename`. Expected result: a sequence URL for the scratch line, which the agent reads with `read`. The agent runs `capture` at the first frame of each scene and `check_timeline`. It tells you the timeline URL, the brief URL, and the lines with no take. You watch the cut and name the takes to swap. Expected result: a string-out you can review in the editor. The same job from a terminal: ```bash invideo project new --title "Short film assembly" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Assembly v1" --fps 24 invideo asset upload ./footage/* invideo asset upload ./script.pdf invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo context new-brief --name "Line to take" \ --description "Each script line, its take, start and end" invideo edit show --json invideo branch new --name assembly --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @stringout.json invideo edit capture --at 0,48,102 --out ./frames invideo library search \ --library elevenlabs_text_to_speech_voices --query "calm male" invideo gen models --query "scratch voice line" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt="We should have left an hour ago." -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key scratch-line-14 \ -i prompt="We should have left an hour ago." -i voice_id= invideo status --wait invideo edit check ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the `url` that `invideo asset upload ` returns for each take, a `…/notebook/seq-N.M` sequence URL. A transcript refuses a bin `--asset`. - `` is the dry run's `.estimated_credits` (or `credits` on a `media` op), for each paid line. - `` comes from `invideo edit show ` for the branch command. `` is the `.branch_url` that `invideo branch new` returns. For `edit change`, `` is read again with `invideo edit show `. The main token is stale on the branch. - `` is the `url` the paid `gen run` returns. - `@stringout.json` reads a bare JSON list of ops, the `operations` list of the call below. - `` comes from the `elevenlabs_text_to_speech_voices` search, and `` is a notebook page listed by `invideo notebook show `. The key MCP call, in full, lays out two lines from two takes and marks the scene. `` is the branch URL that `timeline_history` returns, and `` comes from `get_timeline` on it. `` and `` are the sequence URLs that `add_media` returns for takes 3 and 7. At 24 fps, a line that runs 3.5 seconds is 84 frames. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "add_marker", "at_f": 0, "name": "Scene 1. Kitchen, night", "note": "Lines 1 to 2" }, { "op": "place_media", "asset": "", "track": "V1", "at_f": 0, "source_start_seconds": 12.4, "source_end_seconds": 15.9, "mode": "overwrite", "linked_audio": true }, { "op": "place_media", "asset": "", "track": "V1", "at_f": 84, "source_start_seconds": 31.0, "source_end_seconds": 35.2, "mode": "overwrite", "linked_audio": true } ] } ``` To swap a take, the agent uses `place_media` with mode `replace` and the clip to replace in `replace_clip`. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** one transcript per take with `audio.transcript`. Only the first call spends credits. A scratch line made with `elevenlabs_text_to_speech.elevenlabs_tts_v4` costs credits too. - **Tool ops:** `audio.waveform`, `document.pages`. The dry run shows its price before anything starts. - **Free:** uploads, the match, the string-out, the markers, the checks and the export. The transcripts take a few minutes. The match and the string-out take the agent a few minutes more. Your review of the takes takes the longest. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from takes with no clear sound, or lines that the actors changed. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the take's sequence URL from `add_media` or `invideo asset upload`. | | CLI exit 3 right after `invideo branch new` | The main token is stale on the branch. Run `invideo edit show ` and use its `state_token`. | | A line has no match | The actor changed the words. Tell the agent the take, or ask it to match by meaning. | | The wrong take was picked | Name the take. The agent swaps it with `place_media` mode `replace`. | | A take has no sound | It cannot be matched by words. Name the line it belongs to, or match it by the slate in `video.frames`. | | Separate sound drifts out of sync | Check with `audio.waveform` at the start and end, and place the sound again from the matched word. | | The transcript call returns status running | Call `audio.transcript` again with the same file after `retry_after_s`. | | CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild. | | Avoid: laying the string-out on main | Instead: a branch from `timeline_history`, so the person accepts it. | | Avoid: one transcript call for each word search | Instead: transcribe once, then read the words as many times as you need. | #### Prompts to try Each prompt is a real variation of the job. ```text Use the takes the script supervisor marked as good in ./notes.csv, not the last take. Put the other takes for each line on a track below. ``` ```text Make a selects reel of every take of scene 4, in order, with a marker on each take that says which lines it covers. ``` ```text My interview has no script. Use this outline instead, ./outline.md, and lay out the answers that match each point, best answer first. ``` #### When to use something else invideo has no sync by timecode. If your camera and recorder share timecode, sync them in DaVinci Resolve or Premiere Pro first, then bring the synced files in. For the fine cut after the assembly, keep editing on the timeline, or export a project for your editor with `export` and `format` set to `premiere`, `final_cut` or `davinci`. #### Related - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) - [Cut ums, pauses and retakes, as reversible timeline edits](/how-to/creators/cut-ums-and-retakes) - [Edit a long YouTube video](/how-to/creators/edit-a-long-youtube-video) - [Edit a podcast episode and pull clips from it](/how-to/creators/podcast-edit-and-clips) - [Check your video before you say it is done](/how-to/check-your-video) ### Make a gaming montage from your clips Source: https://docs.invideo.io/how-to/creators/gaming-montage.md A gaming montage from your Fortnite, Valorant or Minecraft clips: the best plays cut on the beat, slow-mo kills, freeze frames, glitches and callouts. You get a gaming montage, also called a highlight reel, frag movie or edit, from your own clips. Your best kills, clutches and funny moments are cut on the beat of a song. The big plays get slow motion, a freeze frame, a shake or a glitch, and a text callout like "ACE" or "1v4 CLUTCH". Use invideo for this when you have long recordings and no time to scrub them: your agent finds the loud moments, cuts them on the beat, and you can still move any clip after on the timeline. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a Valorant montage from my clips in ./clips. Find the kills and the clutch moments, cut them on the beat of a hard trap song, slow down each final kill, add a shake on the big hits and "ACE" when I get one. 16:9 for YouTube. Show me the moments you picked before you cut. ``` In a chat app, you drag your clips into the project's Media panel in invideo. In a terminal, you name the folder and the agent uploads it. #### What you need Short clips are faster to read than a whole stream, but both work. - **Your clips.** MP4 or MOV from OBS Studio, the Xbox Game Bar, ShadowPlay, a console capture, or a Twitch download. - **The game sound.** Keep it in the recording. The agent finds the action by its sound. - **The song.** A track from stock music, or your own file if you have the rights. Copyrighted songs can get the video muted on YouTube or TikTok. - **The callouts.** The words to show: "ACE", "CLUTCH", your name, your channel. - **The shape.** 16:9 for YouTube, 9:16 for TikTok and Shorts. #### Steps Your agent edits on a branch and tells you what changed at each step. For each big recording, the agent calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id`. It runs `media` with `audio.onsets` and `audio.content` on each clip's sequence URL: shots, kill sounds and a loud voice show up as hits and loud spans. It runs `video.sceneSplit` to find cuts in a long stream, and looks at each moment with `video.frames`. Expected result: a sequence URL for each clip, and a list of moments with times. The agent searches `stock_music` with `search_library`, for example "hard trap" or "phonk". You pick from the previews. It runs `audio.beats` on the song for the beats, and `audio.markers` for the drop and the phrases. Expected result: a list of beat times and the time of the drop. The agent makes a timeline with `new_timeline` and a branch with `timeline_history`. It places each moment with `place_media`, then moves each cut onto a beat with `trim_clip`. The best play goes on the drop. Expected result: every cut on a beat. The agent uses `retime` on the big plays. Kind `section` with a `speed` below 1 slows the kill. Kind `freeze` holds the frame at `at_f` for `duration_f` frames. While the speed is changed, that part of the clip's sound is silent, so the agent adds a hit sound over it. Expected result: slow motion and freeze frames on the plays you asked for. The agent adds transitions at the cuts with `add_transition`, for example `shake_zoom`, `glitch` or `flash`. It adds effects to clips with `add_effect`, for example `pixel_glitch`, `wiggle` for camera shake, or `beat_rock` for color bursts. Expected result: the hits feel bigger. The agent adds each callout with `add_text` on the frame of the play, bold and centered, and pops it in with `set_keyframes` on `opacity`. For a hit sound under it, the agent runs `find_models` with "impact sound effect" and reads its pick with `get_model`: a `prompt` and a `duration` within the range `get_model` gives. A good pick is `elevenlabs_sfx`. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a callout on each big play, and a sequence URL for the hit sound, which the agent reads with `read`. The agent runs `capture` at each callout, a few cuts and the end, and `check_timeline`. It runs `audio.loudness` on the song and the game sound. Then it runs `export` with `format` video. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Valorant montage" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Montage v1" --fps 60 invideo asset upload ./clips/*.mp4 invideo media audio.onsets invideo media audio.content invideo media video.frames --at 61,62,63 --out ./look invideo library search --library stock_music \ --query "hard trap" invideo asset add --stock invideo media audio.beats invideo gen models --query "impact sound effect" invideo gen model --model elevenlabs_sfx invideo gen run --model elevenlabs_sfx --dry-run \ -i prompt="deep bass impact hit" -i duration=3 invideo gen run --model elevenlabs_sfx --max-credits \ --idempotency-key hit-1 -i prompt="deep bass impact hit" -i duration=3 invideo status --wait invideo edit show --json invideo branch new --name montage-v1 --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @ops.json invideo edit capture --at 4,12.5,30 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the `url` that `invideo asset upload ` returns for each clip, a `…/notebook/seq-N.M` URL. For `audio.beats` it is the song's, the `url` that `invideo asset add` returns. - `` is a stock result's id from `invideo library search`. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is the dry run's `.estimated_credits`. `` is the `url` the paid run returns. - `` comes from `invideo edit show ` for the branch command. `` is the `.branch_url` that `invideo branch new` returns. For `edit change`, `` is read again with `invideo edit show `. - `@ops.json` reads a bare JSON list of ops, the `operations` list of the call below. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The key MCP call slows a kill, freezes the last frame, adds a shake at the next cut and the callout. This is the full call. `` is the branch URL that `timeline_history` returns, and `` comes from `get_timeline` on it. `c4` and `c5` are clip ids from `get_timeline`. At 60 fps, the kill runs from frame 720 to frame 780. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "retime", "clip": "c4", "kind": "section", "from_f": 720, "to_f": 780, "speed": 0.4 }, { "op": "retime", "clip": "c4", "kind": "freeze", "at_f": 870, "duration_f": 30 }, { "op": "add_transition", "left_clip": "c4", "right_clip": "c5", "type": "shake_zoom", "in_f": 6, "out_f": 6 }, { "op": "add_text", "track": "V2", "start_f": 870, "end_f": 930, "text": "ACE", "style": { "font_size": 160, "font_weight": 800, "align": "center", "stroke": true } } ] } ``` A `retime` changes the clip's length, and later clips move. The agent reads the timeline again with `get_timeline` before it adds more cuts after it. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** a paid stock song and any sound effect from `elevenlabs_sfx`. - **Tool ops:** `audio.onsets`, `audio.content`, `audio.beats`, `audio.markers`, `audio.loudness`, `video.sceneSplit`, `video.frames`. The dry run shows its price before anything starts. - **Free:** uploads, the cuts, `retime`, the effects, the callouts and the export. A montage from a folder of short clips takes the agent a few minutes. A long stream takes longer to read. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from clips with music under the game, or effects that hide the play. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | The agent picked the wrong moments | Give it the times, or the words of the kill feed. It looks with `video.frames` and picks again. | | Your in-game music hides the shots | `audio.onsets` hears the music too. Turn off game music when you record, or pick by frames. | | The sound drops out in the slow motion | That is how `retime` works. Add a hit sound or a whoosh over that part. | | `retime` refused | The clip loops, and `retime` refuses looping clips. Make a slow-motion file with `media` `video.changeSpeed` instead. | | A link download fails | Upload the file with `start_upload`, then `add_media` with the `upload_id`. | | A clip has no sound | `audio.onsets` finds nothing. The agent picks the moments with `video.frames` only, and tells you. | | `trim_clip` refused as stale | The edge moved. Read with `get_timeline` and send the trim with the new `from_f`. | | Too many effects | Ask for effects on the top plays only, and plain cuts between. | | CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild. | | Avoid: sending more cuts after a `retime` without a read | Instead: read with `get_timeline` first. Later clips have moved. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 9:16 Fortnite montage for TikTok from ./fortnite. Fast cuts on every beat, a flash on each elimination, and my name at the end. ``` ```text Cut a Minecraft build timelapse from my long recording: speed up the building, keep the reveal at normal speed, calm music under it. ``` ```text Find the five funniest moments in my Twitch VOD, where chat and I laugh the loudest, and make a short montage with meme callouts. ``` #### When to use something else invideo does not record your game or download Twitch VODs. Record with OBS Studio or your console, and download VODs from your Twitch dashboard. Then bring the files in. invideo has no face cam crop that follows you. Place your face cam by hand with `set_position` and `set_zoom`. #### Related - [Make a sports highlight reel, including college recruiting videos](/how-to/personal/sports-highlight-reel) - [Make a book trailer or a game trailer](/how-to/creators/book-or-game-trailer) - [Make a trend edit like CapCut: slow-mo, meme, freeze frame](/how-to/personal/trend-edit) - [Make Reels and Shorts from your footage: hook, captions, transitions, sound effects](/how-to/creators/reels-and-shorts-from-your-footage) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) ### Make a thumbnail for the video Source: https://docs.invideo.io/how-to/creators/thumbnail.md A YouTube thumbnail from a frame of your video: a cutout of you, a bold title and a clean background, in 16:9, with variants to test. You get a thumbnail, also called a cover image or YouTube thumbnail, for your video. It starts from a real frame of your video, or a shot your agent generates. Your face or the subject is cut out, a clean background goes behind it, and a short title in big letters sits on top. Use invideo for this when the thumbnail should match the video: your agent grabs the frame from the same timeline, builds the thumbnail on its own timeline, and makes a new variant with one text change. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a YouTube thumbnail for my video in this project. Find the frame where my face looks the most surprised, cut me out, put me on the right over a bright blurred background, and add "I TRIED IT FOR 30 DAYS" on the left in big yellow letters. 16:9. Make two variants. ``` In a chat app, you look at the thumbnail in invideo and ask for changes in the chat. In a terminal, the agent saves the image to a folder you name. #### What you need Big faces and few words read best at the small size people see in a feed. - **The video, or a photo.** The timeline or the source clip in the project, or a photo you bring in. - **The moment.** A time, or a description: "my reaction at the end", "the finished build". - **The title.** Three to five words. It should add to the video title, not repeat it. - **The look.** Colors, font, and your channel's style. Your brand guide, if you have one. - **The shape.** 16:9, the shape YouTube shows thumbnails in. #### Steps Your agent edits on a branch and tells you what changed at each step. ##### Make the parts The agent makes the still, the cutout and the background first. The agent looks at the video with `capture` on the timeline, or `media` with `video.frames` on a source clip, at the moments you named. You pick one, or the agent picks the clearest face. Expected result: a few frames to pick from. From a source clip, the agent runs `media` with `video.extractFrameAtTime` on the clip's sequence URL from `add_media`, with `time_seconds` and an `idempotency_key`. From the timeline, it runs `export` with `mode` image and `still_at`. Expected result: a still image as a new sequence. The agent runs `media` with `image.removeBackground` on the still's sequence URL, `dry_run` first, and tells you the price. Then it runs it with `max_credits` and an `idempotency_key`. Expected result: a cutout of you or the subject, as a new image. The agent runs `find_models` with `output` image and the background in words. A good pick is `flux_3_image.generate`, with a `prompt` and `aspect_ratio` 16:9. To keep the same scene, `flux_3_image.edit` takes your still in `images`. Your agent can search for others with `find_models`. The agent reads its pick with `get_model`, calls `generate` with `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, and reads the result with `read`, never with a second `generate`. For a crisp result, it runs `media` with `image.upscale` on the image's sequence URL, `dry_run` first. Expected result: a sequence URL for a 16:9 background. ##### Build and export Then the agent builds the thumbnail, makes variants and checks them small. The agent makes a 16:9 timeline with `new_timeline` and a branch with `timeline_history`. It places the background on `V1` and the cutout on `V2` with `insert_media`, then moves and sizes the cutout with `set_position` and `set_zoom`. It adds `drop_shadow` to the cutout with `add_effect`. Expected result: you over the background, on one side. The agent adds the title with `add_text`, big and bold, with `stroke` and `shadow` on. It colors one word with `style_text_range`. Expected result: a title you can read at a glance. The agent copies the thumbnail timeline with `duplicate_timeline` for each variant. It changes the words with `set_text`, or the color with `set_text_style`. Expected result: one timeline per variant. The agent runs `capture` on each variant and looks at it at a small size, as it shows in a feed. Expected result: a title you can read at feed size on every variant. The agent runs `export` with `mode` image and `still_at` for each variant, with its `timeline_id`. Expected result: one still image per variant. The same job from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo edit new --name "Thumbnail" invideo asset upload ./video.mp4 invideo media video.frames --at 212,214,216 --out ./pick invideo media video.extractFrameAtTime --time-seconds 214 \ --idempotency-key thumb-still-1 invideo media image.removeBackground --dry-run invideo media image.removeBackground --max-credits \ --idempotency-key thumb-cutout-1 invideo gen models --query "bright blurred studio background" invideo gen model --model flux_3_image.generate invideo gen run --model flux_3_image.generate --dry-run \ -i prompt="bright yellow and blue blurred studio, soft light" \ -i aspect_ratio=16:9 invideo gen run --model flux_3_image.generate \ --max-credits --idempotency-key thumb-bg-1 \ -i prompt="bright yellow and blue blurred studio, soft light" \ -i aspect_ratio=16:9 invideo status --wait invideo notebook show invideo media image.upscale --dry-run invideo media image.upscale --max-credits \ --idempotency-key thumb-bg-up-1 invideo edit show --json invideo branch new --name thumb-a --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @thumb.json invideo edit capture --at 0.5 --out ./thumb invideo edit export --format video --mode image \ --still-at 0.5 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` is your video's project, from `invideo project new` or the editor. `` comes from `invideo edit new`. - `` is the video's `url` that `invideo asset upload` returns, a `…/notebook/seq-N.M` URL. File-making ops like `video.extractFrameAtTime` refuse a bin `--asset`. - `` is the sequence URL `video.extractFrameAtTime` returns. The cutout's sequence URL comes back from `image.removeBackground`. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is each dry run's `.estimated_credits`. - `` is the `url` the paid `gen run` returns. `` is the image's sequence URL, which `invideo notebook show ` lists. - `` comes from `invideo edit show`: on `` for the branch, then on `` for the change. `` is the `.branch_url` that `invideo branch new` returns. - `@thumb.json` reads a bare JSON list of ops, the `operations` list of the call below. The background and the cutout are already placed with `insert_media` in an earlier change. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the still in `./out`, and the agent renames it. The key MCP call, shown as the full call, places the cutout, adds its shadow and the title. `` is the branch URL `timeline_history` returns, and `` comes from `get_timeline` on it. `c2` is the cutout clip's id, read with `get_timeline` after `insert_media` placed it. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "set_position", "clip": "c2", "x": 480, "y": 60 }, { "op": "set_zoom", "clip": "c2", "x": 1.2, "y": 1.2 }, { "op": "add_effect", "clip": "c2", "effect": "drop_shadow" }, { "op": "add_text", "track": "V3", "start_f": 0, "end_f": 30, "text": "I TRIED IT\nFOR 30 DAYS", "style": { "font_size": 180, "font_weight": 900, "color": "#ffe600", "align": "left", "stroke": true, "stroke_color": "#000000", "stroke_width": 10, "shadow": true } } ] } ``` The `export` call for the still, with `still_at` inside the text clip's time, on the same ``: ```json { "url": "", "format": "video", "options": { "mode": "image", "still_at": 0.5 }, "idempotency_key": "thumb-variant-a" } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** the cutout with `image.removeBackground`, the generated background, and `image.upscale`. - **Tool ops:** `video.frames`, `video.extractFrameAtTime`. The dry run shows its price before anything starts. - **Free:** finding the frame with `capture`, the thumbnail timeline, the text, the variants and the still export. A thumbnail takes the agent a few minutes. Each variant after the first takes less. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from text that is too small, or a cutout with rough edges. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `video.extractFrameAtTime` or `image.removeBackground` refused with `code: "not_found"` | The call named a media bin asset. Pass the file's sequence URL from `add_media` or `invideo asset upload`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | The title is hard to read small | Use fewer words, a bigger `font_size`, and `stroke` on. Then `capture` again. | | The cutout has a rough edge | Run `image.removeBackground` again with `model` set to the other one, `birefnet_bg_remove`. | | The face is blurry | Pick a sharper frame, or run `image.upscale` on the still before the cutout. | | The background has text or a logo in it | Generate it again with "no text" in the prompt. | | The still export is blank | `still_at` is outside the clips. Set it inside the span of every clip. | | `generate` refused for `max_credits` | The price is above the cap. Run the dry run again and agree a new cap. | | Avoid: a frame grab of the whole video as the thumbnail | Instead: a cutout, a clean background and a few big words. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a thumbnail from the finished build at the end of my video. Put "BEFORE" and "AFTER" on two halves, with a red arrow between them. ``` ```text I have no good frame. Generate a photo of a person shocked at a laptop, in my channel colors, and add "STOP DOING THIS" in big white letters. ``` ```text Make three thumbnail variants with different titles from this list, ./titles.txt, and export each as a still. ``` #### When to use something else invideo does not upload thumbnails to YouTube or test them against each other. Upload the stills in YouTube Studio, and use its own test tools there. For a detailed design with many layers and photo retouching, use an image editor like Photoshop, Canva or Figma. Bring the finished image back in with `add_media` if you want it in the video. #### Related - [Make a faceless YouTube video yourself, with AI help](/how-to/creators/faceless-youtube-video) - [Edit a long YouTube video](/how-to/creators/edit-a-long-youtube-video) - [Make an intro, welcome video, outro or logo animation for your channel or business](/how-to/creators/intro-outro-logo-animation) - [Models](/reference/models) - [Check your video before you say it is done](/how-to/check-your-video) ### Customize a template you bought Source: https://docs.invideo.io/how-to/creators/customize-a-template-you-bought.md invideo does not open After Effects, Premiere Pro or CapCut template files. Your agent rebuilds the look on a timeline you can change for every version. invideo does not open a template you bought. A template from VideoHive, Envato Elements, Motion Array or the CapCut app is a file for another tool. An `.aep` file opens in After Effects. A `.mogrt` file opens in Premiere Pro. A CapCut template opens in CapCut. If you have that tool, change the text and photos there. It is the fastest way. If you do not have that tool, or you want many versions, your agent can rebuild the look in invideo. It studies the template's preview video and remakes the text, motion and transitions on a timeline. Then it makes one version per name, product or date. Use invideo for this when you want a template you can change by asking: once the look is on a timeline, each new version is one text change, and your agent makes them all. Do not publish the seller's preview video. It is a guide for the rebuild, not footage for your video. Read the template's license for what you may copy. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text I bought this intro template: ./template/preview.mp4. I do not have After Effects. Rebuild the look in invideo with the fonts in ./template/fonts, my logo ./logo.png and the text "Maya Cooks". Match the timing of the preview. Then make versions for "Maya Bakes" and "Maya Travels". Show me frames next to the preview. ``` In a chat app, you drag the preview, the fonts and your files into the project's Media panel in invideo. In a terminal, you name the folder and the agent uploads it. #### What you need Most template downloads come with a preview video and a fonts folder. Use those. - **The preview video.** The MP4 that shows the template in motion, from the download or the seller's page. - **The fonts.** TTF or OTF files from the download, or a link to where the seller says to get them. - **Your content.** The text, logo, photos and clips that replace the placeholders. - **The music.** The template's track if the license covers it, a track from stock music, or your own file. - **The shape.** The shape of the template: 16:9, 9:16 or 1:1. #### Steps Your agent edits on a branch and tells you what changed at each step. The agent brings each file in with `add_media` on the timeline URL. A font makes no sequence. Its id in the result's `created` is the `font` that `add_text` takes. Expected result: the preview, your files and the fonts in the media bin. The agent runs `media` with `video.sceneSplit` on the preview to find its scenes, `video.frames` to look at each one, and `audio.beats` for the timing of its music. It makes a timeline in the template's shape with `new_timeline` and a branch with `timeline_history`, then places the preview on its own track with `insert_media` and lowers it with `set_opacity`, as a guide. Expected result: a list of scenes with times, and the preview on the timeline, faint, to build over. For each scene, the agent adds the text with `add_text` and the template's font, then matches the size, color and spacing with `set_text_style`. It adds bars and boxes with `add_shape`, and your logo and photos with `insert_media`. For a placeholder shot you do not have, it searches `stock_video` first. For a shot that stock does not have, it runs `find_models` with the shot in words and reads its pick with `get_model`. A good pick is `seedance_2_5.frames`. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true`, a `prompt` and the template's `aspect_ratio`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: each scene looks like the preview, with your content, and each generated shot is a sequence URL the agent reads with `read`. The agent fades text in and out with `set_keyframes` on `opacity`, and slides it with `add_keyframe_lane` on `position_x` or `position_y`, then `add_keyframes` for the points. It picks transitions from the catalog with `add_transition`, for example `slide`, `zoom` or `light_leak`, and effects with `add_effect`. Expected result: the motion follows the preview's timing. The agent runs `capture` on the timeline and `video.frames` on the preview at the same times, and compares them by eye. It fixes what is off. Then it turns the guide off with `set_clip_enabled` set to false. Expected result: frames that match the preview's look, with the guide off. The agent copies the finished timeline with `duplicate_timeline` for each version. It changes the words with `set_text` and swaps photos with `place_media` mode `replace`. Expected result: one timeline per version. The agent runs `capture` on each version and `check_timeline`. It checks that no text runs off the frame with a longer name. Then it runs `export` with the `timeline_id` of each version. Expected result: one export card per version, each with status `completed`. The same job from a terminal: ```bash invideo project new --title "Maya intro" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Intro rebuild" invideo asset upload ./template/preview.mp4 \ ./template/fonts/*.otf ./logo.png invideo media video.sceneSplit --dry-run invideo media video.frames --at 0.5,1.5,3 --out ./ref invideo edit catalog --transitions slide,zoom,light_leak invideo gen models --query "short shot from a prompt" invideo gen model --model seedance_2_5.frames invideo gen run --model seedance_2_5.frames --dry-run \ -i prompt="hands kneading dough on a floury table" -i aspect_ratio=16:9 invideo gen run --model seedance_2_5.frames \ --max-credits --idempotency-key placeholder-3 \ -i prompt="hands kneading dough on a floury table" -i aspect_ratio=16:9 invideo status --wait invideo edit show --json invideo branch new --name rebuild --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @rebuild.json invideo edit capture --at 0.5,1.5,3 --out ./mine invideo edit check invideo edit export --format video --quality 1080 \ --timeline --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command. - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the `url` that `invideo asset upload` returns for the preview, a `…/notebook/seq-N.M` URL. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is the dry run's `.estimated_credits`. `` is the `url` the paid run returns. - `` comes from `invideo edit show ` for the branch command. `` is the `.branch_url` that `invideo branch new` returns. For `edit change`, `` is read again with `invideo edit show `. - `@rebuild.json` reads a bare JSON list of ops, like the `operations` list of the call below. - `` is a version's timeline id, like `T2`, that `invideo edit show ` lists after `duplicate_timeline`. - `` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it per version. The key MCP call, in full, turns the rebuilt title into a new version. `T1` is the finished rebuild. `` is the branch URL that `timeline_history` returns, and `` comes from `get_timeline` on it. `` is the guide clip's id from `get_timeline`. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "set_clip_enabled", "clip": "", "enabled": false }, { "op": "duplicate_timeline", "timeline": "T1", "name": "Maya Bakes" } ] } ``` On the new timeline, the agent sends `set_text` with the title clip's id and the new words. It reads the ids with `get_timeline` first. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** paid stock music or footage, and any shot the agent generates with `seedance_2_5.frames`. - **Tool ops:** `video.sceneSplit`, `video.frames`, `audio.beats`. The dry run shows its price before anything starts. - **Free:** uploads, fonts, the rebuild, the versions and every export. A short intro takes the agent a few minutes to rebuild. A template with many scenes and 3D motion takes longer, and some moves do not carry over. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from fonts that are missing, or motion the timeline cannot copy. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | The text uses the wrong font | Bring in the font file with `add_media` on the timeline URL, then set its id as `font` with `set_text_style`. | | A move in the template looks 3D | Use the nearest transition from the catalog, like `cube_3d_rotation` or `roll_3d`, or write one with `add_custom_transition`. | | A long name runs off the frame | Lower `font_size` for that version, then `capture` again. | | The guide shows in the export | Turn it off with `set_clip_enabled` set to false before you export. | | `edit_timeline` refused with an old token | Read with `get_timeline` and send the ops again. | | CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild. | | Avoid: telling the person the `.aep` file opened | Instead: say invideo does not open it, name the tool, and offer the rebuild. | | Avoid: placing the seller's preview in the final export | Instead: use it as a guide, turned off before the export. | #### Prompts to try Each prompt is a real variation of the job. ```text I bought a CapCut template but I want it in 16:9. Here is a screen recording of it, ./capcut.mp4. Rebuild the look in 16:9 with my clips. ``` ```text Rebuild this wedding invitation template from its preview with our names and date, then make a 9:16 version for WhatsApp. ``` ```text Rebuild this sale promo template from its preview with our products, and make one version for each product in ./products.csv. ``` #### When to use something else If you own the tool the template is for, use it. After Effects opens `.aep` files, Premiere Pro opens `.mogrt` files, and the CapCut app opens CapCut templates. The template's own controls are faster than a rebuild. invideo cannot copy particle effects, 3D camera moves or plug-in effects from a template exactly. For those, ask the seller for a version for your tool, or hire an editor who owns that tool. #### Related - [Make an intro, welcome video, outro or logo animation for your channel or business](/how-to/creators/intro-outro-logo-animation) - [Make a video invitation for a birthday, wedding, baby shower or gender reveal](/how-to/personal/video-invitation) - [Use CapCut with invideo](/integrations/capcut) - [Turn a CSV into many videos with a script](/how-to/developers/csv-to-videos) - [Timeline edit operations](/reference/edit-operations) ## Marketing ### Make a launch video from your product URL and screenshots Source: https://docs.invideo.io/how-to/marketing/launch-video.md A launch video, also called a product demo or promo video, from your product page and screenshots: voiceover, pushes into the UI, music and captions. You get a launch video, also called a product promo or SaaS demo video, made from your product page, your screenshots and your screen recordings. The video has a voiceover written from your page's copy, slow pushes into the parts of the UI that matter, music and captions. A screen can sit inside a tilted phone or laptop frame. Use invideo for this when you want the launch video as an editable timeline: you change a line of the script, a screenshot or the music after the first cut, and your agent does it in your chat. This is ordinary marketing work on your own product. The agent makes the video. You publish it and you post it. The agent never publishes it. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 45 second launch video for https://example.com. Capture the landing page and the pricing page, use my screenshots in ./shots and the screen recording ./demo.mp4. Write a short voiceover from the page's copy, push into each key feature, add calm upbeat music and captions. Tell me the price before you generate the voice. ``` In a chat app, you drag your screenshots and recordings into the project in invideo, and you paste the page captures the agent makes. In a terminal, you name the folder and the agent uploads it. #### What you need Bring what shows the product best. Real screens beat mockups. - **The product URL.** The agent opens it with its own browser to read the copy and take screenshots. - **Screenshots and screen recordings.** PNG, JPG, MP4 or MOV, at the size you captured them. - **A device frame, if you want one.** A PNG of a phone or a laptop with a transparent screen. - **The shape.** 16:9 for a site or YouTube, 1:1 or 9:16 for social. - **The voice and the mood.** A voice you like, and a music mood such as calm or upbeat. - **The length.** 30, 45 or 60 seconds is common for a launch. #### Steps The agent works on a branch and tells you what changed at each step. invideo does not capture web pages. The agent opens the URL with its own browser or screenshot tool, saves full-width screenshots, and reads the headline, the features and the call to action. Expected result: a folder of page images and a list of the page's key lines. The agent makes a project with `new_project` and a 1920 by 1080 timeline with `new_timeline`. It creates a branch with `timeline_history`. It uploads each screenshot and recording with `start_upload` and `add_media`. Expected result: a sequence URL per file. The agent writes a short script from the page's copy, one line per feature, and shows it to you first. It runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a voice from `search_library` in `elevenlabs_text_to_speech_voices`. It calls `generate` with `dry_run: true`, the script as `prompt` and the `voice_id`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL with the voiceover. The agent reads it with `read` and never calls `generate` again to check. The agent places each screen with `place_media` in the order of the script. On a still, it adds the `dynamic_zoom` effect with `add_effect`, then sets the end point and the end zoom with `set_effect_parameter` to push into the feature. For a custom move, it adds a lane with `add_keyframe_lane` on `zoom_x`, `zoom_y`, `position_x` or `position_y` and fills it with `add_keyframes`. Expected result: each screen moves toward the part the voice talks about. For a flat frame, the agent places the device PNG on a track above the screen and sizes the screen with `set_zoom` and `set_position`. For a tilted frame, it needs a corner pin. It reads `timeline_catalog` with `guides` `custom_shader`, writes a GLSL shader with the four screen corners as `vec2` parameters, and adds it with `add_custom_effect`, `dry_run` first. Expected result: the recording sits inside the tilted screen. The agent finds a track with `search_library` in `stock_music` and adds it with `add_media`. It sets the music under the voice with `set_audio_gain`. It prices `audio.transcript` on the voiceover's sequence URL with `dry_run`, starts it with `max_credits` set to the price, and calls again after `retry_after_s` for the word times. Then it adds captions with `add_captions`. Expected result: music under the voice, and captions that follow each word. The agent runs `capture` at each push and each caption, and `check_timeline`. It looks for text off the edge and screens that look soft. Then it runs `export` with `format` video. Expected result: an export card with status `completed`, and the MP4 in its files. A terminal agent saves it with `invideo notebook show`. The same job from a terminal: ```bash invideo project new --title "Launch video" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Launch 45s" invideo asset upload ./shots/*.png ./demo.mp4 invideo library search \ --library elevenlabs_text_to_speech_voices --query "warm narrator" invideo gen models --query "voiceover from a script" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --dry-run -i prompt=@script.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key launch-voice-v1 \ -i prompt=@script.txt -i voice_id= invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo edit catalog --guides custom_shader --effects dynamic_zoom invideo edit show --json invideo branch new --name launch-v1 --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 2,8,15,30 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where the values come from: - `` comes from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`. `` is a notebook page from `invideo notebook show `. - `` comes from the voice search. Each `` is the dry run right before it. - `` is the voice's sequence URL, which the paid voice run returns. - `` comes from `invideo edit show `, and on the branch from `invideo edit show `; the main token is stale there. `` is the `.branch_url` that `invideo branch new` returns. - `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves the file as `./out/export.mp4`. - The file `./ops.json` holds a bare list of operations: the `operations` list of the MCP call below. The key MCP call places a screenshot, starts the push and puts the corner pin on the recording. `` is the branch's URL from `timeline_history`, and `` comes from `get_timeline`. `` is the URL `add_media` returns for the screenshot. `c1` is the id the placed screenshot gets, and `c4` is the recording, from `get_timeline`. `` is the shader the agent writes from the guide. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "place_media", "asset": "", "track": "V1", "at_f": 0, "source_start_seconds": 0, "source_end_seconds": 5, "mode": "append", "linked_audio": false }, { "op": "add_effect", "clip": "c1", "effect": "dynamic_zoom" }, { "op": "add_custom_effect", "clip": "c4", "name": "Corner pin", "source": "", "params": [ { "name": "tl", "label": "Top left", "type": "vec2", "default": [0.18, 0.12] }, { "name": "tr", "label": "Top right", "type": "vec2", "default": [0.82, 0.16] }, { "name": "br", "label": "Bottom right", "type": "vec2", "default": [0.80, 0.86] }, { "name": "bl", "label": "Bottom left", "type": "vec2", "default": [0.20, 0.90] } ] } ] } ``` The agent sets the end point and end zoom of `dynamic_zoom` in a second call, with the effect's id from `get_timeline`. You can drag the four corner controls in the effects panel after. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** uploads, layout, the zoom effect, keyframes, the corner pin shader, captions you place, and the export. - **Costs credits:** the voiceover model, the transcript of the voice, and stock music. A launch video takes under an hour, most of it on the script and your review. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are a soft screenshot or a corner pin that sits off the screen. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | An upload is refused | Read the `message`, fix what it names, and upload once more. | | A screenshot looks soft after the push | Capture it at a larger size, or push less with a lower end zoom. | | `invalid_custom_effect` | Fix each error the refusal lists by line and column. Send again with `dry_run` first. | | The pinned screen does not line up with the frame | Change the corner values with `set_effect_parameter`, and `capture` again. | | `set_keyframes` refused for zoom | It takes `opacity` and `rotation` only. Use `add_keyframe_lane` and `add_keyframes`. | | The voice reads a product name wrong | Spell it as it sounds in the script, and generate that line again. | | CLI exit 3 on the branch | The token is from main. Run `invideo edit show ` and use its `state_token`. | | The `./out` folder is empty after `status` | `status` waits and does not download. Run `invideo notebook show --out ./out`. | | CLI exit 5 | A credit limit. Ask the person before the agent spends more. | | Avoid: the agent asks invideo to capture the URL | Instead: it uses its own browser or screenshot tool, then `add_media`. | | Avoid: saying done without looking | Instead: `capture` frames at every push and caption. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 30 second vertical teaser for my app from the screen recording ./onboarding.mov inside the phone frame ./iphone.png. Tilt the phone, no voice, bold captions with the three key lines from my homepage. ``` ```text Turn my changelog page https://example.com/changelog into a 60 second "what's new" video. One screenshot per feature, a push into each, a calm voice and soft music. ``` ```text Make the launch video for https://example.com in 16:9 and 1:1. Same script and voice. Put each shape on its own branch so I can compare. ``` #### When to use something else invideo does not capture web pages or record your screen. Use the agent's browser tool, your OS screenshot tool, or a screen recorder, then bring the files in. For a 3D device that turns in space, use a 3D tool and bring the render in as a clip. The corner pin here is a flat warp of the screen. #### Related - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Test hooks on one ad, with branches](/how-to/marketing/test-hooks-on-branches) - [Make an App Store preview video at Apple's sizes](/how-to/marketing/app-store-preview) - [Turn release notes or a changelog into a video every week](/how-to/training/release-notes-to-video) - [Check your video before you say it is done](/how-to/check-your-video) ### Make a UGC ad from product photos with an AI actor Source: https://docs.invideo.io/how-to/marketing/ugc-ad-with-ai-actor.md A vertical UGC-style ad, or AI creator ad, with an AI actor who talks about your product, your real product shots, captions and a hook. You get a vertical UGC ad, also called a creator-style ad or AI spokesperson ad, where an AI actor talks to camera about your product. Your real product photos and clips sit between the talking shots, so the product on screen is the one you sell. The ad has a hook line, captions and a short call to action. Use invideo for this when you want the actor, the voice, your product shots and the captions on one editable timeline: you swap the hook, the voice or a product shot and export again, without a new shoot. Making ads for your own product is ordinary marketing work, and your agent does it. The agent never switches an ad on or spends ad budget. You upload the ad and run it in the ad platform. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 20 second vertical UGC ad for my serum. Use the actor photo ./actor.jpg and my product photos in ./product. Write a script with the hook "I stopped buying three products for this one", make the voice, animate the actor, cut to my real product shots, add captions. Tell me the price before you generate anything. ``` In a chat app, you drag the actor photo and product photos into the project in invideo. In a terminal, you name the folder and the agent uploads it. #### What you need The actor and the product come from you. The agent does not invent either one. - **An actor photo you have the rights to.** A front-facing portrait of a person who agreed to appear in AI ads, or a face made with an image model. - **Product photos and clips.** The real product, sharp, from a few angles. A short phone clip of the product in a hand is good. - **The claim and the hook.** What the product does, in your words, and two or three hook lines to test. - **The shape.** 9:16 for TikTok, Reels and Shorts. 4:5 or 1:1 for feeds. - **The voice.** A voice from the library, or your own voice clip. #### Steps The agent works on a branch and tells you what changed at each step. The agent makes a project with `new_project`, a 1080 by 1920 timeline with `new_timeline`, and a branch with `timeline_history`. It uploads the actor photo and product files with `start_upload` and `add_media`. Expected result: a sequence URL per file. The agent writes a short script: the hook, one or two lines on the product, the call to action. It shows you the script first. It runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. It picks a voice with `search_library` in `elevenlabs_text_to_speech_voices`, because a voice id works only with its own model. It calls `generate` with `dry_run: true` and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL with the voiceover, which the agent reads with `read`. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `heygen_photo_avatar`, and `kling_avatar.std` takes the same `image` and `audio`. It calls `generate` with the actor photo as `image`, the voice as `audio`, `aspect_ratio` 9:16 and `dry_run: true`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL and, when the take lands, a sequence URL with a talking video whose length follows the voice. The agent reads it with `read` and never calls `generate` again to check. The agent cuts from the actor to your real product photos and clips with `place_media`. A product shot stays your photo or clip, so the label, color and shape are exact. Expected result: talking shots and real product shots, in script order. A generated shot can redraw the label or the shape. The agent runs `capture` on every generated shot that shows the product, and compares each frame with your photo. It replaces any shot where the product changed with your real photo. Expected result: the product looks the same in every frame. The agent adds the hook as `add_text` in the first seconds. It prices `audio.transcript` on the voice's sequence URL with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. It adds a line such as "AI-generated actor" with `add_text` where the platform asks for one. Expected result: a hook at the top, captions that follow the voice, and the disclosure on screen. The agent runs `capture` at the hook, at each cut and at the end, and `check_timeline`. It checks that captions and the hook sit clear of the app buttons. Then it runs `export` with `format` video. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Serum UGC ad" invideo agent register --name export INVIDEO_AS= invideo edit new --name "UGC 20s" --width 1080 --height 1920 invideo asset upload ./actor.jpg ./product/* invideo library search \ --library elevenlabs_text_to_speech_voices --query "warm young woman" invideo gen models --query "voiceover from a script" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@script.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key serum-voice-1 \ -i prompt=@script.txt -i voice_id= invideo gen models --query "talking actor from a photo" invideo gen model --model heygen_photo_avatar invideo gen run --model heygen_photo_avatar --dry-run \ -i image= -i audio= \ -i aspect_ratio=9:16 invideo gen run --model heygen_photo_avatar \ --max-credits --idempotency-key serum-ugc-actor-take-1 \ -i image= -i audio= \ -i aspect_ratio=9:16 invideo status --wait invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo edit show --json invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 0.5,4,9,15,19 --out ./frames invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`. `` is the `url` that `invideo asset upload` returns for the actor photo. `` is a notebook page from `invideo notebook show `. `` comes from the library search. `` is the sequence URL the voice run returns when it lands. Each `` is its dry run's `estimated_credits`. `` is the `url` the paid actor run returns. `` comes from `invideo edit show`. `ops.json` is a bare list of edit ops. `` is `.sequences[0]` of what the export returns. `invideo status` does not download; `invideo notebook show` saves the file as `export.mp4`. The key MCP call makes the talking actor. It is a dry run, so it only checks the inputs and returns the price. `` comes from `read` on the project URL, and the two sequence URLs come from `add_media` and the voice generation. ```json { "url": "", "model": "heygen_photo_avatar", "dry_run": true, "inputs": { "image": "", "audio": "", "aspect_ratio": "9:16", "expressiveness": "medium" } } ``` The agent then sends the same call with `dry_run` false, `max_credits` set to the price and `idempotency_key` `serum-ugc-actor-take-1`. To change the voice later without a new actor take, the agent calls `generate` with `sync_lipsync_v3.video`, the actor video as `video` and the new voice as `audio`: a dry run first, then `max_credits` and an `idempotency_key`. It sets `sync_mode` to `remap` when the new voice is a different length. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** uploads, cuts, your product shots, text, captions you place, the checks and the export. - **Costs credits:** the voice, the actor model, any reference-to-video shot, the lip re-sync and the transcript. Actor models charge by the second of audio. One ad takes under an hour, most of it on the script and the takes you compare. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are a product that changed in a generated shot, or a mouth out of sync. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The label or shape changed in a generated shot | Use your real photo or clip for that shot. Generated shots are for the actor, not the pack. | | You want the actor holding the product | Generate it with `seedance_2_5.r2v` and your product photos in `reference_images`: `find_models`, `get_model`, a dry run, then `generate` with `max_credits` and an `idempotency_key`. Check the label by eye. | | The mouth drifts from the words | Run `sync_lipsync_v3.video` on the take with the same voice. | | The actor model refuses the photo | Use a sharp, front-facing photo of one face. Read the refusal `message`. | | Status `needs_confirmation` | Only you can confirm it, in invideo. | | The download folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./out`. | | Avoid: the agent resends `generate` to check on a take | Instead: it reads the thread URL, or calls `status`. | | Avoid: a face of a real person without their consent | Instead: use a person who agreed, or a made-up face. | #### Prompts to try Each prompt is a real variation of the job. ```text Make three versions of my UGC ad, each with a different hook from hooks.txt. Same actor, same product shots. One branch per hook. ``` ```text Make a 15 second unboxing-style ad: my clip ./unbox.mp4 first, then the actor ./actor.jpg says why they switched. Bold white captions, 9:16. ``` ```text Swap the voice on my finished UGC ad to a younger male voice, keep the actor and re-sync the lips. Tell me the price first. ``` #### When to use something else For an ad with a real creator, book one on a creator marketplace and bring the clip in with `add_media`. invideo then cuts, captions and exports it. The rules for labeling AI actors differ by platform and by country. invideo adds the words you choose, but it does not check an ad against a platform's policy. Read [Label AI content so your ad runs on TikTok, Meta and Google](/how-to/marketing/ai-disclosure-for-ads) before you run the ad. #### Related - [Label AI content so your ad runs on TikTok, Meta and Google](/how-to/marketing/ai-disclosure-for-ads) - [Test hooks on one ad, with branches](/how-to/marketing/test-hooks-on-branches) - [Turn a product photo into a video without redrawing the product](/how-to/marketing/product-photo-to-video) - [Cut a customer testimonial or raw creator footage into an ad, or the case study set](/how-to/marketing/testimonial-to-ad) - [Make performance ads for Meta, TikTok and YouTube, named and iterated from results](/how-to/marketing/performance-ads) - [Check your video before you say it is done](/how-to/check-your-video) ### Test hooks on one ad, with branches Source: https://docs.invideo.io/how-to/marketing/test-hooks-on-branches.md Many hook variants, or ad creative variations, from one master ad: one branch per hook, a new first line or first clip, and a named file for each. You get many versions of one ad, each with a different hook: the first line, the first clip, or both. This is hook testing, also called creative testing or ad variations. The body of the ad stays the same, so the test shows which opening works. Each version is a named MP4 that you upload to your ad platform. Use invideo for this when you want every variant to come from one master timeline: each hook lives on its own branch, a fix to the master body is one edit, and you can open any branch in the editor to check it. Making ad variants is ordinary marketing work, and your agent does it. The agent never uploads, switches on or pays for an ad. You run the test in the ad platform. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Here is my master ad and 12 hooks in hooks.txt, one per line. Make one branch per hook. Change the first text line to the hook, and use the first clip listed next to each hook. Export each one with the file name serum-h01 to serum-h12 and give me the list. ``` In a chat app, you paste the hooks into the chat. In a terminal, the agent reads a text or CSV file you name. #### What you need A good master and a clean list make the test easy to read. - **A master ad.** A finished timeline in invideo, with the hook as its own text clip in the first seconds. - **The hooks.** One per line: the words, and the first clip for that hook if it changes. - **Hook clips.** Any new opening clips, as MP4 or MOV, or stock you want to search. - **A naming scheme.** A short ad name and a hook number, such as `serum-h01`. Add the angle if you track it, such as `serum-h01-price`. #### Steps The agent keeps main untouched. Every hook is a branch off the master. The agent reads the timeline with `get_timeline` in `mode` window. It finds the hook text clip and the first video clip, and notes their ids and frames. Expected result: the ids of the hook text and the first clip, and the `state_token`. The agent saves a checkpoint with `timeline_history` `checkpoint`, titled "master". Each branch then starts from it: `create_branch` with `checkpoint_slug` set to that checkpoint, or `invideo branch new --checkpoint` on the CLI. Without it, a branch starts from the current state of the branch you are on. Expected result: the checkpoint shows in `timeline_history` `list`. For each hook, the agent runs `timeline_history` `create_branch` with a name such as `serum-h01`. Expected result: a branch URL per hook, of the shape `…/tree/serum-h01/seq-9.1`. On each branch, the agent changes the hook words with `set_text` on the hook clip. Expected result: the new hook on screen in the first seconds. When a hook has its own opening clip, the agent adds the file with `add_media`. It puts it in place of the first clip with `place_media` in `mode` replace, which keeps the old clip's length. Expected result: the new clip first, and the body of the ad unchanged. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `seedance_2_5.frames`. It calls `generate` with `dry_run: true` and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL, which the agent reads with `read` and places first with `place_media`. The agent runs `capture` at the first and the third second of each branch, and `check_timeline`. It checks that the hook is readable and clear of the app buttons. Then it runs `export` on each branch URL with `format` video, `file_name` set from the naming scheme, and its own `idempotency_key`. Expected result: one export card per hook, each with status `completed`, and a list of names for you. The same job from a terminal, for one hook. The agent repeats it for each line of the file. ```bash invideo agent register --name export INVIDEO_AS= invideo edit show --mode window --start-seconds 0 \ --end-seconds 5 invideo branch checkpoint --title "master" --token invideo edit show --json invideo branch list invideo branch new --name serum-h01 --token \ --checkpoint invideo gen models --query "short opening shot for an ad" invideo gen model --model seedance_2_5.frames invideo gen run --model seedance_2_5.frames --dry-run \ -i prompt="close-up, serum drop on skin" -i aspect_ratio=9:16 -i duration=4 invideo gen run --model seedance_2_5.frames \ --max-credits --idempotency-key serum-h01-clip \ -i prompt="close-up, serum drop on skin" -i aspect_ratio=9:16 -i duration=4 invideo edit show --json invideo edit change --timeline T1 --token \ --operations @hook-01.json invideo edit capture --at 1,3 --out ./frames/h01 invideo edit export --format video --quality 1080 \ --file-name serum-h01 --idempotency-key serum-h01-v1 --json invideo status --wait invideo notebook show --out ./exports mv ./exports/export.mp4 ./exports/serum-h01.mp4 ``` Where the values come from: `` is the master's timeline URL, from `invideo edit new`. `` comes from `invideo project new`. `` is the name you choose in `invideo agent register`, and `` is a notebook page from `invideo notebook show `. `` comes from the `invideo edit show` right before each command: the first one, then the one after the checkpoint, then the one on the branch, because the main token is stale there. `` is the name `invideo branch list` gives the checkpoint. `` is the `branch_url` that `invideo branch new` returns. `` is the dry run's `estimated_credits`. `` is `.sequences[0]` of what the export returns. The ops file `hook-01.json` is a bare list: the `operations` list of the MCP call below. The key MCP call on one branch changes the hook line and swaps the first clip. `` in the prompt above is the master's URL. Here `` is the branch's token from `get_timeline`, the ids `c9` and `c1` come from the same read, and `` is the hook clip's sequence URL from `add_media` or from the generation. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "set_text", "clip": "c9", "text": "I stopped buying three products for this one" }, { "op": "place_media", "asset": "", "track": "V1", "at_f": 0, "source_start_seconds": 0, "source_end_seconds": 3, "mode": "replace", "replace_clip": "c1", "linked_audio": false } ] } ``` The export for that branch sets the file name in `options`. The name shows on the card. A file saved with `invideo notebook show` is still `export.mp4`. ```json { "url": "", "format": "video", "idempotency_key": "serum-h01-v1", "options": { "quality": "1080", "file_name": "serum-h01" } } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** branches, checkpoints, the text and clip changes, the checks and every export. - **Costs credits:** a stock clip for a new opening, and any generated opening clip or voice line. A list of hooks takes a few minutes of edits, plus the export time for each. For a long list, the agent runs it in parts and reports after each part. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are a stale token between branches, or a hook clip that changes the ad's length. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The exports folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./exports`. | | You want all variants side by side on one branch | Copy the timeline with `duplicate_timeline` instead, one copy per hook. | | The hook needs a spoken line | Make it with `elevenlabs_text_to_speech.elevenlabs_tts_v4` and a `voice_id` from `search_library` in `elevenlabs_text_to_speech_voices`, priced and run the same way as a clip. | | A new clip must push the rest of the ad later | Use `insert_media` with `ripple` true instead of `place_media`. | | CLI exit 3, or a stale `expected_state_token` | Each branch has its own token. Read that branch with `get_timeline` before the edit. | | `set_text` refused on a caption clip | The caption has several slides. Use `set_caption_slide_text` for the slide with the hook. | | The new first clip is longer and the ad grew | Use `place_media` in `mode` replace, which keeps the old clip's length. | | Two exports have the same name | Give each export its own `file_name` and its own `idempotency_key`. | | `timeout` on an export | Do not export again. Read the export card URL, or run `invideo status`. | | Avoid: editing main for each hook | Instead: one branch per hook, off the master checkpoint. | | Avoid: rebuilding the whole ad per hook | Instead: change only the hook text and the first clip. | #### Prompts to try Each prompt is a real variation of the job. ```text Make 20 hook variants of my ad from hooks.csv. Columns: hook, first clip. Name them acme-h01 to acme-h20. Run it in parts of five and show me frames after each part. ``` ```text For my 3 best hooks, make a 9:16 and a 1:1 version each, so 6 files. Name them with the hook number and the shape. ``` ```text Find a stock clip for each of these 10 hooks, put it first, and tell me the price of the stock before you add it. ``` #### When to use something else invideo makes the variants. It does not run the test, split the budget or read the results. Use your ad platform's own testing tool, such as Meta Ads Manager or TikTok Ads Manager, and match the file names in its report. #### Related - [Make performance ads for Meta, TikTok and YouTube, named and iterated from results](/how-to/marketing/performance-ads) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Make a UGC ad from product photos with an AI actor](/how-to/marketing/ugc-ad-with-ai-actor) - [Localize a winning ad with the same voice and lip-sync](/how-to/marketing/localize-a-winning-ad) - [Turn a CSV into many videos with a script](/how-to/developers/csv-to-videos) ### Stock-footage commercial Source: https://docs.invideo.io/how-to/marketing/stock-footage-commercial.md A promo video, or business commercial, from licensed stock footage, a voiceover and your text, cut to 15, 60 and 120 seconds on three branches. You get a commercial for your business, also called a promo video or explainer ad, built from licensed stock footage. It has a voiceover, your business name and offer on screen, music, and a call to action. You get it in three lengths, 15, 60 and 120 seconds, each on its own branch. Use invideo for this when you have no footage of your own: your agent searches stock video, images and music that are licensed for the video, and you can swap any shot on the timeline after the first cut. This is ordinary marketing work for your own business. The agent makes the video. You publish it, and you choose where it runs. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a commercial for my bakery, Rise and Crumb, in Austin. Fresh bread every morning, custom cakes, open 7am to 3pm. Use stock footage and warm music, a friendly voice, and end with my address and site. Make 15, 60 and 120 second versions. Tell me the stock price first. ``` The chat-app path and the terminal path are the same here. You type the facts, and the agent finds the media. In a terminal it can also read your facts from a file. #### What you need The agent writes only what you give it. Bring the facts. - **Your business facts.** The name, what you sell, what makes you different, the offer, and the call to action. - **The words to show.** The address, the phone number or the site, exactly as they should appear. - **Your logo, if you have one.** A PNG with a transparent background. - **The shape.** 16:9 for YouTube or a site, 9:16 for Reels and TikTok, 1:1 for feeds. - **The mood.** Warm, upbeat, calm or bold, for the shots, the voice and the music. #### Steps The agent builds the longest version first, then cuts it down on branches. The agent writes three scripts from your facts: a short one for 15 seconds, a full one for 60 and a longer one for 120 seconds. Each ends with the call to action. It shows you the scripts first. Expected result: three scripts you approve. The agent runs `search_library` in `stock_video` for each line of the script, and in `stock_image` and `stock_music` where it needs them. It looks closer at a result with `media` `video.frames` and the `stock` id. Searching is free. Expected result: a shot list with a stock id per line, and a music track. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. A voice id works only with its own model, so the agent picks the voice with `search_library` in `elevenlabs_text_to_speech_voices`. It calls `generate` with `dry_run: true`, the script as `prompt` and the `voice_id`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It does this once per script, with one key per script. Expected result: three sequence URLs, one per length, which the agent reads with `read`. The agent makes a timeline with `new_timeline` and a branch named `120s` with `timeline_history`. It adds each chosen stock result with `add_media` and the `stock` id, which charges its cost. It places shots with `place_media` along the voice and adds your words with `add_text`. Expected result: a full commercial with every shot on the voice line it fits. The agent makes branches named `60s` and `15s` with `timeline_history` `create_branch`. On each, it puts that length's voice in place with `place_media` in `mode` replace, removes shots with `delete_clip`, and shortens the rest with `trim_clip`. Expected result: three branches whose lengths match their names. The agent places the music with `place_media` and sets it under the voice with `set_audio_gain`. It fades the music out with `set_audio_fades`. It adds your logo with `insert_media` and the address and site on the last seconds with `add_text`. Expected result: music under the voice, and an end card with your details. The agent runs `capture` at every text and at the end card of each branch, and `check_timeline`. It checks that your address and phone number read exactly as you gave them. Then it runs `export` on each branch URL with `format` video and a `file_name` such as `rise-and-crumb_60s`. Expected result: three export cards with status `completed`. The same job from a terminal: ```bash invideo project new --title "Rise and Crumb commercial" invideo agent register --name export INVIDEO_AS= invideo library search --library stock_video \ --query "baker pulling fresh bread from oven" invideo library search --library stock_music \ --query "warm acoustic" invideo media video.frames --stock --at 1,3,5 invideo gen models --query "friendly voiceover from a script" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --dry-run -i prompt=@script-60.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key crumb-voice-60-v1 \ -i prompt=@script-60.txt -i voice_id= invideo edit new --name "Rise and Crumb 120s" invideo asset add --stock invideo edit show --json invideo branch new --name 60s --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @cut-60.json invideo edit capture --at 2,20,40,58 --out ./frames/60s invideo edit export --format video --quality 1080 \ --file-name rise-and-crumb_60s --json invideo status --wait invideo notebook show --out ./out/60s mv ./out/60s/export.mp4 ./out/60s/rise-and-crumb_60s.mp4 ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`, and `` is a notebook page from `invideo notebook show `. `` comes from the library search, and `` from `invideo library search` in `elevenlabs_text_to_speech_voices`. `` is the dry run's `estimated_credits`. `` comes from `invideo edit show` on the edit, and on the branch from `invideo edit show `. The main token is stale there. `` is the `branch_url` that `invideo branch new` returns. `` is `.sequences[0]` of what the export returns. `invideo status` does not download, and the saved file is always `export.mp4`. The ops file `cut-60.json` is a bare list: the `operations` list of the MCP call below. The key MCP call on the `60s` branch removes a shot, shortens another and adds the end card. At 30 frames a second, frame 1800 is the 60 second mark. `` here is the branch's token from `get_timeline`, and the clip ids come from the same read. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "delete_clip", "clip": "c6", "mode": "close_gap", "linked": true }, { "op": "trim_clip", "clip": "c7", "edge": "tail", "from_f": 1290, "to_f": 1200, "mode": "close_gap", "linked": true }, { "op": "add_text", "track": "V2", "start_f": 1650, "end_f": 1800, "text": "Rise and Crumb\n214 Oak Street, Austin\nriseandcrumb.com", "style": { "font_size": 64, "align": "center", "color": "#ffffff" } } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** searching stock, the edits, the three branches and every export. - **Looking at stock with `media`:** the dry run shows the price before anything starts. - **Costs credits:** each stock clip, image or song when the agent adds it, and the voice. iStock results use one of your workspace's iStock licenses. One commercial in three lengths takes under an hour, most of it on the script and your review of the shots. See [Credits and what they cost](/account/credits) for prices. #### Rights Stock you add through invideo is licensed for use in your video. The agent looks at low-resolution previews. Your export uses the clean file. For what you may do with stock, music and generated media, read [Licensing and commercial use](/account/commercial-use). #### If something goes wrong Most problems are a shot that does not fit the line, or a version that runs long. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | A version runs longer than its name | Read it with `get_timeline` and trim the last clips with `trim_clip`. | | `trim_clip` refused as stale | `from_f` must be the edge as last read. Read the clip again. | | A stock shot shows a competitor's logo | Pick another result with `search_library`. | | The phone number on screen is wrong | The agent types what you gave. Send the right number and it fixes it with `set_text`. | | CLI exit 3 on the branch | The token is the main timeline's. Run `invideo edit show ` and use its token. | | The download folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./out/60s`. | | CLI exit 5 | A credit limit. Use fewer stock clips, or reuse a clip. | | Avoid: adding every search result to look at it | Instead: look with `media` and the `stock` id, then add the ones you pick. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 30 second vertical promo for my gym's January offer: first month free. Energetic stock, bold text, no voice, a fast beat. ``` ```text Make a 60 second commercial for my plumbing business with a calm male voice. Use my logo ./logo.png and my real van photo ./van.jpg at the end. ``` ```text Use my 120 second cafe commercial and make a Spanish version on a new branch, with a Spanish voice and the same shots. ``` #### When to use something else For a commercial with your own staff, shop and customers, film them on a phone and bring the clips in with `add_media`. Real footage often wins over stock for a local business. For airtime on TV, the station sets its own delivery rules. invideo exports a 1080p MP4. Ask the station what it needs, and use a desktop editor or a post house for broadcast formats. #### Related - [Make monthly videos for a dentist, gym, restaurant or home service](/how-to/marketing/local-business-monthly-videos) - [Make a brand ad film from a brief, with generated shots and your real product](/how-to/marketing/brand-ad-film) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Licensing and commercial use](/account/commercial-use) - [Check your video before you say it is done](/how-to/check-your-video) ### Make an App Store preview video at Apple's sizes Source: https://docs.invideo.io/how-to/marketing/app-store-preview.md An App Store preview, or app preview video, cut from your screen recording at Apple's device sizes, with text overlays and a pre-flight check. You get an App Store preview, also called an app preview video or App Store trailer, cut from your own screen recordings. It is sized for each iPhone and iPad display Apple asks for, uses text to explain each step because previews start muted, and passes a pre-flight check before you upload it. Use invideo for this when you need the same preview at several device sizes: your agent makes one timeline per size from one cut, checks each against Apple's spec, and you change a line of text in all of them after. This is ordinary marketing work for your own app. The agent makes the files. You upload them in App Store Connect, and Apple reviews them. The agent never uploads or submits them. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make an App Store preview from my screen recording ./capture.mov. Cut it to 25 seconds: onboarding, the main feature, the result. Add a short text line for each part, no prices, music I can use. Make the iPhone 886x1920 and the iPad 1200x1600 sizes, and check each file against Apple's spec before you say it is done. ``` In a chat app, you drag the recording into the project in invideo. In a terminal, you name the file and the agent uploads it. #### What you need Apple's rules decide most of this list. Read them on Apple's App preview specifications page and the App previews guidelines. They change, so the agent checks them before each job. - **Screen recordings from the device.** Record on the iPhone or iPad, or in the Simulator, at the device's own resolution. Footage must come from the app itself. - **The device sizes you ship.** Apple lists one pixel size per display family, portrait and landscape. - **The text for each step.** Short lines that say what the person sees. No prices. - **A disclosure, if it applies.** If a feature needs a purchase, a subscription or a sign-in, say so on screen or on the end frame. - **Music you have the rights to.** Stock music from invideo, or your own licensed track. These are Apple's sizes for the common display families: | Display | Portrait | Landscape | | --- | --- | --- | | iPhone with Dynamic Island or Face ID | 886 x 1920 | 1920 x 886 | | iPhone with Home Button, large | 1080 x 1920 | 1920 x 1080 | | iPad, 13 and 11 inch | 1200 x 1600 | 1600 x 1200 | Apple asks for a preview between 15 and 30 seconds long, at 30 frames a second or less, as H.264 in MP4, M4V or MOV, with stereo AAC sound. #### Steps The agent cuts once on the main size, then copies the cut for each other size. The agent makes a timeline with `new_timeline` and sets its size and rate with `set_timeline_settings`, for example 886 by 1920 at 30 fps. It creates a branch with `timeline_history`. Expected result: an empty timeline at Apple's size. The agent uploads the recording with `start_upload` and `add_media`. It runs `media` `metadata` for its size and frame rate, and `video.frames` to see the screens. Expected result: a sequence URL, and a note of where each part of the app appears. The agent places the parts you want with `place_media`, in story order, and trims them with `trim_clip`. It keeps the app's screen at its own size with `fill_frame`, and does not zoom far into the UI. Expected result: a cut between 15 and 30 seconds, with only app footage on screen. The agent adds one short line per step with `add_text`, large enough to read on a phone. It adds stock music with `search_library` in `stock_music` and `add_media`. It adds a disclosure line on the end frame when a feature needs a purchase or a sign-in. Expected result: text that explains the preview with the sound off. The agent copies the timeline with `duplicate_timeline`, one copy per size, and sets each copy's size with `set_timeline_settings`. It checks each clip's framing with `fill_frame` or `fit_frame`, and moves text with `set_position`. Expected result: one timeline per size, each with the same cut. The agent runs `check_timeline` and `capture` on each timeline at every text line and at the end frame. It looks for text cut at the edge, any price, any date, and anything outside the app. Expected result: frames with no problems. The agent runs `export` with `format` video, `quality` 1080, `fps` 30 and `audio_format` aac, then runs `media` `metadata` on each export card's URL. It checks the width, the height, the length and the frame rate against Apple's spec. The card is a sequence, so no re-upload is needed. Expected result: one export card per size, with its numbers read back. The same job from a terminal: ```bash invideo project new --title "App Store preview" invideo agent register --name export INVIDEO_AS= invideo edit new --name "iPhone 886x1920" \ --width 886 --height 1920 --fps 30 invideo asset upload ./capture.mov invideo media metadata invideo edit show --json invideo branch new --name preview-v1 --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @cut.json invideo edit check invideo edit capture --at 1,6,12,18,24 --out ./frames invideo edit export --format video --quality 1080 --fps 30 \ --audio-format aac --json invideo status --wait invideo media metadata invideo notebook show --out ./iphone mv ./iphone/export.mp4 ./iphone/preview_iphone.mp4 ``` Where the values come from: - `` comes from `invideo project new`. `` comes from `invideo edit new`. `` is the name you choose in `invideo agent register`. - `` is the `url` that `invideo asset upload` returns for the recording. - `` comes from `invideo edit show `, and on the branch from `invideo edit show `; the main token is stale there. `` is the `.branch_url` that `invideo branch new` returns. - `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves `./iphone/export.mp4`. - The file `./cut.json` holds a bare list of operations, the same list the MCP path sends in `operations`. - In the MCP call below, `` is the timeline's URL from `new_timeline`, and `` comes from `get_timeline`. The key MCP call makes the iPad copy from the iPhone cut and sets its size. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "duplicate_timeline", "timeline": "T1", "name": "iPad 1200x1600" } ] } ``` In the next call, on the new timeline's id from the result, the agent sends `{ "op": "set_timeline_settings", "timeline": "T2", "width": 1200, "height": 1600, "fps": 30 }`. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the upload, the cut, the copies per size, the text, the checks and every export. - **Costs credits:** stock music, and a voiceover if you add one. A preview at two or three sizes takes under an hour, most of it on choosing the parts of the recording. See [Credits and what they cost](/account/credits) for prices. #### What invideo cannot check invideo checks the file: its size, length, frame rate and what is in the frames. It cannot tell you whether Apple will accept the preview. Apple's App Review decides that, and it reads the content as well as the file. If Apple rejects the preview, App Store Connect says why, and the agent fixes that on the timeline. #### If something goes wrong Most rejections come from what is in the frames, not from the file. | Symptom | Fix | | --- | --- | | Apple rejects hands, a phone or a person in the shot | Use only footage captured from the app. Remove the clip with `delete_clip`. | | Apple rejects a price on screen | Remove the text with `delete_clip`, or change it with `set_text`. Prices vary by region. | | The file's width or height does not match the spec | Read it with `media` `metadata`. Fix the timeline size with `set_timeline_settings` and export again. | | A portrait file is smaller than Apple's size | `quality` sets the file's height, and 1080 is its largest value. Scale the file to the exact size with `media` `video.upscale` on the export card, then check it with `metadata`. Or scale it outside invideo with ffmpeg or HandBrake. | | The file is too long or too short | Trim with `trim_clip`, or export a range with `start` and `end`. | | Text is hard to read on a phone | Make it larger with `set_text_style`, and `capture` again. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | CLI exit 3 on the branch | The token is from main. Run `invideo edit show ` and use its `state_token`. | | The saved file is called `./iphone/export.mp4` | `notebook show` always saves `./iphone/export.mp4`. Rename it per size. | | CLI exit 2 | The request cannot be done as asked. Read the error and the help for that command. | | Avoid: zooming deep into the UI | Instead: show the screen at its own size, and explain with text. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a landscape App Store preview for my iPad game from ./play.mov. Show more gameplay than menus, 1600x1200, epic music, no prices. ``` ```text My preview was rejected for showing a date. Find the date in the text, remove it, and export the three sizes again. ``` ```text Make my iPhone preview in German and Japanese. Same cut, translated text lines, one branch per language. ``` #### When to use something else invideo exports MP4, and `quality` sets its height. Apple's portrait sizes are taller than the largest `quality` value, so the portrait files always need a scale step after export: `media` `video.upscale`, or ffmpeg or HandBrake for an exact pixel size. For ProRes 422, finish the file in a desktop editor such as Final Cut Pro. invideo does not record your screen. Use the iPhone's screen recording, Xcode's Simulator recording, or QuickTime Player with the device plugged in. #### Related - [Make a launch video from your product URL and screenshots](/how-to/marketing/launch-video) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Check your video before you say it is done](/how-to/check-your-video) - [Licensing and commercial use](/account/commercial-use) - [MCP tools](/reference/mcp-tools) ### Turn a product photo into a video without redrawing the product Source: https://docs.invideo.io/how-to/marketing/product-photo-to-video.md A product video, or image-to-video ad, from your product photos, where the label, shape and color stay exactly as in your photo. You get a short product video, also called an image-to-video ad or product animation, from your product photos. The camera moves, the background lives, and the product looks exactly like the one you sell. The label, the shape and the color come from your photo, not from a model's guess. Use invideo for this when the product must stay exact: your agent keeps your real photo on the timeline for every shot where the label shows, moves it with free effects and keyframes, and uses a model only where a redraw does no harm. This is ordinary product marketing work, and the agent does it. You choose where the video runs and you publish it. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 12 second vertical product video from ./bottle.jpg and ./bottle-side.jpg. Cut the bottle out, put it on a soft studio background, a slow push in, then a lifestyle shot made with a model. The label must never change. Tell me the price before you generate. ``` In a chat app, you drag the photos into the project in invideo. In a terminal, you name the files and the agent uploads them. #### What you need The photo is the product. A better photo gives a better video. - **Product photos.** Sharp, well lit, at a high resolution. A front shot and one or two angles. - **A clean background, if you have one.** A plain backdrop makes the cutout clean. - **The shots you want.** A push in, a turn, a lifestyle scene, the product in a hand. - **The shape.** 9:16 for Reels and TikTok, 1:1 or 4:5 for feeds, 16:9 for a store page. - **The words.** The product name, one claim and the call to action. #### Steps The agent sorts each shot into two kinds: exact shots that use your photo, and mood shots that may use a model. The agent makes a project with `new_project`, a timeline with `new_timeline`, and a branch with `timeline_history`. It uploads each photo with `start_upload` and `add_media`. Expected result: a sequence URL per photo. The agent runs `media` `image.removeBackground` on the front photo, with `dry_run` first, then `max_credits` set to the price and an `idempotency_key`. The default model is `bria_bg_remove`. `birefnet_bg_remove` is the other choice. Expected result: a cutout of the product as a new sequence. The agent looks at it with `read`, which returns the image, and checks the edges. The agent places a background on `V1` and the cutout above it with `insert_media`. It adds the `dynamic_zoom` effect with `add_effect` for a slow push. For a turn or a slide, it uses `set_keyframes` on `rotation`, or a lane from `add_keyframe_lane` on `position_x` or `zoom_x` and `zoom_y`, filled with `add_keyframes`. This is free, and every pixel of the product is your photo. Expected result: the product moves, and the label is sharp. The agent runs `find_models` with the shot in words, picks a model, and reads its inputs with `get_model`. For a lifestyle scene, a good pick is `seedance_2_5.r2v` with your photos in `reference_images`. For a move from one photo, good picks are `kling_v4.kling_v4_frames` or `wan_27_alibaba.wan_27_i2v` with the photo as the first frame, or `camera_moves.image` for a set camera move. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It sees a thread URL and, when the shot lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. Expected result: a new video sequence per shot. A model redraws the product, so these shots keep the product small, moving or out of focus. The agent runs `capture` on every generated shot where the product shows, and compares each frame with your photo: the label text, the logo, the color, the cap, the shape. It replaces any shot where the product changed with an exact shot from your photo. Expected result: a product that matches your photo in every frame. The agent adds the product name and claim with `add_text`, and music with `search_library` in `stock_music` and `add_media`. Expected result: words on screen and music under the video. The agent runs `capture` at each shot and each text, and `check_timeline`. Then it runs `export` with `format` video. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Bottle product video" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Bottle 9x16" --width 1080 --height 1920 invideo asset upload ./bottle.jpg ./bottle-side.jpg invideo media image.removeBackground --dry-run invideo media image.removeBackground \ --max-credits --idempotency-key bottle-cutout invideo gen models --query "product lifestyle shot from photos" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ --input r2v-inputs.json invideo gen run --model seedance_2_5.r2v \ --max-credits --idempotency-key bottle-life-1 \ --input r2v-inputs.json invideo status --wait invideo edit show --json invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 1,4,7,10 --out ./frames invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`. `` is the `url` that `invideo asset upload` returns for the front photo. `` is a notebook page from `invideo notebook show `. `` is each dry run's `estimated_credits`. `` is the `url` the paid `gen run` returns. `` comes from `invideo edit show`. `` is `.sequences[0]` of what the export returns. `invideo status` does not download; `invideo notebook show` saves the file as `export.mp4`. The file `r2v-inputs.json` holds the model's inputs alone, as `get_model` lists them, with no `inputs` wrapper. The dry run and the paid run pass the same file, so the run that spends is the run that was priced. ```json { "prompt": "The bottle on a sunny kitchen counter, slow push in", "reference_images": ["", ""], "aspect_ratio": "9:16", "duration": 6 } ``` `` is the upload URL of the side photo. The key MCP call cuts the product out. It is a dry run, so it returns the price and starts nothing. ```json { "url": "", "op": "image.removeBackground", "model": "bria_bg_remove", "dry_run": true } ``` The agent then sends the same call with `dry_run` false, `max_credits` at the price, and an `idempotency_key`. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** uploads, the exact shots with effects and keyframes, text, the checks and the export. - **Costs credits:** the background removal, each model shot, and stock music. Most video models charge by the second, so short mood shots cost less. A short product video takes under an hour, most of it on the model shots and the check. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are a model that redrew the label, or a rough cutout edge. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The label text is wrong in a model shot | Use an exact shot from your photo for that moment. Models redraw text. | | The color shifted in a model shot | Compare with `capture`. Replace the shot, or keep the product small in it. | | The cutout has a halo | Try `birefnet_bg_remove`, or start from a photo on a plain backdrop. | | `fill_frame` refused on the cutout | Its zoom is animated. Set the size with `set_zoom` before the lane. | | `set_keyframes` refused for zoom | It takes `opacity` and `rotation` only. Use `add_keyframe_lane` and `add_keyframes`. | | The download folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./out`. | | `inputs is not an input of this model` | `r2v-inputs.json` has an `inputs` wrapper. Keep only the model's inputs in the file. | | CLI exit 5 | A credit limit. Use more exact shots, which are free. | | Avoid: the agent says the product "should look the same" | Instead: it captures frames and compares them with your photo. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a 6 second 1:1 loop of my sneaker ./shoe.png turning slowly on a pastel background. No model, only my photo. ``` ```text Make three 8 second lifestyle shots of my candle from these photos, kitchen, bedroom and patio, then check the label in every frame. ``` ```text Make a 15 second Amazon-style video from my 5 product photos: a push on each, a feature line on each, white background, no music. ``` #### When to use something else invideo does not turn a photo into a 3D model you can spin freely. For a true 360 view, shoot the product on a turntable, or use a 3D tool, and bring the clip in. For the product photos themselves, a studio shoot gives the cleanest result. If you need new photos made from your product, an image model can help, but check the label the same way. #### Related - [Make a UGC ad from product photos with an AI actor](/how-to/marketing/ugc-ad-with-ai-actor) - [Make an Amazon listing or Sponsored Brands video ready for moderation](/how-to/marketing/amazon-listing-video) - [Make a Shopify and TikTok Shop product video that follows the no-stills rule](/how-to/marketing/shopify-and-tiktok-shop-video) - [Animate a photo, or make a pet memorial from one picture](/how-to/personal/animate-a-photo) - [Check your video before you say it is done](/how-to/check-your-video) ### Turn listing photos into a vertical real-estate reel Source: https://docs.invideo.io/how-to/marketing/real-estate-reel.md A vertical real-estate reel, or listing video, from your listing photos: slow pans, price and address on screen, music, and an upscaled 4K copy. You get a vertical real-estate reel, also called a listing video or property tour reel, from the photos of a listing. Each room gets a slow pan or push, the price and the address sit on screen, and music plays under it. You get a 1080p MP4 for Reels and TikTok, and an upscaled 4K copy when the listing site or the seller asks for one. Use invideo for this when you list homes every week: your agent builds the first reel, then makes each new listing on a copy of it, so you only swap the photos, the price and the address. This is ordinary marketing work for a listing you represent. The agent makes the video. You post it and you publish the listing. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 30 second vertical reel from the listing photos in ./42-elm. Front of the house first, then kitchen, living room, bedrooms, yard. Slow pans, the text "€685,000" and "42 Elm Street, Dublin", calm music. Export 1080p, then make a 4K copy and tell me its price first. ``` In a chat app, you drag the photos into the project in invideo. In a terminal, you name the folder and the agent uploads it. #### What you need The agent puts on screen only what you give it, word for word. - **The listing photos.** JPG or PNG, wide shots, in the order of the tour. Use enough photos to show each room once. - **The text to show.** The price, the address, beds and baths, and your name or brokerage, exactly as they should read. - **Your logo or headshot, if you use one.** A PNG. - **The music mood.** Calm, upbeat or luxury. - **The length.** 15, 30 or 60 seconds. - **Whether you need an upscaled 4K copy.** Many listing sites take 1080p. Ask the site. #### Steps The agent builds one reel, then copies it for each new listing. ##### Build the first reel The agent builds one reel on a branch and checks it before export. The agent makes a project with `new_project`, a 1080 by 1920 timeline with `new_timeline`, and a branch with `timeline_history`. It uploads the photos with `start_upload` and `add_media`. Expected result: a sequence URL per photo. The agent places each photo with `insert_media` in tour order, and fills the vertical frame with `fill_frame`. A wide photo then shows its middle. Expected result: no black bars, one photo after another. On each photo, the agent adds the `dynamic_zoom` effect with `add_effect`. Then, in a second `edit_timeline` call with the effect's id from `get_timeline`, it sets the start and end points with `set_effect_parameter` so the frame slides across the room. Expected result: each room moves slowly, from one side to the other. The agent adds the price and the address with `add_text` on the first photo, and beds and baths on a later one. It types the words you gave, exactly. It styles them with `set_text_style`. Expected result: readable text in the middle of the frame, clear of the app buttons. The agent runs `find_models` with the mood in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_music_v2_5_instrumental`. It calls `generate` with `dry_run: true`, a `prompt` and a `duration` that matches the reel, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL, which the agent reads with `read` and places on `A2`. The agent reads the beats with `media` `audio.beats`, moves the cuts to them with `trim_clip`, and adds soft cuts with `add_transition`, such as `fade` or `slide`. Expected result: the photos change on the beat. The agent runs `capture` at the price, the address and each room, and `check_timeline`. It checks the price and the address letter by letter against what you gave. Then it runs `export` with `format` video and `quality` 1080. Expected result: an export card with status `completed`. ##### Upscale to 4K and reuse the reel The agent upscales the export, then reuses the reel for the next home. `export` makes 1080p. For 4K, the agent runs `media` `video.upscale` on the export card's URL, with `byteplus_vod_upscale` as the `model` and `target_resolution` 4k in `inputs`. The card is a sequence, so no re-upload is needed. It runs `dry_run` first and tells you the price. Then it runs the same call with `max_credits` set to that price and an `idempotency_key`. Upscales charge by each second of the source. Expected result: a 4K video as a new sequence. For the next listing, the agent copies the timeline with `duplicate_timeline` and names it after the address. It swaps each photo with `place_media` in `mode` replace, and changes the words with `set_text`. Expected result: a new reel with the same style, ready to check. The agent runs `capture` on the copy at the price, the address and each room, and `check_timeline`. Then it runs `export` with the copy's `timeline_id`. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Listings" invideo agent register --name export INVIDEO_AS= invideo edit new --name "42 Elm" --width 1080 --height 1920 invideo asset upload ./42-elm/*.jpg invideo gen models --query "calm instrumental music bed" invideo gen model --model elevenlabs_music_v2_5_instrumental invideo gen run --model elevenlabs_music_v2_5_instrumental \ --dry-run -i prompt="calm piano, warm, slow" -i duration=30 invideo gen run --model elevenlabs_music_v2_5_instrumental \ --max-credits --idempotency-key 42-elm-music \ -i prompt="calm piano, warm, slow" -i duration=30 invideo edit show --json invideo edit change --timeline T1 --token \ --operations @reel-ops.json invideo edit capture --at 1,5,10,20,29 --out ./frames invideo edit export --format video --quality 1080 \ --file-name 42-elm-street --json invideo status --wait invideo notebook show --out ./out invideo media video.upscale --model byteplus_vod_upscale \ --inputs '{"target_resolution": "4k"}' --dry-run invideo media video.upscale --model byteplus_vod_upscale \ --inputs '{"target_resolution": "4k"}' \ --max-credits --idempotency-key 42-elm-4k ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`. `` is a notebook page from `invideo notebook show `. `` comes from `invideo edit show`. `` is each dry run's `estimated_credits`. `` is `.sequences[0]` of what the export returns. `invideo status` does not download. `invideo notebook show` saves the file as `export.mp4`, whatever `--file-name` says, so the agent renames it to `42-elm-street.mp4`. The ops file `reel-ops.json` is a bare list: the `operations` list of the MCP call below. The key MCP call places a photo, fills the frame, adds the pan and the price. `` is the timeline URL from `new_timeline`, `` comes from `get_timeline`, and `` is the sequence URL `add_media` returns for the front photo. The new clip's id `c1` can be used later in the same call. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "insert_media", "asset": "", "track": "V1", "at_f": 0, "ripple": true }, { "op": "fill_frame", "clip": "c1" }, { "op": "add_effect", "clip": "c1", "effect": "dynamic_zoom" }, { "op": "add_text", "track": "V2", "start_f": 15, "end_f": 105, "text": "€685,000\n42 Elm Street, Dublin", "style": { "font_size": 72, "align": "center", "color": "#ffffff", "shadow": true } } ] } ``` The 4K upscale is a `media` call on the export card, with `` from the export result's `.sequences[0]`: ```json { "url": "", "op": "video.upscale", "model": "byteplus_vod_upscale", "inputs": { "target_resolution": "4k" }, "dry_run": true } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** uploads, the pans, the text, the beats, the copies per listing, the checks and the 1080p export. - **Costs credits:** the generated music or paid stock music, and the 4K upscale. The upscale charges by each second of the video, so a shorter reel costs less. The first reel takes under an hour. Each copy for a new listing takes a few minutes, plus the export. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are a room cut off by the vertical crop, or a typo in the price. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | You want stock music instead | Run `search_library` in `stock_music`, and add the pick with `add_media`. | | You want a hand-made pan | Add a lane with `add_keyframe_lane` on `position_x`, and fill it with `add_keyframes`. | | The best part of a wide room is cut off | Change the pan's start and end points, or move the photo with `set_position`. | | `fill_frame` refused | The clip's zoom is animated. Remove the lane, fill the frame, then add the lane again. | | The price or address is wrong | The agent types what you gave. Send the right text and it fixes it with `set_text`. | | Text sits under the app's buttons | Move it with `set_position` toward the middle, and `capture` again. | | The 4K copy looks soft | Upscaling cannot add real detail to a small photo. Start from full-size photos. | | The download folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./out`. | | `timeout` on the upscale | Do not start it again. `read` the sequence URL or call `status`. | | Avoid: the agent writes its own description of the home | Instead: it shows only the words you gave, so the listing stays accurate. | #### Prompts to try Each prompt is a real variation of the job. ```text Copy my 42 Elm reel for 7 Birch Lane. Photos in ./7-birch, price €540,000, 3 beds 2 baths. Same music and style. ``` ```text Make a 15 second "Sold" reel from the front photo of 42 Elm with a bold "SOLD" title and my headshot ./me.png at the end. ``` ```text Make an open house reel for Saturday 1 to 4pm from ./12-oak, with the date and time on the last photo, and a 16:9 copy for YouTube. ``` #### When to use something else For a walk-through video, film it on a phone gimbal or hire a videographer, then bring the clips in. Photos with pans are not a real walk-through. invideo does not make virtual staging or floor plans. Use a staging or floor plan tool, then bring the images in with `add_media`. Check your local rules on showing staged rooms. #### Related - [Make monthly videos for a dentist, gym, restaurant or home service](/how-to/marketing/local-business-monthly-videos) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Make a stock-footage commercial for your business, in short and long cuts](/how-to/marketing/stock-footage-commercial) - [Make a photo slideshow for any occasion: anniversary, graduation, retirement, baby's first year, family recap](/how-to/personal/occasion-slideshow) - [Check your video before you say it is done](/how-to/check-your-video) ### Finish an AI clip from Higgsfield Source: https://docs.invideo.io/how-to/marketing/finish-an-ai-clip.md Turn an AI-generated clip into a finished video: cuts, captions or subtitles, music, sound effects, text, an upscale and an MP4 export. You get a finished video from a clip you made in Higgsfield, Runway, Magnific or any other AI video tool. The raw clip gets cuts, sound effects matched to the picture, music, captions or subtitles if someone speaks, your text, and a sharper upscale when you need one. You download an MP4 you can post. Use invideo for this when the generator gave you a silent or rough clip: your agent adds the sound, the words and the cuts on an editable timeline, and you change any of it after without making the clip again. Finishing your own AI clips is ordinary video work, and the agent does it. You choose where the video goes and you post it. The agent never publishes it. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Finish my Runway clip ./city-night.mp4. Cut the first second where it warps, add sound effects that match the picture, a low synth music bed, and the title "Neon Hours" for 2 seconds. Vertical 9:16. Tell me the price before you generate any sound. ``` In a chat app, you drag the MP4 into the project in invideo, or paste the clip's public link. In a terminal, you name the file and the agent uploads it. #### What you need Download the clip from the generator first, at its best quality. - **The clip.** An MP4 or MOV from Higgsfield, Runway, Magnific or another tool. Several clips work too. - **The shape.** The clip's own shape, or 9:16, 1:1 or 16:9 for the platform. - **The sound you want.** Sound effects matched to the picture, music, a voice, or the clip's own sound. - **The words.** A title, a caption style, or a call to action. - **The size.** 1080p for social. For 4K, the agent exports at 1080p, then upscales the file. #### Steps The agent looks at and listens to the clip before it edits. The agent makes a project with `new_project`, a timeline with `new_timeline`, and a branch with `timeline_history`. It uploads the clip with `start_upload` and `add_media`, or passes a public link as `media_url`. Expected result: a sequence URL for the clip. The agent runs `media` `metadata` for the size, the length and whether there is sound. It runs `video.frames` to see the shots, and `audio.content` to find speech, music or silence. Expected result: a note of the bad frames to cut and whether anyone speaks. The agent places the clip with `place_media`, then cuts warped or broken frames with `split_clip` and `delete_clip`. For several clips, it splits each one with `media` `video.sceneSplit` first. Expected result: only the frames you want, in order. If `audio.content` shows speech, the agent prices `audio.transcript` on the clip's sequence URL with `dry_run`, starts it with `max_credits` set to the price it told you, and calls again after `retry_after_s` for the words. Then it adds captions with `add_captions`, one slide per line and the words with their times. Expected result: captions that follow the speech. For sound effects matched to the picture, the agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `mmaudio_v2.mmaudio_v2_video_to_audio`. It calls `generate` with `dry_run: true`, the clip's sequence URL as `video` and a `prompt` for the sound, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It reads the new sequence URL with `read`, places that clip with its new sound in place of the silent one, adds music from `search_library` in `stock_music`, and sets the levels with `set_audio_gain`. Expected result: a sequence URL for the clip with sound, and music under it. The agent adds the title and any call to action with `add_text`. For a new shape, it sets the timeline size with `set_timeline_settings` and fills the frame with `fill_frame`. Expected result: text on screen and the shape you asked for. The agent runs `capture` at each cut and each text, and `check_timeline`. It runs `export` with `format` video, which stops at 1080p. For a sharper or 4K copy, it runs `media` `video.upscale` on the export card's URL, `dry_run` first, then with `max_credits` and an `idempotency_key`. The card is a sequence, so no re-upload is needed. Expected result: an export card with status `completed`, and an upscaled sequence if you asked for one. The same job from a terminal: ```bash invideo project new --title "Neon Hours" invideo agent register --name export INVIDEO_AS= invideo edit new --name "Neon 9x16" --width 1080 --height 1920 invideo asset upload ./city-night.mp4 invideo media metadata invideo media audio.content invideo media video.frames --at 0,0.5,1,3,6 invideo gen models --query "sound effects for a video clip" invideo gen model --model mmaudio_v2.mmaudio_v2_video_to_audio invideo gen run \ --model mmaudio_v2.mmaudio_v2_video_to_audio \ --dry-run -i video= -i prompt="rain, distant traffic, neon hum" invideo gen run \ --model mmaudio_v2.mmaudio_v2_video_to_audio \ --max-credits --idempotency-key neon-sound-v1 \ -i video= -i prompt="rain, distant traffic, neon hum" invideo edit show --json invideo branch new --name finish-v1 --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @finish.json invideo edit capture --at 0.5,2,5,8 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo media video.upscale --dry-run invideo notebook show --out ./out ``` Where the values come from: - `` comes from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`. `` is a notebook page from `invideo notebook show `. - `` is the clip's URL from `invideo asset upload`. `` is the dry run's `.estimated_credits`. - `` comes from `invideo edit show `, and on the branch from `invideo edit show `; the main token is stale there. `` is the `.branch_url` that `invideo branch new` returns. - `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves the file as `./out/export.mp4`. - The file `./finish.json` holds a bare list of operations: the `operations` list of the MCP call below. The upscale's paid run adds `--max-credits` with its dry run price and an `--idempotency-key`. The key MCP call cuts the warped first second and adds the title. `` is the branch's URL from `timeline_history`, and `` comes from `get_timeline`. At 30 frames a second, frame 30 is the one second mark. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "split_clip", "clip": "c1", "at_f": 30 }, { "op": "delete_clip", "clip": "c1", "mode": "close_gap", "linked": true }, { "op": "add_text", "track": "V2", "start_f": 0, "end_f": 60, "text": "Neon Hours", "style": { "font_size": 96, "align": "center", "color": "#ffffff", "shadow": true } } ] } ``` After `split_clip`, the left half keeps the id `c1` and the right half is a new clip, so `delete_clip` on `c1` removes the first second. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the upload, the looks and sound reads, the cuts, captions you place, text and the export. - **Costs credits:** the transcript, generated sound and music, stock music, a reframe model and the upscale. The upscale charges by each second of the video. Finishing one clip takes a few minutes. Generated sound and an upscale add the time those models take. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems are a clip with no sound stream, or a warp the agent missed. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | You want a generated music bed | Make it with `elevenlabs_music_v2_5_instrumental` the same way as the sound: `find_models`, `get_model`, a dry run, then `generate` with `max_credits` and an `idempotency_key`. | | A crop to the new shape loses too much | Generate fill with `ltx_2_3_pro.reframe` the same way, with the shot's sequence URL as `video` and the new `aspect_ratio`. | | The clip has no audio at all | That is normal for many generators. Add sound with `mmaudio_v2.mmaudio_v2_video_to_audio` or music. | | `audio.transcript` returns no words | No one speaks. Skip captions, or add a voice with `elevenlabs_text_to_speech.elevenlabs_tts_v4`. | | A warp shows mid-clip | Look at more frames with `media` `video.frames`, then cut it with `split_clip` and `delete_clip`. | | `add_media` from a link is refused | The link must be public. Download the file and upload it with `start_upload`. | | The upscale looks waxy on faces | Try another model from the `video.upscale` list, such as `topaz_proteus_natural`. | | `timeout` on a generation | Do not generate again. `read` the thread URL or call `status`. | | CLI exit 3 on the branch | The token is from main. Run `invideo edit show ` and use its `state_token`. | | The `./out` folder is empty after `status` | `status` waits and does not download. Run `invideo notebook show --out ./out`. | | Avoid: the agent edits the clip without looking | Instead: it reads frames and sound with `media` first. | #### Prompts to try Each prompt is a real variation of the job. ```text I have 6 Higgsfield clips in ./shots. Put them in order, cut each to its best 2 seconds on the beat of an upbeat track, and add a logo end card. ``` ```text My Magnific clip has a person talking. Add word-by-word captions in yellow, keep the original sound, and export 1:1 and 9:16. ``` ```text Upscale my finished Runway video to 4K and tell me the price first. ``` #### When to use something else To change what happens inside a shot, go back to the generator and make a new take. invideo edits, sounds and finishes the clip you have. For the tools' own steps, see [Use Higgsfield with invideo](/integrations/higgsfield), [Use Runway with invideo](/integrations/runway) and [Use Magnific with invideo](/integrations/magnific). #### Related - [Use Higgsfield with invideo](/integrations/higgsfield) - [Use Runway with invideo](/integrations/runway) - [Use Magnific with invideo](/integrations/magnific) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Check your video before you say it is done](/how-to/check-your-video) ### Localize a winning ad with the same voice and lip-sync Source: https://docs.invideo.io/how-to/marketing/localize-a-winning-ad.md Translate and dub an ad that works into new languages. You fix the words first, then your agent voices them in the same voice and re-syncs the lips. Localize an ad that already sells: translate it, dub it, and keep the speaker's own voice and lips in sync. Your agent translates the script, you fix the words in text, and only then does it voice each line and re-sync the mouth. You end up with one branch and one export per language, with on-screen text and captions in that language. This is ordinary ad work for a real product. The agent makes the files. You upload them and switch the ads on in the ad platform. The agent never publishes an ad or sends an email. Use invideo for this when you want to check the translation before anyone pays for a voice, and keep every language as an editable branch of the same timeline. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt with the timeline URL of the winning ad. ```text Localize this ad into German and Spanish (Mexico): . Transcribe it, translate the script, and show me the translation as text before you make any voice. Keep the brand name in English. After I approve, clone the speaker's voice, re-sync the lips, change the on-screen text and captions, one branch per language, and show me frames before you export. ``` Replace `` with the ad's timeline URL, from the editor's address bar. In a chat app, you paste the timeline URL and you fix the translation in the chat. In a terminal, the agent writes the translation to a file, you edit the file, and the agent reads it back. #### What you need The agent needs the ad and the rules for each language. - The timeline URL of the ad, or the project name. - The target languages, with the region where it matters (Spanish for Spain or for Mexico). - Words that never change: the brand name, the product name, a slogan. - A native speaker who reads the translation before the voice is made. This is you or someone you trust. - The right to clone the speaker's voice. Get the actor's consent in writing before you start. #### Steps The agent translates and voices first, then builds one branch per language. ##### Translate and voice The agent fixes the words in text before it spends anything on a voice. The agent prices `audio.transcript` on the speaker's clip by its sequence URL with `dry_run`, tells you the price, starts it with `max_credits` set to that price, and calls again after `retry_after_s` for the words. It sees every word with its time and speaker. The agent translates each line itself and writes the lines into a brief note with `new_brief` and `edit`, one note per language. You read the note in invideo and fix it. The agent sees your changes when it reads the brief again with `read`. The agent pulls the speaker's sound with `media` `audio.extract` on the clip's sequence URL, then cuts short clean pieces of speech with `audio.trim` (`start_time`, `end_time`) on the extracted audio's sequence URL. Each makes a new file, so each call carries an `idempotency_key`. It sees one audio sequence per clip. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `seed_audio_1_0.ta2a`. Each input takes the sequence URL of one short clip: `reference_audio_1` is required, and `reference_audio_2` and `reference_audio_3` are optional. The prompt tags each voice as `@Audio1` to `@Audio3`, matching the inputs, before its line in quotes. The model detects the language by itself. It calls `generate` with `dry_run: true` and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It sees a sequence URL for each new voice and reads it with `read`; it never calls `generate` again to check. ##### Build each language The agent works on one branch per language and never edits main. The agent branches with `timeline_history` action `create_branch`, named after the language. It puts the new voice under the picture with `media` `video.replaceAudio`, or places it on a new track and mutes the original with `set_audio_muted`. It sees the branch URL and a new `state_token`. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `sync_lipsync_v3.video` (inputs `video`, `audio`, `sync_mode`), and `kling_lipsync` (inputs `video`, `audio`) is another. It calls `generate` with `dry_run: true` and tells you the price, then runs with `max_credits` and an `idempotency_key`. It sees a new video sequence URL, reads it with `read`, and swaps it in with `place_media` mode `replace`. The agent changes each text clip with `set_text`. It prices `audio.transcript` on the new voice the same way and calls again after `retry_after_s` for the word times. Then it sends `add_captions`. It sees the clips with the new words and a new `state_token`. The agent calls `capture` at each line and each text, and `check_timeline`. It looks for a mouth out of sync and text that runs off the frame, because German and Spanish lines are often longer. Then it runs `export` on each branch. It sees one export card per branch with status `completed`. The terminal version, for one language: ```bash invideo agent register --name export INVIDEO_AS= invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo context new-brief --name "Ad 12 localization" \ --description "German and Spanish (Mexico) scripts for review" invideo media audio.extract \ --idempotency-key ad12-extract invideo media audio.trim --start-time 2 --end-time 9 \ --idempotency-key ad12-ref-1 invideo gen models --query "seed audio" invideo gen model --model seed_audio_1_0.ta2a invideo gen run --model seed_audio_1_0.ta2a --dry-run \ -i prompt=@de-line-01.txt -i reference_audio_1= invideo gen run --model seed_audio_1_0.ta2a \ --max-credits --idempotency-key ad12-de-voice \ -i prompt=@de-line-01.txt -i reference_audio_1= invideo edit show --json invideo branch new --name de --token invideo gen models --query "lip sync" invideo gen model --model sync_lipsync_v3.video invideo gen run --model sync_lipsync_v3.video --dry-run \ -i video= -i audio= invideo gen run --model sync_lipsync_v3.video \ --max-credits --idempotency-key ad12-de-sync \ -i video= -i audio= invideo edit show --json invideo edit change --timeline T1 --token \ --operations @de.json invideo edit capture --at 1,4,8,12 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./de mv ./de/export.mp4 ./de/ad12_de_9x16_v1.mp4 ``` Where the values come from: - `` is the ad's project, and `` is the ad's timeline URL, the one you give the agent. `` is the name you choose in `invideo agent register`. - `` is a notebook page; `invideo notebook show ` lists them. - `` is the speaker clip's sequence URL, from `invideo notebook show ` or what the upload returns. - `` is the URL `audio.extract` returns, and `` the URL `audio.trim` returns. `` is the sequence URL the paid voice run returns. - Each `` is the dry run right before it. - `` comes from `invideo edit show `, and on the branch from `invideo edit show `; the main token is stale there. `` is the `.branch_url` that `invideo branch new` returns. - `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves `./de/export.mp4`. - The file `./de.json` holds a bare list of operations: the `place_media` swap, the `set_text` changes and the captions. The file `de-line-01.txt` holds the prompt with its `@Audio1` tag. The voice call over MCP, as a dry run. The clip in `reference_audio_1` is `@Audio1` in the prompt. `` comes from `read` on the project, and `` is the URL `audio.trim` returns. The paid call is the same with `dry_run` removed, `max_credits` set to the price and an `idempotency_key`. ```json { "url": "", "model": "seed_audio_1_0.ta2a", "dry_run": true, "inputs": { "prompt": "@Audio1, warm and upbeat: \"Schluss mit kaltem Kaffee.\"", "reference_audio_1": "" } } ``` invideo has no one-shot dubbing model. For a one-shot draft, ElevenLabs Dubbing or HeyGen video translation makes one outside invideo, with no step where you fix the words first. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: the transcripts, the voice with `seed_audio_1_0.ta2a`, and the lip sync. - Free: the translation the agent writes, your fixes, the branches, every edit, `capture` and `export`. - `audio.extract` and `audio.trim`: the dry run shows the price before anything starts. One language takes under an hour, most of it the wait for lip sync and your review. Lip sync charges by the length of the audio. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems come from a weak reference clip or a line that grew in translation. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | You have no consent to clone the voice | Use `elevenlabs_text_to_speech.elevenlabs_tts_v4` with a voice from `elevenlabs_text_to_speech_voices` instead, priced the same way. | | The new voice sounds like another person | Use cleaner reference clips: speech only, no music under it. Add a second clip as `reference_audio_2`. | | The mouth drifts out of sync at the end | The new audio is longer than the video. Set `sync_mode` to `remap`, or shorten the line in text and voice it again. | | German text runs off the frame | Make the text smaller with `set_text_style`, or split the line into two text clips. | | The brand name is translated | Fix it in the brief note before the voice, and list it as a word that never changes. | | CLI exit 3 on the branch | The token is from main. Run `invideo edit show ` and use its `state_token`. | | CLI exit 5 | A credit limit. Tell the person and stop. | | Avoid: voicing before the text is approved | Instead: wait for the person's fixes in the brief. A voice costs credits; text does not. | | Avoid: editing main for a language | Instead: one branch per language with `timeline_history`. | #### Prompts to try Each prompt is a real variation of this job. ```text My best ad is in English. Make French, German and Italian versions. Keep "Brewly" in English. Put each translation in the brief, wait for my OK, then voice, lip-sync and export each one. ``` ```text Make a quick Spanish draft of this ad so I can show the team. Voice the translation, no lip sync. One export, named as a draft. ``` ```text The Japanese version is approved. Change only the on-screen price text to the yen price I give you, add Japanese captions, and export. ``` #### When to use something else invideo does not check a translation for you. A native speaker or a translation service should read every line before the voice is made. For regulated claims in a market, ask your legal or compliance team. For a full studio dub with several actors, a dubbing studio or ElevenLabs Dubbing is a better fit. #### Related - [Translate a training video and retime the cut](/how-to/training/translate-and-retime) - [Dub existing footage](/how-to/training/dub-existing-footage) - [Word-by-word captions](/how-to/creators/word-by-word-captions) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Label AI content so your ad runs on TikTok, Meta and Google](/how-to/marketing/ai-disclosure-for-ads) - [Check your video before you say it is done](/how-to/check-your-video) ### Brand ad film Source: https://docs.invideo.io/how-to/marketing/brand-ad-film.md Turn a brief into a 30 or 60 second brand spot or commercial. Generated mood shots, your real product on screen, one color look, music and voice. Make a brand ad film, a 30 or 60 second spot or commercial, from a written brief. Your agent generates the mood shots, cuts in real footage or photos of your product, puts one color look over all of it, and adds music and a voice. You end up with an MP4 and a timeline you can still change shot by shot. This is ordinary ad work for a real product. The agent makes the film. You decide where it runs, and you upload it to the ad platform yourself. The agent never publishes an ad or sends an email. Use invideo for this when you want generated shots and real product footage on one timeline, with the brief, the brand rules and every take kept in the same project. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a 30 second brand film for Brewly cold brew from this brief: . Use the real product shots in ./product. Generate the mood shots around them, never the product itself. One warm look across every shot, an instrumental track, a calm female voice for the last line. Price every generation first and show me frames before you export. ``` Replace `` with your brief, pasted as text. In a chat app, you drag the product shots and the logo into the project. In a terminal, the agent uploads them from the folder you name. #### What you need The agent needs the brief and the real product. - The brief: the audience, the one message, the tone, the length (30 or 60 seconds) and the shape (16:9 for YouTube and TV, 9:16 for Reels and TikTok). - Real footage or photos of the product. The product on screen is always the real one. - The brand kit: colors as hex codes, fonts as TTF or OTF files, the logo. - The last line or the tagline, word for word. - A LUT as a `.cube` file if your brand has one. This is optional. #### Steps The agent plans first, generates second, and edits on a branch. The agent makes a brief with `new_brief` and adds a `shot-list` note with `edit`. It writes the brand kit to `context/brands/brewly.md` with `write`: colors, fonts, logo and rules like "never show the can on its side". It sees the brief URL and the entry URL. The agent uploads the product shots, logo, fonts and LUT with `start_upload` and `add_media`. It sees one sequence URL per file, and a bin id for each font. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. For a shot from words alone, a good pick is `seedance_2_5.frames`. For a shot that must match a look, a good pick is `seedance_2_5.r2v` with `reference_images`. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It sees a thread URL and, when each take lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. The agent runs `find_models` for an instrumental track and for a voice, and reads each pick with `get_model`. Good picks are `elevenlabs_music_v2_5_instrumental` for the music, and `elevenlabs_text_to_speech.elevenlabs_tts_v4` with a `voice_id` from `elevenlabs_text_to_speech_voices` for the last line. For each, it calls `generate` with `dry_run: true`, tells you the price, and runs with `max_credits` and an `idempotency_key`. It sees a sequence URL for each and reads it with `read`. The agent makes the timeline with `new_timeline` and branches with `timeline_history`. It places shots with `place_media`, the real product shots on the beats where the product shows, the music on `A2` and the voice on `A1`. It adds the `ducker` audio effect to `A2` and the logo and tagline with `add_text`. A new timeline ducks under `A1` by default. It sees a new `state_token` after each call. The agent applies the LUT to each clip with `apply_lut`, or adds a grade with `edit_grade` and sets it with `set_grade_parameter`. It copies the look to the other clips with `paste_attributes`. It sees the grades in `get_timeline`. The agent calls `capture` at one frame per shot and compares them by eye: color, light, and the product's label. It runs `check_timeline`. Then it runs `export`. It sees an export card with status `completed`. The terminal version: ```bash invideo agent register --name export INVIDEO_AS= invideo context new-brief --name "Brewly 30s" \ --description "30 second brand film, warm, morning ritual" invideo context write /context/brands/brewly.md \ --markdown @brewly.md invideo asset upload ./product/*.mp4 ./brand/* invideo gen models --query "cinematic mood shot from words" invideo gen model --model seedance_2_5.frames invideo gen run --model seedance_2_5.frames --dry-run \ -i prompt="slow dawn light over a kitchen counter" -i aspect_ratio=16:9 invideo gen run --model seedance_2_5.frames \ --max-credits --idempotency-key brewly-dawn-1 \ -i prompt="slow dawn light over a kitchen counter" -i aspect_ratio=16:9 invideo status --wait invideo edit new --name "Brewly 30s" invideo edit show --json invideo branch new --name cut-1 --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @look.json invideo edit capture --at 1,5,9,13,17,21,25,29 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where the values come from: - `` is your project's URL, or what `invideo project new` returns. `` comes from `invideo edit new`. - `` is the name you choose for the agent in `invideo agent register`. - `` is a notebook page; `invideo notebook show ` lists them. - `` is the dry run's `.estimated_credits`. `` is the `url` the paid run returns. - `` comes from `invideo edit show `. `` is the `.branch_url` that `invideo branch new` returns. On the branch, `` is the one from `invideo edit show `; the main token is stale there. - `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves the file as `./out/export.mp4`. The file `./look.json` holds a bare list of operations: one look on every clip, and the ducker on the music. On the MCP path, the same list goes in the `operations` field of `edit_timeline`. A new timeline has `A1` (Voice) and `A2` (Music), and ducks under `A1` by default. `m4` is the LUT in the bin, and the clip ids come from `get_timeline`. ```json [ { "op": "apply_lut", "clip": "c3", "lut": "m4", "strength": 0.8 }, { "op": "paste_attributes", "from": "c3", "to": ["c4", "c5", "c6"], "attributes": ["effects"] }, { "op": "add_audio_effect", "target": "A2", "target_kind": "track", "effect": "ducker" } ] ``` For a 4K delivery, export at 1080p first. Then run `media` `video.upscale` on the export with a model from its list, like `byteplus_vod_upscale`, or `generate` with `topaz_starlight_fast_3` and `resolution` set to `4k`. Both take a dry run first and `max_credits` on the paid run. Upscales charge for each second of the source. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: each generated shot, the music, the voice, paid stock, and an upscale. - Free: the brief, the brand kit, uploads, every edit, the grade, `capture` and `export`. Video generation is the big cost, and it grows with length and resolution. Generate short takes at a lower resolution to pick a direction, then make the final takes. A first cut takes about an hour. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are shots that do not match, or a product that looks wrong. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | A generated shot shows a fake product | Cut it. Generate the scene around the product, then cut to the real product shot. | | The shots do not look like one film | Use one LUT or one grade, copied with `paste_attributes`. Pass a frame from the hero shot as a reference image. | | `generate` refused for `max_credits` | The price is above the cap. Run `dry_run`, tell the person, and ask before raising it. | | `apply_lut` refused | The clip has more than one grade. Remove one with `edit_grade` kind `remove`. | | The music drowns the voice | The ducker follows `A1` by default. If the voice is on another track, point it there with `set_sidechain_source`. Raise `reduction` with `set_audio_effect_parameter`, using the ducker's id from `get_timeline`. | | CLI exit 3 on the branch | The token is from main. Run `invideo edit show ` and use its `state_token`. | | Avoid: generating the product | Instead: keep the real product as a clip. A generated label or shape misleads buyers. | | Avoid: saying done after the last edit | Instead: `capture` one frame per shot and compare them. | #### Prompts to try Each prompt is a real variation of this job. ```text Make the 60 second version of the Brewly film from the same brief. Reuse the approved shots, add two new mood shots, and keep the same look. ``` ```text Cut a 15 second version and a 6 second bumper from the approved 30 second film. One branch each. ``` ```text The client wants 4K. Export the final branch at 1080p, price an upscale to 4K, and wait for my OK. ``` #### When to use something else invideo does not shoot your product. For a hero product shot with real light and motion, book a product photographer or a studio, then bring the footage in. Music from a model or from stock covers most ads. For a jingle or a known song, license it from the rights holder. For TV delivery specs, ask your broadcaster or a post house for the final check. #### Related - [Make a launch video from your product URL and screenshots](/how-to/marketing/launch-video) - [Turn a product photo into a video without redrawing the product](/how-to/marketing/product-photo-to-video) - [Make a stock-footage commercial for your business, in short and long cuts](/how-to/marketing/stock-footage-commercial) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Label AI content so your ad runs on TikTok, Meta and Google](/how-to/marketing/ai-disclosure-for-ads) - [Color grade log footage](/how-to/film/color-grade-log-footage) ### Performance ads Source: https://docs.invideo.io/how-to/marketing/performance-ads.md Make new ad variants each week from a few masters, named by a scheme, and pick next week's variants from your results sheet. Make performance ads, also called ad creatives or variants, at a steady weekly pace for Meta, TikTok and YouTube. Your agent keeps one master timeline per concept, makes each variant as a copy with a new hook, line or call to action, sizes it for each placement, and names every file by your scheme. Each week it reads your results sheet and proposes the next round. This is ordinary ad work for a real product. The agent makes and names the files. You upload them, set budgets, and switch ads on in Ads Manager. The agent never touches a live ad, never changes a budget, and never publishes. Use invideo for this when you want every variant to stay an editable timeline beside its master, so next week's change is a few edits and a free export, not a new video. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Here are this week's results: ./results/week-44.csv. My masters are in . Read the results, tell me which hooks and lines won, and propose 12 new variants. After I approve the list, make each one as a copy of its master, in 9:16 and 4:5, named by my scheme, and export them all. ``` In a chat app, you paste the results table into the chat. In a terminal, the agent reads the CSV from the folder you name. #### What you need The agent needs the masters, the scheme and the numbers. - One master timeline per concept, already cut and approved. - The variant list: hooks, lines, offers or calls to action to swap. The agent can propose them from your results. - The placements: 9:16 for Reels, Stories, TikTok and Shorts, 4:5 or 1:1 for feeds, 16:9 for YouTube in-stream. - Your naming scheme. One example: week, concept, hook, size, version, like `w44_c2_hookB_9x16_v1`. - Your results sheet, exported from Ads Manager as CSV, with one row per ad name. #### Steps The agent works in rounds. Each round is one branch, so last week's ads stay as they were. The agent reads your CSV with its own file tools and matches each row to a file name. It sorts by the metric you name, like cost per purchase or hook rate. It tells you which hooks, lines and sizes won, and what it proposes next. You see the ranked list; nothing in invideo changes. The agent reads the master with `get_timeline` and creates a branch with `timeline_history` action `create_branch`, named for the week. It sees the branch URL. The agent runs `duplicate_timeline` with a `name` that matches the file name. The copies share nothing with the master. It sees one new timeline id per variant. For a new hook line, the agent runs `set_text` on the hook's text clip. For a new opening shot, it uses `place_media` mode `replace`. It sees a new `state_token`. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `seedance_2_5.frames`. It calls `generate` with `dry_run: true` and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It sees a sequence URL, reads it with `read`, and places it with `place_media`. The agent sets the canvas with `set_timeline_settings` and fixes each clip with `fill_frame` and `set_position`. It adds safe zone lines with `create_guide`, from the platform's spec page, and moves text inside them. The page [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) has the details. It sees the new canvas in `get_timeline`. The agent calls `capture` on each timeline at the hook, the middle and the call to action, and runs `check_timeline`. Then it runs `export` once per timeline, with `timeline_id`, `file_name` set to the scheme name and an `idempotency_key`. It sees one export card per variant, each with status `completed`, and gives you the list of names. The terminal version, for one variant: ```bash invideo agent register --name export INVIDEO_AS= invideo edit show --json invideo branch new --name w44 --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @copy-master.json invideo gen models --query "short product shot for an ad" invideo gen model --model seedance_2_5.frames invideo gen run --model seedance_2_5.frames --dry-run \ -i prompt="hand pours cold brew over ice" -i aspect_ratio=9:16 -i duration=5 invideo gen run --model seedance_2_5.frames \ --max-credits --idempotency-key w44-c2-b-shot \ -i prompt="hand pours cold brew over ice" -i aspect_ratio=9:16 -i duration=5 invideo edit show --json invideo edit change --timeline T7 --token \ --operations @hookB.json invideo edit capture --timeline T7 --at 0.5,3,14 \ --out ./frames invideo edit export --format video --quality 1080 \ --timeline T7 --file-name w44_c2_hookB_9x16_v1 --idempotency-key w44-c2-b \ --json invideo status --wait invideo notebook show --out ./ads mv ./ads/export.mp4 ./ads/w44_c2_hookB_9x16_v1.mp4 ``` Where the values come from: `` from `invideo edit new`, `` from `invideo project new`, `` from your choice in `invideo agent register`, and `` from `invideo notebook show `. `` comes from the first `invideo edit show`, then from `invideo edit show` on the branch, read again before each change, because the main token is stale there. `` is the `branch_url` that `invideo branch new` returns. `` is the dry run's `estimated_credits`. `` is `.sequences[0]` of what the export returns. `invideo status` does not download, so `invideo notebook show` saves the file, always as `export.mp4`, and the agent renames it. A voice line works the same way with `elevenlabs_text_to_speech.elevenlabs_tts_v4`, `-i prompt=` and `-i voice_id=`. The two ops files are bare lists. The first, `copy-master.json`, runs on the master `T1` and copies it. The second, `hookB.json`, runs on the copy `T7` and changes the hook. The copy's id `T7` and the hook clip's id `c14` come from `invideo edit show` on the branch. ```json [ { "op": "duplicate_timeline", "timeline": "T1", "name": "w44_c2_hookB_9x16_v1" } ] ``` ```json [ { "op": "set_text", "clip": "c14", "text": "Cold brew in 30 seconds. No machine." } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: a new generated shot, a new voice line, paid stock. - Free: copies, text swaps, resizing, guides, `capture` and every `export`. A variant that only swaps text and size takes a few minutes. Run a big round in parts, a few variants at a time, and check each part before the next. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems come from a stale token or a name that does not match the sheet. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The download folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./ads` with the card URL from `.sequences[0]`. | | The variant needs a new voice line | Make it with `elevenlabs_text_to_speech.elevenlabs_tts_v4` and a `voice_id` from `search_library` in `elevenlabs_text_to_speech_voices`, priced and run the same way as a shot. | | The saved file is `export.mp4`, not the scheme name | `file_name` does not name the saved file. Rename it to the scheme name after the download. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` on the URL you edit, the branch URL on a branch, and rebuild the ops with the new token. | | A result row matches no file | The ad was renamed in Ads Manager. Ask the person for the mapping. Do not guess. | | Two exports have the same name | Add the version to `file_name`. Each name in the scheme must be unique. | | Text sits under the TikTok buttons | Move it inside the guides with `set_position`, and capture again. | | An export never finishes | `read` the card or run `invideo status --wait`. Do not call `export` again. | | Avoid: editing the master for a variant | Instead: `duplicate_timeline`, and change the copy. | | Avoid: changing an ad that is live | Instead: make a new variant with a new version number. The person swaps it in Ads Manager. | | Avoid: claiming a variant will win | Instead: report what the numbers say and how many results each row has. | #### Prompts to try Each prompt is a real variation of this job. ```text Hook B beat hook A on every concept. Make hook B versions of the three concepts that don't have one, in 9:16 and 4:5, version 1. ``` ```text Make 5 call-to-action variants of concept 2: "Shop now", "Try it free", "See flavors", "Get 2 cans", "Order now". 9:16 only. ``` ```text List every variant made in October with its name, its master, and what it changed. Put it in a brief note so the team can see it. ``` #### When to use something else invideo does not read Ads Manager, place ads, or set budgets. Export your results from Meta Ads Manager, TikTok Ads Manager or Google Ads as a CSV, and upload the finished files there yourself. For automatic creative testing inside a platform, use the platform's own tools, like Meta's Advantage+ creative options. For a shared tracker of names and results, use a spreadsheet. #### Related - [Test hooks on one ad, with branches](/how-to/marketing/test-hooks-on-branches) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Make static ads at volume from the same brief as your video ads](/how-to/marketing/static-ads-at-volume) - [Make a UGC ad from product photos with an AI actor](/how-to/marketing/ugc-ad-with-ai-actor) - [CSV to videos](/how-to/developers/csv-to-videos) - [Label AI content so your ad runs on TikTok, Meta and Google](/how-to/marketing/ai-disclosure-for-ads) ### Label AI content so your ad runs on TikTok Source: https://docs.invideo.io/how-to/marketing/ai-disclosure-for-ads.md Find which shots in your ad are AI-generated, add an AI label in the video and the file name, and set each platform's own AI disclosure. Label the AI content in an ad, also called AI disclosure or an AIGC label, so the platform and the viewer know what was generated. Your agent lists every generated shot, voice and image in the ad, adds a label in the video where you want one, and puts a tag in the file name. You set each platform's own AI toggle or checkbox when you upload. This is ordinary ad work for a real product. The agent prepares the video and the list. You set the disclosure in the ad platform and you switch the ad on. The agent never publishes an ad. This page is not legal advice, and it makes no claim about what a platform will approve. Use invideo for this when your ad mixes generated and real footage: the notebook records which model made each take, so the agent can list them instead of guessing. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt with the timeline URL. ```text For this ad , list every clip that a model generated or changed: video, voice, music and images, with the model and the timecode. Add a small "Made with AI" label for the whole ad, add "_ai" to the export file name, and tell me which platform settings I need to set. ``` Replace `` with the URL of the ad's timeline, from the editor's address bar or from `invideo edit new`. In a chat app and in a terminal the steps are the same. In a terminal, the agent also saves the list to a file you name. #### What you need The agent needs the ad and your house rule. - The timeline URL of the ad. - Where it runs: TikTok, Meta (Facebook and Instagram), Google and YouTube. - Your house rule for the label: the words, where it sits, and whether it shows for the whole ad or only on generated shots. - Whether the ad is about social issues, elections or politics. Those ads have stricter rules on every platform. #### What each platform asks Each platform has its own rule and its own switch. The rules change, so read the platform's page on the day you upload. The summaries below put each page in words. ##### TikTok TikTok asks advertisers to disclose an ad whose image, video or audio is completely made by AI or significantly changed by AI. You switch on "This ad contains AI-generated content" in TikTok Ads Manager when you create the ad. After you submit, you cannot change the toggle unless you change the video or image. Spark Ads are handled differently. Read How to add disclaimers to ads in TikTok Ads Manager. ##### Meta Meta labels ad images that were made or clearly edited with Meta's own generative AI tools with "AI info". Ads about social issues, elections or politics must disclose content that was digitally created or altered, including with tools outside Meta. Read How AI-generated images in ads are identified and labelled on Meta. ##### Google and YouTube Google asks election advertisers to disclose synthetic content that shows real or realistic people or events in a way that did not happen. They tick "Altered or synthetic content" in the campaign settings. For some formats Google adds the label itself; for others the advertiser adds a clear one in the ad. Read Disclosure requirements for synthetic content. For a video posted to a YouTube channel, YouTube asks creators to disclose realistic altered or synthetic content at upload. Read Disclosing use of GenAI content. #### Steps The agent finds what was generated, labels it, and hands you the list for the platform settings. The agent runs `read` on the project. Each thread is named after the model that made it unless someone renamed it, and each sequence shows who made it. It reads the timeline with `get_timeline` and matches each clip to its sequence. It sees a list of clips with model, kind and timecode. The agent groups the list: generated people and voices, generated scenes, generated music, and real footage. It tells you which platform rules above may apply. You decide. It sees your answer in the chat. The agent creates a branch with `timeline_history` action `create_branch`, named `ai-label`. It sees the branch URL, and makes every later edit there. The unlabeled cut stays on main. The agent adds the label with `add_text` on the top video track, for the whole ad or for each generated shot. It styles it with `set_text_style` so it stays readable on a phone, and places it inside the platform's safe zone. It sees a new text clip id. The agent adds a short end slide with `add_text` that names the models used, one per line. It sees the slide on the timeline. The agent calls `capture` on each labeled shot, runs `check_timeline`, then runs `export`. It sees an export card with status `completed`. A terminal agent saves the file and renames it to end in `_ai`, like `w44_c2_hookB_9x16_v1_ai.mp4`. Then the agent gives you the list for the platform settings. You see the tagged file and the list. The terminal version: ```bash invideo agent register --name export INVIDEO_AS= invideo project show invideo edit show --json invideo branch new --name ai-label --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @label.json invideo edit capture --at 0.5,6,12 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out mv ./out/export.mp4 ./out/w44_c2_hookB_9x16_v1_ai.mp4 ``` Where the values come from: `` and `` are the URLs you give the agent, or what `invideo project new` and `invideo edit new` return. `` is the name you choose in `invideo agent register`. `` comes from `invideo edit show `, and on the branch from `invideo edit show `; the main token is stale there. `` is the `.branch_url` that `invideo branch new` returns. `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves the file as `./out/export.mp4`. The file `./label.json` holds the label as a bare list of operations, over the whole ad. `end_f` is the ad's last frame, from `get_timeline`. `V3` is the Titles track of a new timeline. On the MCP path, the same list goes in the `operations` field of `edit_timeline`. ```json [ { "op": "add_text", "track": "V3", "start_f": 0, "end_f": 450, "text": "Made with AI", "style": { "font_size": 34, "color": "#ffffff", "shadow": true } } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: nothing on this page, unless you generate new shots. - Free: reading the notebook, the branch, the label, the credits slide, `capture` and `export`. Labeling one ad takes a few minutes. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems come from a clip with no clear source, or a label in the wrong place. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | A clip has no thread or model | It was uploaded. Ask the person where it came from. Do not guess. | | A thread was renamed and hides its model | `read` the sequence URL. Tell the person what you found and what you could not. | | The label sits under the platform buttons | Move it with `set_position` inside the safe zone, and capture again. | | The label is unreadable on a phone | Raise `font_size` and add `shadow` or `background_color` with `set_text_style`. | | The saved file is called `./out/export.mp4` | `notebook show` always saves `./out/export.mp4`. Rename the file to end in `_ai`. | | CLI exit 3 on the branch | The token is from main. Run `invideo edit show ` and use its `state_token`. | | A refusal with `code` `failed` | Try once more. If it fails again, file `report_bug` and tell the person. | | Avoid: telling the person an ad is compliant | Instead: give the list and the platform pages. The person and their legal team decide. | | Avoid: setting the platform toggle | Instead: the person sets it in the ad platform. The agent has no access there. | #### Prompts to try Each prompt is a real variation of this job. ```text Label only the shots with a generated person, at the top left, for the length of each shot. Leave the real product shots unlabeled. ``` ```text Make a list of every model used in all my October ads, by file name, so the compliance team can check them. ``` ```text Add a 2 second end slide that says "Visuals created with AI" and names the video and voice models, then export the 9:16 and 16:9 versions. ``` #### When to use something else invideo does not set disclosures inside TikTok Ads Manager, Meta Ads Manager or Google Ads, and does not judge whether an ad meets a law or a policy. For political or issue ads, or ads in a regulated field like health or finance, ask your legal or compliance team. For Content Credentials (C2PA) in the file itself, use a tool that writes C2PA data, like Adobe Content Authenticity. #### Related - [Make a UGC ad from product photos with an AI actor](/how-to/marketing/ugc-ad-with-ai-actor) - [Make performance ads for Meta, TikTok and YouTube, named and iterated from results](/how-to/marketing/performance-ads) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Make a brand ad film from a brief, with generated shots and your real product](/how-to/marketing/brand-ad-film) - [Commercial use of stock, music and generated media](/account/commercial-use) ### Resize one master ad for every placement Source: https://docs.invideo.io/how-to/marketing/every-placement-from-one-master.md Resize one master ad to every aspect ratio and placement, with safe zone guides, text moved per size, and one named export each. Resize one master ad for every placement: 9:16 for Reels, Stories, TikTok and Shorts, 4:5 and 1:1 for feeds, and 16:9 for YouTube. Your agent copies the master once per aspect ratio, reframes each shot so faces and the product stay in frame, draws the platform's safe zones as guides, moves the text inside them, and exports one named file per size. This is ordinary ad work for a real product. The agent makes the files. You upload them to each ad platform and switch them on. The agent never publishes an ad. Use invideo for this when you want every size to stay an editable timeline beside the master, so a change to the copy or a shot is a few edits in each size and a free export. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt with the timeline URL of the master. ```text Make 9:16, 4:5, 1:1 and 16:9 versions of this ad: . Keep faces and the product in frame, add safe zone guides for Reels and TikTok from their spec pages, move the text inside them, and export each size named ad7_9x16_v1, ad7_4x5_v1 and so on. Show me frames of each size before you export. ``` Replace `` with the master's timeline URL, from the editor's address bar. In a chat app, you paste the timeline URL. In a terminal, the agent finds it with `invideo project show` and saves the frames to a folder. #### What you need The agent needs the master and the list of sizes. - The timeline URL of the master ad, cut and approved. - The placements, and the size for each. Common canvases are 1080 by 1920 for 9:16, 1080 by 1350 for 4:5, 1080 by 1080 for 1:1 and 1920 by 1080 for 16:9. - The safe zone for each placement, from the platform's own page. - Your naming scheme for the files. #### Safe zones in words A safe zone is the part of the frame that the app's buttons, captions and profile name do not cover. Each platform publishes its own, and it changes, so the agent reads the page on the day. - **Meta Reels and Stories.** Keep text, logos and faces off the top, bottom and side edges of a 9:16 ad. With a disclaimer on a Reels ad, Meta asks for more room at the bottom. See About text overlays and the safe zone for ads in Stories and Reels and Best practices for aspect ratios. - **TikTok.** The safe zone depends on the orientation and on how long the caption is. TikTok gives safe zone files to download on TikTok Auction In-Feed Ads. - **YouTube Shorts.** Google recommends 9:16 vertical video and describes the buttons on the right of the Shorts player on YouTube Shorts ads: asset specs and best practices. #### Steps The agent leaves the master alone and works on copies. The agent reads the master with `get_timeline`, then runs `duplicate_timeline` once per size, named like ad7_9x16_v1. It sees one new timeline id per size. The agent runs `set_timeline_settings` on each copy with the width, height and the master's `fps`. It sees the new canvas in `get_timeline`, with the clips now too wide or too tall. For each clip, the agent runs `fill_frame`, then moves the picture with `set_position` so the face or the product sits in the center of the safe area. It uses `set_zoom` where a shot needs to be tighter. It sees each clip's new position. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `ltx_2_3_pro.reframe`, which fills the new space with generated picture. It calls `generate` with `dry_run: true`, the shot's sequence URL as `video` and the new `aspect_ratio`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It sees a new sequence URL, reads it with `read`, and places that shot over the clip with `place_media`. The agent adds the safe zone with `create_guide`: horizontal guides for the top and bottom bands and vertical guides for the sides, each a fraction of the canvas. It locks them with `locked`, so nobody drags them by mistake. It sees the guides in `get_timeline` mode `collection`. The agent moves each text clip with `set_position` and resizes it with `set_text_style`. It copies one clip's place to the others with `paste_attributes` and `transform`. It sees the text inside the guides. The agent calls `capture` on each copy at the hook, each text and the end card, and runs `check_timeline`. Then it runs `export` once per copy with `timeline_id`. It sees one export card per size with status `completed`. The terminal version, for the 9:16 copy: ```bash invideo agent register --name export INVIDEO_AS= invideo edit show --json invideo edit change --timeline T1 --token \ --operations @copies.json invideo edit show --json invideo edit change --timeline T2 --token \ --operations @9x16.json invideo gen models --query "reframe a shot to a new shape" invideo gen model --model ltx_2_3_pro.reframe invideo gen run --model ltx_2_3_pro.reframe --dry-run \ -i video= -i aspect_ratio=9:16 invideo gen run --model ltx_2_3_pro.reframe \ --max-credits --idempotency-key ad7-c5-9x16 \ -i video= -i aspect_ratio=9:16 invideo edit capture --timeline T2 --at 0.5,4,9,14 \ --out ./frames/9x16 invideo edit check invideo edit export --format video --quality 1080 \ --timeline T2 --json invideo status --wait invideo notebook show --out ./9x16 mv ./9x16/export.mp4 ./9x16/ad7_9x16_v1.mp4 ``` Where the values come from: - `` is the master's timeline URL, and `` is the project it sits in, from `invideo project show`. `` is the name you choose in `invideo agent register`. `` is a notebook page from `invideo notebook show `. - `` comes from the `invideo edit show` right before each change. After the copies land, the first token is stale. - `T2` is the 9:16 copy's id, from what `duplicate_timeline` returns or `invideo edit show`. - `` is the sequence URL of the shot that cannot be cropped, from `invideo notebook show `. `` is the dry run's `.estimated_credits`. - `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves `./9x16/export.mp4`. The file `./9x16.json` holds the 9:16 copy as a bare list of operations. On the MCP path, the same list goes in the `operations` field of `edit_timeline`. The clip ids come from `get_timeline` on the copy. The guide positions are an example; take the real ones from the platform's page. ```json [ { "op": "set_timeline_settings", "timeline": "T2", "width": 1080, "height": 1920, "fps": 30 }, { "op": "fill_frame", "clip": "c3" }, { "op": "set_position", "clip": "c3", "x": -120, "y": 0 }, { "op": "create_guide", "timeline": "T2", "orientation": "horizontal", "position": 0.14, "locked": true }, { "op": "create_guide", "timeline": "T2", "orientation": "horizontal", "position": 0.65, "locked": true }, { "op": "create_guide", "timeline": "T2", "orientation": "vertical", "position": 0.06, "locked": true }, { "op": "create_guide", "timeline": "T2", "orientation": "vertical", "position": 0.94, "locked": true }, { "op": "set_position", "clip": "c9", "x": 0, "y": -300 } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: `ltx_2_3_pro.reframe` on a shot that needs generated fill. It charges by the length of the source. - Free: the copies, the canvas, `fill_frame`, `set_position`, `set_zoom`, guides, `capture` and every `export`. All the sizes take under an hour by hand. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are a cropped face or text under the buttons. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | You want branches instead of copies | Create one branch per size with `timeline_history` instead of `duplicate_timeline`. | | A face is cut at the edge in 9:16 | Move the clip with `set_position`, or lower the zoom with `set_zoom`, and capture again. | | `fill_frame` refused | The clip's zoom is animated. Remove the zoom animation first, or move it by hand. | | The product leaves the frame halfway through the shot | One position does not fit a moving shot. Split the clip with `split_clip` and position each part, or use `ltx_2_3_pro.reframe`. | | Black bars in the export | A clip is fit, not filled. Run `fill_frame` on it. | | Lines show in a capture or the export | Check with `get_timeline` whether they are guides or a shape clip. Remove guides with `delete_guide` before the export, and file `report_bug`. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` and use its new `state_token`. | | The saved file is called `./9x16/export.mp4` | `notebook show` always saves `./9x16/export.mp4`. Rename it to your scheme. | | Avoid: one guide set for every platform | Instead: one set per placement, from that platform's page. | | Avoid: resizing the master | Instead: `duplicate_timeline`, and resize the copy. | #### Prompts to try Each prompt is a real variation of this job. ```text The 16:9 master is done. Make only the 9:16 version for TikTok, with TikTok's safe zone for a two-line caption, and export it. ``` ```text The headline changed. Change it in the master and in all four sizes, keep each size's position, and export version 2 of each. ``` ```text Shot 3 loses the product in 1:1. Price a generative reframe of that shot only, and wait for my OK. ``` #### When to use something else `ltx_2_3_pro.reframe` fills new space with generated picture. It is not a face-tracking crop. For an automatic crop that follows a face through a long shot, a tool with face tracking, like Auto Reframe in Premiere Pro or Smart Reframe in DaVinci Resolve, fits better. Each platform's ad preview is the final check of the safe zone. #### Related - [Repurpose for every platform](/how-to/creators/repurpose-for-every-platform) - [Make performance ads for Meta, TikTok and YouTube, named and iterated from results](/how-to/marketing/performance-ads) - [Make static ads at volume from the same brief as your video ads](/how-to/marketing/static-ads-at-volume) - [Check your video before you say it is done](/how-to/check-your-video) - [Timeline edit operations](/reference/edit-operations) ### Make static ads at volume from the same brief as your video ads Source: https://docs.invideo.io/how-to/marketing/static-ads-at-volume.md Make image ads in bulk from the same brief as your video ads: stills from the videos, new images from a model, headlines on top, every size named. Make static ads, also called image ads or statics, in bulk from the same brief and footage as your video ads. Your agent pulls the best stills from each video, makes new images with an image model where you need them, puts the headline and offer on top, sizes each one for its placement, and exports every still with a name. This is ordinary ad work for a real product. The agent makes the images. You upload them and switch the ads on in the ad platform. The agent never publishes an ad. Use invideo for this when your statics should match your video ads: the same shots, the same brand kit and the same headlines, all in one project, with every still exported free. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text For each of the 10 videos in , make 3 static ads: two stills from the video and one new image from the brief. Put the video's hook as the headline, with my brand kit. Make each in 1:1 and 4:5, named like v01_static1_1x1. Do the first video, show me, then do the rest. ``` In a chat app, you see each still in the project. In a terminal, the agent waits for each export with `invideo status`, then saves the image to a folder with `invideo notebook show` and `--out`. `invideo status` alone does not download. #### What you need The agent needs the videos, the words and the sizes. - The video ads, as timelines or sequences in one project. - The brief, and the brand kit in `context/brands/`. - The headlines and offers, one per static, or let the agent take them from each video's hook. - The sizes: 1:1 and 4:5 for feeds, 9:16 for Stories, 16:9 or 1.91:1 for some link ads. - Your naming scheme. #### Steps The agent does one video first, waits for your OK, then runs the rest in parts. The agent picks frames by looking at `capture` on the timeline. It exports each frame with `export` mode `image` and `still_at`, which includes the timeline's text and grade. For a frame of a raw source, it uses `media` `video.extractFrameAtTime` with `time_seconds`. It sees one image per still. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `nanobanana_pro`, with a `prompt`, `reference_images` and an `aspect_ratio` within the range `get_model` gives. The agent passes a still of the real product as a reference. It calls `generate` with `dry_run: true` and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It sees one image sequence URL per take, and reads it with `read`. For 9:16 or 16:9, the agent runs `media` `image.resizeAspectRatio`. For 1:1 and 4:5, it cuts the shape with `image.crop` (`x`, `y`, `w`, `h`), then sets the size with `image.resizeFit` (`max_width`, `max_height`). For a grid of products, it runs `image.collage` with `image_array`. It sees a new image sequence per call. The agent makes a timeline at the static's size with `new_timeline`. It places the image with `insert_media`, adds the headline and offer with `add_text`, and styles them from the brand kit with `set_text_style`. It sees a timeline with an image and text clips. The agent runs `duplicate_timeline` once per static, swaps the image with `place_media` mode `replace`, and swaps the words with `set_text`. It sees one timeline per static. The agent calls `capture` at `0` on each timeline. It checks that the text is readable at phone size and the product is not covered. Then it runs `export` with mode `image`, `still_at` `0`, `timeline_id` and `file_name`. It sees one export card per static with status `completed`. The terminal version, for one static: ```bash invideo agent register --name export INVIDEO_AS= invideo edit export --format video --mode image \ --still-at 3.2 --file-name v01_frame_3s --json invideo gen models --query "product image for an ad" invideo gen model --model nanobanana_pro invideo gen run --model nanobanana_pro --dry-run \ --input static-inputs.json invideo gen run --model nanobanana_pro \ --max-credits --idempotency-key brewly-static-01 \ --input static-inputs.json invideo media image.crop --x 420 --y 0 --w 1080 \ --h 1080 --idempotency-key brewly-static-01-crop invideo media image.resizeFit --max-width 1080 \ --max-height 1080 --idempotency-key brewly-static-01-fit invideo edit new --name "Statics 1x1" --width 1080 \ --height 1080 invideo edit show --json invideo edit change --timeline T1 --token \ --operations @layout-1x1.json invideo edit capture --at 0 --out ./frames invideo edit export --format video --mode image \ --still-at 0 --file-name v01_static1_1x1 --json invideo status --wait invideo notebook show --out ./statics ``` The file `static-inputs.json` holds the model's inputs alone, as `get_model` lists them, with no `inputs` wrapper. It carries the list the `-i` flags cannot carry. The dry run and the paid run pass the same file. `` is the sequence URL of the real product still, from the still export or `add_media`. ```json { "prompt": "Brewly can on a sunlit counter, clean, warm", "aspect_ratio": "4:5", "reference_images": [""] } ``` Where the values come from: `` is the video's timeline URL, from `invideo edit new` or `invideo notebook show `. `` comes from `invideo project new`. `` is the name you choose in `invideo agent register`, and `` is a notebook page from `invideo notebook show `. `` is the statics timeline from `invideo edit new`, and `` comes from `invideo edit show`. `` is the dry run's `estimated_credits`. `` is the image the paid run returns, and `` is what `image.crop` returns. `` is `.sequences[0]` of what each export returns. The layout of one 1:1 static is the ops file `layout-1x1.json`, a bare list. The image goes on `V1` and the text on `V3`, the Titles track of a new timeline. The text runs for one second, and the export takes the still at `0`. ```json [ { "op": "insert_media", "asset": "", "track": "V1", "at_f": 0, "ripple": false }, { "op": "add_text", "track": "V3", "start_f": 0, "end_f": 30, "text": "Cold brew in 30 seconds", "style": { "font_size": 88, "font_weight": 700, "color": "#ffffff", "shadow": true } } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: each new image from a model, and an `image.upscale` if a still needs more pixels. - Free: stills from `export` mode `image`, the layouts and every export. - `video.extractFrameAtTime`, `image.crop`, `image.resizeFit`, `image.resizeAspectRatio` and `image.collage`: the dry run shows the price before anything starts. Stills and layouts take a few minutes per static. Run a large batch in parts, one video at a time, and check each part before the next. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems come from a blurry still or a size the op does not take. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `image.resizeAspectRatio` refuses 1:1 or 4:5 | It takes 16:9 and 9:16. Use `image.crop`, then `image.resizeFit`. | | A still is blurry | Pick a frame with less motion from `capture`, or run `image.upscale` with `dry_run` first. | | The generated image shows a fake product | Pass the real product still in `reference_images`, or use a real still instead. | | `export` mode `image` refused | It needs `still_at`. Add the time in seconds. | | Text covers the product | Move the text with `set_position`, or make it smaller with `set_text_style`. | | The folder is empty after `invideo status` | `invideo status` does not download. Run `invideo notebook show --out ./statics`. | | The saved image has a fixed name, not the `file_name` | `notebook show` saves under a fixed name. Rename each file to the scheme name. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: making every static at once | Instead: do one video, get the person's OK, then run the rest in parts. | | Avoid: a new layout for each static | Instead: `duplicate_timeline` from the approved layout, and swap image and words. | #### Prompts to try Each prompt is a real variation of this job. ```text Take the 3 best frames from video 4, put each of my 3 offers on them, and export 9 statics in 4:5. ``` ```text Make a 1:1 collage of my 4 flavors from the product stills, with the headline "Pick your morning", and export it. ``` ```text The headline on all 1:1 statics changes to "Now in 8 flavors". Change it on every layout and export version 2. ``` #### When to use something else invideo exports a still from a timeline. It does not make layered design files. For a static that a designer will keep editing, with layers and smart objects, use Figma, Canva or Photoshop, and bring the final image back in. For dynamic product ads that pull from a catalog, use the ad platform's own catalog ads. #### Related - [Make performance ads for Meta, TikTok and YouTube, named and iterated from results](/how-to/marketing/performance-ads) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Make a brand ad film from a brief, with generated shots and your real product](/how-to/marketing/brand-ad-film) - [Thumbnail](/how-to/creators/thumbnail) - [CSV to videos](/how-to/developers/csv-to-videos) ### Cut a customer testimonial or raw creator footage into an ad Source: https://docs.invideo.io/how-to/marketing/testimonial-to-ad.md Turn a customer interview or raw UGC footage into a 30 second ad, with the best lines picked from the transcript, b-roll, a name title, captions and music. Cut a customer testimonial, a customer story interview or raw creator footage (UGC) into a 30 second ad. Your agent transcribes the talk, picks the strongest lines by reading it, cuts out the rest, covers the jumps with b-roll, adds the speaker's name and captions, and lays music under the voice. From the same footage it can cut the case study set: a 30 second ad, a 60 second story and a 15 second cutdown, each on its own branch. This is ordinary ad work for a real customer and a real product. The agent cuts the footage you have the rights to. You get the customer's release, and you switch the ad on in the ad platform. The agent never publishes an ad or sends an email. Use invideo for this when the cut should come from the customer's own words: the agent reads every word with its time, so you can ask for "the line about saving time" instead of scrubbing. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Here is a 20 minute interview with my customer Dana Ruiz, Ops Lead at Fieldwork: ./interview.mp4. Transcribe it, pick the 4 strongest lines about the problem, the switch and the result, and cut a 30 second ad. Cover the jumps with the b-roll in ./broll, add her name and title, captions, and music under her voice. Show me the lines you picked before you cut. ``` In a chat app, you drag the interview and b-roll into the project. In a terminal, the agent uploads them from the folders you name. #### What you need The agent needs the footage and the facts about the speaker. - The interview or the raw creator footage, with clear sound. - B-roll: the product in use, the customer's place, screen recordings. - The speaker's name and title, spelled the way they want. - The customer's signed release for ads. You keep this; the agent does not check it. - The shape: 9:16 for Reels and TikTok, 1:1 or 4:5 for feeds, 16:9 for YouTube. - The mood of the music. #### Steps The agent picks lines by reading, and shows you the picks before it cuts. The agent prices `audio.transcript` on the interview's sequence URL with `dry_run`, tells you the price, starts it with `max_credits` set to that price, and calls again after `retry_after_s` for the words. It sees every word with its time and speaker, so it can skip the interviewer's questions. The agent reads the transcript and picks lines for a simple arc: the problem, the switch, the result, and a line to close. It lists each pick with its start and end time and the exact words. You approve or swap them. It sees your answer in the chat. The agent makes the timeline with `new_timeline` and branches with `timeline_history`, naming the branch `ad-30`. It places each picked line with `place_media` and `linked_audio` set to true, in story order. To trim inside a line, it uses `split_clip` and `delete_clip` with mode `close_gap`. It sees a talk track about 30 seconds long. The agent places b-roll above each cut with `place_media` mode `place_on_top`, so the voice runs on under it. It sees b-roll clips on the track above the talk. The agent adds a name title with `add_text` in the first seconds the speaker is on screen: name on one line, title and company on the next. It runs `audio.transcript` on the cut's talk clips for word times, or reuses the first transcript, and adds captions with `add_captions`. It sees a text clip and a caption clip. The agent runs `find_models` with the mood in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_music_v2_5_instrumental`. It calls `generate` with `dry_run: true`, a `prompt` and a `duration` of 30, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It reads the sequence URL it gets back with `read`, places the track on `A2`, adds the `ducker` audio effect, and fades the music out with `set_audio_fades`. A new timeline ducks under `A1` (Voice) by default. It sees a sequence URL for the music, then the music clip and the effect. The agent calls `capture` at each cut, the name title and the end card. It runs `media` `audio.loudness` on the interview source, and `check_timeline`. Then it runs `export` with a `target_lufs` for the platform. It sees an export card with status `completed`. For the case study set, the agent creates one branch per cut from the approved 30 second branch: `story-60` with more lines and `cut-15` with the one best line. Each branch exports on its own. The terminal version: ```bash invideo agent register --name export INVIDEO_AS= invideo asset upload ./interview.mp4 ./broll/*.mp4 invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo edit new --name "Fieldwork testimonial" \ --width 1080 --height 1920 invideo edit show --json invideo branch new --name ad-30 --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @cut-30.json invideo gen models --query "warm instrumental music bed" invideo gen model --model elevenlabs_music_v2_5_instrumental invideo gen run --model elevenlabs_music_v2_5_instrumental \ --dry-run -i prompt="warm hopeful acoustic" -i duration=30 invideo gen run --model elevenlabs_music_v2_5_instrumental \ --max-credits --idempotency-key fieldwork-music-v1 \ -i prompt="warm hopeful acoustic" -i duration=30 invideo edit capture --at 0.5,3,8,15,22,29 \ --out ./frames invideo edit export --format video --quality 1080 \ --target-lufs -14 --file-name fieldwork_ad30_9x16_v1 --json invideo status --wait invideo notebook show --out ./out mv ./out/export.mp4 ./out/fieldwork_ad30_9x16_v1.mp4 ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`, and `` is a notebook page from `invideo notebook show `. `` is the `url` that `invideo asset upload` returns for the interview. `` comes from `invideo edit show` on the edit, and on the branch from `invideo edit show `. The main token is stale there. `` is the `branch_url` that `invideo branch new` returns. Each `` is its dry run's `estimated_credits`. `` is `.sequences[0]` of what the export returns. `invideo status` does not download, and the saved file is always `export.mp4`. The ops file `cut-30.json` is a bare list. It holds two picked lines, a name title and the ducker on the music, at 30 frames a second. A new timeline has `V1` (A-roll), `V2` (B-roll), `V3` (Titles), `A1` (Voice) and `A2` (Music). ```json [ { "op": "place_media", "asset": "", "track": "V1", "at_f": 0, "source_start_seconds": 312.4, "source_end_seconds": 318.9, "mode": "append", "linked_audio": true }, { "op": "place_media", "asset": "", "track": "V1", "at_f": 195, "source_start_seconds": 744.0, "source_end_seconds": 751.2, "mode": "append", "linked_audio": true }, { "op": "add_text", "track": "V3", "start_f": 15, "end_f": 105, "text": "Dana Ruiz\nOps Lead, Fieldwork", "style": { "font_size": 44, "align": "left", "shadow": true } }, { "op": "add_audio_effect", "target": "A2", "target_kind": "track", "effect": "ducker" } ] ``` The ducker reacts to `A1` (Voice), the default sidechain source of a new timeline. If the voice sits on another track, the agent adds `set_sidechain_source` with `timeline` `T1` and that track. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: the transcript of the interview, paid stock music or a generated track, and `audio.clean` if the voice needs it. - Free: picking lines, every cut, b-roll placement, titles, captions, `capture` and every `export`. - `audio.loudness`: the dry run shows its price before anything starts. A 30 second ad from a long interview takes under an hour, most of it your review of the picks. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are a line cut mid-word or music that buries the voice. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | You want stock music instead | Run `search_library` in `stock_music`, and bring the pick in with `add_media`. | | A line starts or ends mid-word | Use the word times from the transcript, and trim with `trim_clip` to the word's edge. | | The jump in the face is visible | Cover the cut with b-roll on the track above, or add a short `cross_zoom` transition with `add_transition`. | | The interviewer's voice is in the cut | Check the speaker of each word in the transcript, and cut those spans. | | Music drowns the voice | Check that the voice is on `A1`, or point `set_sidechain_source` at the track it is on. Raise the ducker's `reduction` with `set_audio_effect_parameter`, using its id from `get_timeline`. | | A noisy room | Run `media` `audio.clean` on the interview with `dry_run` first. It makes a new file; the original stays. | | The transcript call returns a status, not words | It is still running. Call again with the same file after `retry_after_s`. Only the first call costs credits. | | The download folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./out`. | | CLI exit 3 on the branch | The token is the main timeline's. Run `invideo edit show ` and use its token. | | Avoid: changing what the customer meant | Instead: keep each line whole in meaning. Show the person every pick with its words. | | Avoid: editing main | Instead: one branch per cut with `timeline_history`. | #### Prompts to try Each prompt is a real variation of this job. ```text Here are 6 raw selfie clips from a creator. Find the best hook in the first sentence of each, and cut a 20 second UGC ad that opens on the best one. ``` ```text From the approved 30 second ad, make the case study set: a 60 second story and a 15 second cutdown, one branch each, same music and look. ``` ```text Pull every line where the customer says a number, like hours saved or money saved, with timecodes. Do not cut anything. ``` #### When to use something else invideo does not get releases or check claims. Get the customer's written release for ads, and check that any number they say is true before it runs. For a filmed interview with lights and two cameras, hire a videographer, then bring the footage in. For a full long-form documentary edit, see the documentary and interview page. #### Related - [Documentary and interview edit](/how-to/film/documentary-and-interview-edit) - [Make a UGC ad from product photos with an AI actor](/how-to/marketing/ugc-ad-with-ai-actor) - [Word-by-word captions](/how-to/creators/word-by-word-captions) - [Music and sound effects](/how-to/creators/music-and-sound-effects) - [Make performance ads for Meta, TikTok and YouTube, named and iterated from results](/how-to/marketing/performance-ads) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) ### Make an Amazon listing or Sponsored Brands video ready for moderation Source: https://docs.invideo.io/how-to/marketing/amazon-listing-video.md Make an Amazon product listing video or Sponsored Brands video ad with the real product, no claims you cannot back, faces and labels blurred, and a pre-flight check. Make a product video for an Amazon listing or a Sponsored Brands video ad, the kind Amazon reviews before it runs. Your agent cuts real footage of your product, keeps claims to what you can back, blurs faces and other brands' labels, and checks the cut against Amazon's rules in words before export. Amazon makes the final call in its own review, and this page does not promise approval. This is ordinary ad work for a real product. The agent makes the file. You upload it in Seller Central or the Amazon Ads console and launch the campaign there. The agent never publishes, never launches a campaign and never sends an email. Use invideo for this when you want to fix a rejection in minutes: the video stays an editable timeline, so a cut, a blur or a text change is an edit and a free export, not a new shoot. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a Sponsored Brands video for our Brewly cold brew from the clips in ./product. Real product only, no prices or deals, no star ratings, and only these claims: "brews in 12 hours", "no sugar added". Blur any face and any other brand's label. Check it against Amazon's rules and show me the first and last frame and a frame at every cut before you export. ``` In a chat app, you drag the clips into the project. In a terminal, the agent uploads them from the folder you name. #### What you need The agent needs real footage and your list of claims. - Footage or photos of the real product, the same one buyers get. - The claims you can back, word for word. Anything not on this list stays out. - Where it runs: the product listing, or a Sponsored Brands video ad. - The marketplace, so on-screen text and voice match its language. - Amazon's own pages. For Sponsored Brands video, read Sponsored Brands video creative. For listing videos, read the video rules in Seller Central help, behind your seller sign-in. #### Amazon's rules in words Amazon publishes its rules and changes them, so the agent reads the pages on the day. These are the points that most often matter for video, from Amazon's pages. The length, size, frame rate and file format are on the spec page; check the page, because this page gives no numbers. - **Shape.** Sponsored Brands video asks for widescreen, with no black, colored or blurred bars at the sides or top. Keep text out of the lower-right corner. - **Language.** Spoken words and on-screen text match the marketplace's language. - **Claims.** No claim you cannot back. No customer reviews or star ratings in the video. - **Offers.** No prices, deals, discounts or savings in the video. - **Amazon itself.** No Amazon logos or references to Amazon. - **Quality.** No black or blank frames at the start or end, no abrupt ending, no flashing effects, and text that is easy to read against its background. - **Sound.** No sudden jumps in volume and no harsh sounds. The moderation guide has the full list: A complete guide to Sponsored Brands and display ads moderation. The policies are on Sponsored ads guidelines and acceptance policies. #### Steps The agent builds on a branch, blurs what must not show, and checks before export. The agent uploads the clips with `start_upload` and `add_media`, or `invideo asset upload`. It looks at each with `media` `video.frames`. It sees one sequence per clip. The agent makes a widescreen timeline with `new_timeline` and branches with `timeline_history`. It places the shots with `place_media`, product first. It adds only your approved claims with `add_text`. It sees a new `state_token`. The agent looks at frames for faces and other brands' labels. It runs `find_models` with the job in words and reads the pick's inputs with `get_model`. A good pick is `object_track`, with `points` on the object, the `time` of that frame, and `output` set to `matte`. It calls `generate` with `dry_run: true` and tells you the price, then runs with `max_credits` set to that price and an `idempotency_key`. It sees a sequence URL for a black-and-white matte video, white where the object is, and reads it with `read`. The agent places the matte on its own track above the shot. It places a copy of the shot on the track between, adds `gaussian_blur` and `track_matte_key` to the copy with `add_effect`. In a second call, with the key's id from `get_timeline`, it points the key at the matte's track with `set_matte_source` and sets its `mode` to `luma` with `set_effect_parameter`. It sees the blur only where the face or label was. The agent adds music from `search_library` in `stock_music`. For a voice in the marketplace's language, it runs `find_models` with the job in words, reads `elevenlabs_text_to_speech.elevenlabs_tts_v4` with `get_model` and finds a `voice_id` with `search_library` in `elevenlabs_text_to_speech_voices`. It calls `generate` with `dry_run: true`, the script as `prompt` and that `voice_id`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It checks each source with `media` `audio.loudness`. It sees a sequence URL for the voice and reads it with `read`. It never calls `generate` again to check. The agent calls `capture` at `0`, at one frame before the end, at every cut and every text. It checks the list above: no black first or last frame, no bars, no text in the lower-right corner, no price, no stars, no Amazon logo, readable text. It runs `check_timeline`. It sees frames and findings, and fixes each one. The agent runs `export` with `quality` and `fps` set to what the spec page asks. It sees an export card with status `completed`, and tells you what it checked and what needs your eye. The terminal version: ```bash invideo agent register --name export INVIDEO_AS= invideo asset upload ./product/*.mp4 invideo edit new --name "Brewly SB video" --width 1920 \ --height 1080 invideo edit show --json invideo branch new --name sb-v1 --token invideo edit show --json invideo gen models --query "object matte to blur a face" invideo gen model --model object_track invideo gen models --query "text to speech voice" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --dry-run -i prompt=@voice.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key brewly-sb-voice-v1 \ -i prompt=@voice.txt -i voice_id= invideo edit change --timeline T1 \ --token --operations @blur.json invideo edit check invideo edit capture --at 0,4,8,12,14.96 --out ./frames invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out mv ./out/export.mp4 ./out/brewly_sb_v1.mp4 ``` Where the values come from: - `` is your project's URL, or what `invideo project new` returns. `` comes from `invideo edit new`. - `` is the name you choose in `invideo agent register`. `` is a notebook page from `invideo notebook show `. - `` comes from `invideo edit show `, and on the branch from `invideo edit show `; the main token is stale there. `` is the `.branch_url` that `invideo branch new` returns. - `` is an id from `search_library` in `elevenlabs_text_to_speech_voices`. `` is the dry run's `.estimated_credits`. - `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves `./out/export.mp4`. - `` is the matte's sequence URL, which the `object_track` run returns. The file voice.txt holds the script in the marketplace's language. The `object_track` input `points` is a list, so the agent sends that generation over MCP with `dry_run` first. The file `./blur.json` holds the blur as a bare list of operations; on the MCP path the same list goes in the `operations` field of `edit_timeline`. `c8` is the copy of the shot on `V2`, read from `get_timeline`, and the matte sits on `V3`, which is free over this shot. After this call the agent reads the key's effect id with `get_timeline`. In a second call it sends `set_matte_source` with `target` `c8`, that `effect` and `source_track` `V3`, and `set_effect_parameter` with `parameter` `mode` and `value` `luma`. ```json [ { "op": "place_media", "asset": "", "track": "V3", "at_f": 120, "source_start_seconds": 0, "source_end_seconds": 4, "mode": "overwrite", "linked_audio": false }, { "op": "add_effect", "clip": "c8", "effect": "gaussian_blur" }, { "op": "add_effect", "clip": "c8", "effect": "track_matte_key" } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: `object_track` or `sam_3_1_video` for each shot that needs a blur, a voice, and paid stock music. - Free: the cut, the claims, the blur effects, `capture`, `check_timeline` and `export`. A short product video takes under an hour. A fix after a rejection takes a few minutes. See [Credits](/account/credits) for prices. #### If something goes wrong Amazon's review gives a reason for each rejection. Fix that reason on a new branch and export again. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | Rejected for black frames at the start or end | Capture `0` and the last frame. Trim the empty frames with `trim_clip`. | | Rejected for bars at the sides | Run `fill_frame` on each clip so the picture covers the canvas. | | Rejected for a claim | Remove the text with `delete_clip`, or change it with `set_text` to a claim on your list. | | Rejected for language | Change the text with `set_text`, and voice it again in the marketplace's language. | | The matte clip shows in the capture | Hide its track with `set_track_hidden` and capture again. If the blur then stops, file `report_bug`. | | The blur drifts off the face | Run `object_track` again with more `points`, on a frame where the face is clear. | | An object is hard to point at for `object_track` | Run `sam_3_1_video` with words like "face, logo". It draws its masks on the video. Read those frames to pick the points, then run `object_track` for the clean matte. | | CLI exit 3 on the branch | The token is from main. Run `invideo edit show ` and use its `state_token`. | | The saved file is called `./out/export.mp4` | `notebook show` always saves `./out/export.mp4`. Rename it. | | Avoid: adding a claim the person did not give | Instead: use only the approved list. Ask before adding any line. | | Avoid: promising the video will pass | Instead: say what was checked. Amazon decides in its review. | #### Prompts to try Each prompt is a real variation of this job. ```text Amazon rejected my video for "text in the lower-right corner". Move every text clip out of that corner on a new branch, capture each, and export. ``` ```text Make a listing video for my blender from these 8 clips: what's in the box, the blades, a smoothie, cleaning. No voice, music only, my claims only. ``` ```text Blur the logo on the mug in shot 3 and the face of the person in shot 5. Price it first. ``` #### When to use something else invideo does not upload to Amazon, launch campaigns or read the review result. Upload the video in Seller Central or the Amazon Ads console. For a claim like "clinically proven" or "number one", ask your legal team for the proof before it goes in. For product photography and studio shots, book a photographer, then bring the footage in. #### Related - [Make a Shopify and TikTok Shop product video that follows the no-stills rule](/how-to/marketing/shopify-and-tiktok-shop-video) - [Turn a product photo into a video without redrawing the product](/how-to/marketing/product-photo-to-video) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Label AI content so your ad runs on TikTok, Meta and Google](/how-to/marketing/ai-disclosure-for-ads) - [Check your video before you say it is done](/how-to/check-your-video) ### Make a Shopify and TikTok Shop product video that follows the no-stills rule Source: https://docs.invideo.io/how-to/marketing/shopify-and-tiktok-shop-video.md A vertical product video for your Shopify store and TikTok Shop that moves, shows the real product, and has captions that stay off it. Make a product video, or shoppable video, for your Shopify product page and your TikTok Shop listing. You get a vertical video where the product moves, your real product stays exact, and captions sit clear of it. A slideshow of still photos with a zoom on each is the video TikTok Shop marks as low quality, so this page avoids it. Use invideo for this when you have product photos and a few phone clips, and you want your agent to add motion, captions and the right shape on an editable timeline, then hand you the file to upload. The agent never uploads to Shopify or TikTok Shop. You upload the file and publish the listing. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a vertical product video for my Shopify page and TikTok Shop from the photos and clips in ./product. No slideshow of stills: animate the photos into short moving shots, and keep my real product clip as it is. Add captions away from the product. Price the generation first and show me frames before you export. ``` In a chat app, you drag the photos and clips into the project. In a terminal, the agent names the folder and uploads the files. #### What you need These are the inputs the agent asks for. - Photos of the product, front and detail, with a plain background if you have them. - At least one real clip of the product: in a hand, in use, or on a table while the camera moves. - The words for the captions: the product name, what it does, one reason to buy. - The shape. Both stores take vertical 9:16 for this job. - A mood for the music, or no music. #### The store rules, in words The two stores have different rules. Read their own pages before you upload, because the stores change them. - **TikTok Shop** asks for videos with real on-screen activity. Its guidance names still images, screenshots, slideshows, animated content and GIF-style videos as content it does not want. It asks that the product in the video matches the product page, and that no text or stickers cover the product. Read the TikTok Shop Seller University guides on high-quality shoppable videos and on common mistakes for video content quality. - **Shopify** takes product videos as MP4, MOV or WebM files, with its own limits on length and size. See Shopify's product media types. For TikTok Shop, lead with your real footage. A clip that a model makes from a photo moves, but it is generated. Use it to support your real clip, not to replace it. #### Steps The agent works on a branch, so the main timeline stays clean until you approve. The agent makes a project with `new_project` and uploads each file with `start_upload` and `add_media`. Expected result: one sequence URL per photo and clip. The agent runs `media` `image.resizeAspectRatio` with `aspect_ratio` `9:16` on each photo. It is a tool op; the dry run shows its price before anything starts. An image-to-video model follows the shape of its first frame, so this step sets the shape of the moving shot. Expected result: a new 9:16 image sequence beside each photo. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `seedance_2_5.frames`, and `kling_v4.kling_v4_frames` gives a second look. It calls `generate` with `dry_run: true`, the 9:16 photo as its first frame and a short `prompt` for slow camera motion around the product, and tells you the price. Then it runs it with `max_credits` and an `idempotency_key`. Expected result: one sequence URL per photo, each a short moving clip. The agent reads it with `read` and never calls `generate` again to check. The agent makes a 1080 by 1920 timeline with `new_timeline` and creates a branch with `timeline_history`. It places your real clip first with `place_media`, then the generated shots, and covers the frame with `fill_frame`. It joins shots with `add_transition` type `slide` or `fade`. Expected result: a new `state_token` and a vertical cut with no still photo on screen. The agent adds safe-zone guides with `create_guide`, then the words with `add_captions`, at the top or bottom of the frame where the product is not. If your clip has speech, it first prices `audio.transcript` on the clip's sequence URL with `dry_run`, starts it, and calls again after `retry_after_s` for the word times. Expected result: a caption clip that never covers the product. The agent finds a track with `search_library` in `stock_music`, brings it into the bin with `add_media` and `stock`, places it on `A2` (Music) with `insert_media`, and sets its level with `set_audio_gain`. Expected result: music under the cut, quieter than any speech. The agent runs `capture` at each shot and `check_timeline`. It compares each frame with your product photo by eye: the shape, the color and the label must match. Then it runs `export` with `format` video, `quality` 1080 and a `file_name`. Expected result: an export card with status `completed`. The terminal version of the same job: ```bash invideo project new --title "Product video" invideo agent register --name export INVIDEO_AS= invideo asset upload ./product/* invideo media image.resizeAspectRatio \ --aspect-ratio 9:16 --dry-run invideo media image.resizeAspectRatio \ --aspect-ratio 9:16 --max-credits --idempotency-key bottle-9x16 invideo gen models --query "animate a product photo" invideo gen model --model seedance_2_5.frames invideo gen run --model seedance_2_5.frames --dry-run \ -i prompt="slow orbit around the bottle" -i first_frame= invideo gen run --model seedance_2_5.frames \ --max-credits --idempotency-key bottle-orbit-v1 \ -i prompt="slow orbit around the bottle" -i first_frame= invideo edit new --name "Product 9x16" \ --width 1080 --height 1920 invideo edit show --json invideo edit change --timeline T1 --token \ --operations @ops.json invideo edit capture --at 1,4,8,12 --out ./frames invideo edit export --format video --quality 1080 \ --file-name product-9x16 --json invideo status --wait invideo notebook show --out ./out mv ./out/export.mp4 ./out/product-9x16.mp4 ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`, and `` is a notebook page from `invideo notebook show `. `` is the `url` that `invideo asset upload` returns for a photo. `` is the 9:16 photo that `image.resizeAspectRatio` returns. Each `` is the dry run right before it. `` comes from `invideo edit show`. `` is `.sequences[0]` of what the export returns. `invideo status` does not download; `invideo notebook show` saves the file as `export.mp4`. The key edit puts the real clip first, fills the frame, and adds a caption at the bottom. This is `ops.json`, a bare list. At 30 fps, frame 90 is 3 seconds. ```json [ { "op": "place_media", "asset": "m1", "track": "V1", "at_f": 0, "source_start_seconds": 0, "source_end_seconds": 3, "mode": "overwrite", "linked_audio": false }, { "op": "fill_frame", "clip": "c1" }, { "op": "create_guide", "timeline": "T1", "orientation": "horizontal", "position": 0.8, "locked": true }, { "op": "add_captions", "track": "V3", "slides": [ { "text": "Keeps drinks cold all day", "start_f": 0, "end_f": 90 } ] } ] ``` The media bin id `m1` comes from `invideo edit show` with `--mode collection --collection asset`. The clip id `c1` is the one `place_media` makes in the same call. The guide marks where the store's buttons sit, so the agent keeps the captions above it. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: every timeline edit, `capture` and `export`. - `image.resizeAspectRatio`: the dry run shows its price before anything starts. - Costs credits: each image-to-video take, `audio.transcript` if your clip has speech, and stock music. One video takes under an hour, most of it the generation. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are a redrawn product or text in the wrong place. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The generated shot changes the product | Reject the take. Generate again with a shorter motion prompt, or use your real clip for that shot. | | The generated shot comes out 16:9 | The first frame was not 9:16. Run `image.resizeAspectRatio` first, then generate again. | | A file is missing from the folder | Name the missing file and ask the person for it. | | A caption covers the product | Move the caption clip with `set_position`, or restyle it with `set_text_style`. Capture again. | | `timeout` on `generate` | Do not call it again. `read` the thread or call `status`. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` and rebuild the ops. | | The download folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./out`. | | CLI exit 5 | Credits ran out. Stop and tell the person. | | Avoid: a slideshow of stills with zooms | Instead: real clips and moving shots. TikTok Shop names slideshows as low quality. | | Avoid: saying done without frames | Instead: `capture` each shot and compare it with the product photo. | #### Prompts to try Each prompt is a real variation of this job. ```text I only have three photos of the candle. Animate each into a slow push-in, show me the takes, and keep the label exact. Vertical, with captions. ``` ```text Cut my unboxing clip to 20 seconds for TikTok Shop. Captions at the top, no text over the product, light music. ``` ```text Make the same video in 9:16 for TikTok Shop and 1:1 for my Shopify page, one branch each. ``` #### When to use something else invideo does not upload to Shopify or TikTok Shop, and it does not check a listing against the store's rules. You upload the file in Shopify admin or TikTok Shop Seller Center and read their review result there. For a live shopping stream, use TikTok LIVE itself. For product photos you do not have, shoot them on a phone first: a model works best from a real photo. #### Related - [Turn a product photo into a video without redrawing the product](/how-to/marketing/product-photo-to-video) - [Make an Amazon listing or Sponsored Brands video ready for moderation](/how-to/marketing/amazon-listing-video) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Label AI content so your ad runs on TikTok, Meta and Google](/how-to/marketing/ai-disclosure-for-ads) - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Make a video sales letter with slides Source: https://docs.invideo.io/how-to/marketing/video-sales-letter.md Turn your sales script into a video sales letter (VSL) as text slides, stock b-roll or a talking avatar, with a voiceover and captions. Turn your sales script into a video sales letter, or VSL: a long sales video that reads your offer out loud. You pick one of three styles. Slides show your words on screen, b-roll shows stock footage under the voice, and an avatar shows a presenter who speaks the script. Every style gets a voiceover, captions and an editable timeline. Use invideo for this when you want to change one line of the script later and re-render that part, without rebuilding a long video. You write or approve the script. Your agent never invents claims, prices or guarantees for your offer. The agent never publishes the video. You upload it to your video host or funnel builder. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a video sales letter from script.md in the b-roll style. Voice it with a confident narrator, show me the voice preview first. Stock b-roll for each section, captions at the bottom, 16:9. Price everything before you spend, and show me frames before you export. ``` In a chat app, you paste the script or drag the file into the project. In a terminal, the agent names the file. #### What you need These are the inputs the agent asks for. - The script, final or close to final. Mark the sections: hook, problem, offer, proof, call to action. - The style: slides, b-roll or avatar. - For slides: your deck as a PDF, or permission for the agent to make text slides on the timeline. - For an avatar: a front-facing photo of a presenter who agreed to it, or a generated presenter. - A voice. The agent finds one with `search_library` and sends you the preview. - The shape. A VSL is usually 16:9. #### Steps The agent works on a branch, so the main timeline stays clean until you approve. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a voice from `search_library` in `elevenlabs_text_to_speech_voices`, because a voice id works only with its own model. It sends you the voice preview. It calls `generate` with `dry_run: true`, one section as `prompt` and the `voice_id`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, one take per section. Expected result: one sequence URL per section, which the agent reads with `read`. The agent prices `audio.transcript` on each voice take's sequence URL with `dry_run`, starts it with `max_credits` set to that price, and calls again after `retry_after_s` for the words. Expected result: every word with its start and end time. For slides, the agent uploads the PDF with `start_upload` and `add_media`, then runs `media` `document.pages` for one image per page; the dry run shows its price before anything starts. For b-roll, it searches `search_library` in `stock_video` with words from each section and brings the picks in with `add_media` and `stock`. Expected result: picture sequences for every section. For the avatar style, the agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `heygen_photo_avatar`, and `kling_avatar.std` is another. It calls `generate` with the presenter photo as `image`, a voice take as `audio` and `dry_run: true`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL and, when the clip lands, a sequence URL, which the agent reads with `read`. The agent makes a 16:9 timeline with `new_timeline` and creates a branch with `timeline_history`. It places each voice take on an audio track with `insert_media`, and each slide, b-roll shot or avatar clip above it with `place_media`. It sets each picture's length to its line with `trim_clip`. Expected result: a new `state_token` and no gap under the voice. The agent adds the words with `add_captions`, slides and words from the transcript, frames at the timeline rate. For the slides style, it adds key lines as text with `add_text`. Expected result: a caption clip on a video track above the picture. The agent runs `capture` at each section start and `check_timeline`, and reads the captions against your script. Then it runs `export` with `format` video. Expected result: an export card with status `completed`. The terminal version, b-roll style: ```bash invideo project new --title "VSL" invideo agent register --name export INVIDEO_AS= invideo library search \ --library elevenlabs_text_to_speech_voices --query "confident narrator" invideo gen models --query "confident narration voice" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --dry-run -i prompt=@hook.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key vsl-hook-v1 \ -i prompt=@hook.txt -i voice_id= invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo library search --library stock_video \ --query "tired office worker at desk" invideo edit new --name "VSL v1" invideo asset add --stock invideo edit show --json invideo edit change --timeline T1 --token \ --operations @vsl-layout.json invideo edit capture --at 2,60,240,600 --out ./frames invideo edit export --format video --quality 1080 \ --start 0 --end 600 --idempotency-key vsl-part-1 --json invideo status --wait invideo media video.stitch \ --video-array , --dry-run invideo media video.stitch \ --video-array , \ --max-credits --idempotency-key vsl-stitch-v1 invideo status --wait invideo notebook show --out ./out ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`, and `` is a notebook page from `invideo notebook show `. `` comes from the voice search, and each `` is the dry run right before it. `` is the sequence URL from the voice run. `` comes from the stock search. `` comes from `invideo edit show`. `` and `` are the card URLs, `.sequences[0]` of what each part's export returns. `` is the sequence URL `video.stitch` returns. `invideo status` does not download; `invideo notebook show` saves the file as `export.mp4`. The key edit is the ops file `vsl-layout.json`, a bare list. It places a voice take on `A1` (Voice), a stock shot on `V2` (B-roll), and a caption slide on `V3` (Titles). The media bin ids `m1` and `m2` come from `invideo edit show` with `--mode collection --collection asset`. At 30 fps, frame 300 is 10 seconds. ```json [ { "op": "insert_media", "asset": "m1", "track": "A1", "at_f": 0, "ripple": false }, { "op": "place_media", "asset": "m2", "track": "V2", "at_f": 0, "source_start_seconds": 0, "source_end_seconds": 10, "mode": "overwrite", "linked_audio": false }, { "op": "add_captions", "track": "V3", "slides": [ { "text": "You work late every night", "start_f": 0, "end_f": 75 } ] } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: every timeline edit, `capture` and `export`. - `document.pages` and `video.stitch`: the dry run shows the price before anything starts. - Costs credits: the TTS voice, `audio.transcript`, each stock shot, and the avatar model, which charges by the length of the audio. A short letter takes under an hour. A long avatar letter takes longer, most of it the avatar generation. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are timing between the voice and the picture. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The picture changes before the line ends | The picture clip is shorter than its voice take. Trim its tail to the take's end with `trim_clip`. | | The avatar's mouth drifts from the voice | Generate the section again from one voice take. Do not stretch the avatar clip. | | A long letter needs more than one export | Export in parts with `start` and `end` in seconds, one `idempotency_key` each, then join the parts with `media` `video.stitch`. Each export card is a sequence, so `video.stitch` takes their URLs as they are. | | A caption word is wrong | Fix it with `set_caption_slide_text`. The transcript hears the voice, not the script. | | `audio.transcript` returns a status, not words | It is still running. Call again with the same file after `retry_after_s`. | | `timeout` on `generate` | Do not call it again. `read` the thread or call `status`. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` and rebuild. | | The download folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./out` on the card URL. | | CLI exit 5 | Credits ran out. Stop and tell the person. | | Avoid: one export of a very long letter that keeps failing | Instead: export in parts with `start` and `end`, then `video.stitch`. | | Avoid: writing new claims into the script | Instead: ask the person. The script is theirs. | #### Prompts to try Each prompt is a real variation of this job. ```text Make a slide-style VSL from offer.pdf. One page per section, my script below as the voiceover, captions on. Keep each slide up while its line plays. ``` ```text Use this photo of me as a talking avatar for the hook and the call to action, and stock b-roll for the middle. Same voice throughout. ``` ```text Change the price line in section 4 of my VSL to the new offer, voice only that line again, and re-export. ``` #### When to use something else invideo does not host the video, gate it behind an email form, or show a buy button under it. Upload the MP4 to your video host or funnel builder for that. For a presenter avatar from a full video of yourself, use HeyGen or Synthesia, then bring the clip in with `start_upload`. If you need a script from scratch, write it with your own copywriter or agent first, then start here. #### Related - [Turn slides into a narrated video, one deck or hundreds](/how-to/training/slides-to-narrated-video) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Update one line and re-render, keep the rest](/how-to/training/update-one-line) - [Label AI content so your ad runs on TikTok, Meta and Google](/how-to/marketing/ai-disclosure-for-ads) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Turn a webinar replay into an evergreen video with a CTA and chapters Source: https://docs.invideo.io/how-to/marketing/webinar-replay-to-evergreen.md Turn a long webinar recording into an evergreen replay with the dead air and waiting room cut, a call-to-action card, chapters and captions. Turn a webinar recording, or a live session replay, into an evergreen video people watch on demand. Your agent cuts the dead air: the waiting room, "can you hear me", long pauses and the tech fumbles. It adds a call-to-action (CTA) card, chapter markers with a chapter list, and captions, which some people call subtitles. Use invideo for this when the recording is long and every cut must stay reversible: the cuts are timeline edits on a branch, so you can put a section back in the editor. The agent never publishes the replay or emails your list. You do that. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Turn webinar.mp4 into an evergreen replay. Cut the waiting room, the sound checks and every pause longer than two seconds. Add a CTA card for the demo link at the end and after the offer, chapter markers, a chapter list for YouTube, and captions. Price the transcript first. ``` In a chat app, you drag the recording into the project. In a terminal, the agent names the file and uploads it. #### What you need These are the inputs the agent asks for. - The recording as an MP4 or MOV file, from Zoom, Teams, Webex or your webinar tool. - The CTA: the words and the link to show, like "Book a demo at acme.com/demo". - Where the CTA goes: at the end, after the offer, or both. - What to keep from the Q and A, or all of it. - The shape. Webinars are 16:9. #### Steps The agent works on a branch, so the main timeline stays clean until you approve. A webinar file is large, so the agent calls `start_upload` with the file name, PUTs the bytes to the `upload_url`, then calls `add_media` with the `upload_id`. Expected result: a sequence URL for the recording. The agent prices `audio.transcript` on the recording's sequence URL with `dry_run` and tells you the price. Then it starts it with `max_credits` set to that price, and calls again after `retry_after_s` for the words. It pages through the words with `offset`. Expected result: every word with its time and speaker. The agent runs `media` `audio.content` for the silence spans. It reads the transcript for the waiting room, the sound checks and the "give everyone a minute" lines. It lists the spans to cut with their times and shows you the list. Expected result: your yes, or your changes. The agent makes a 16:9 timeline with `new_timeline`, creates a branch with `timeline_history`, and places the recording with `place_media` and `linked_audio` true. It cuts each span with `edit_time_range` and mode `close_gap`, from the last span to the first, so the earlier times stay true. Expected result: a new `state_token` and a shorter timeline. The agent adds a marker at each topic change with `add_marker`, with a `name` for the chapter. It adds the CTA as a text card with `add_text`, with a background color and your brand colors in its `style`. Expected result: markers on the timeline and a CTA clip on its own track. The agent moves each transcript word earlier by the time cut before it, then adds the words with `add_captions`. Expected result: a caption clip that matches the speech after the cuts. The agent runs `capture` at each cut, each CTA and each chapter start, and `check_timeline`. It checks every cut edge against the transcript's word times, so no cut lands inside a word. Then it runs `export` with `format` video and `target_lufs`, and runs `audio.waveform` on the export card to see that no gap or click is left. Expected result: an export card with status `completed`, and the chapter list in the chat. The terminal version of the same job: ```bash invideo project new --title "Webinar replay" invideo agent register --name export INVIDEO_AS= invideo asset upload ./webinar.mp4 invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo media audio.content invideo edit new --name "Replay v1" invideo edit show --json invideo branch new --name evergreen --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @cut-list.json invideo edit show --mode collection --collection marker invideo edit capture --at 0,300,1200,2400 --out ./frames invideo edit export --format video --quality 1080 \ --target-lufs -14 --json invideo status --wait invideo notebook show --out ./out ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`. `` is the `url` that `invideo asset upload` returns for the recording. `` is the dry run's `estimated_credits`. `` comes from `invideo edit show` on the edit, and on the branch from `invideo edit show `. The main token is stale there. `` is the `branch_url` that `invideo branch new` returns. `` is `.sequences[0]` of what the export returns. `invideo status` does not download; `invideo notebook show` saves the file as `export.mp4`. The key edit is the ops file `cut-list.json`, a bare list. It cuts one span, marks a chapter and adds the CTA card. At 30 fps, frame 1800 is one minute. ```json [ { "op": "edit_time_range", "timeline": "T1", "start_f": 0, "end_f": 5400, "mode": "close_gap" }, { "op": "add_marker", "at_f": 9000, "name": "Pricing", "color": "#ffaa00" }, { "op": "add_text", "track": "V3", "start_f": 54000, "end_f": 54450, "text": "Book a demo: acme.com/demo", "style": { "font_size": 64, "color": "#ffffff", "background_color": "#1a56dbcc", "align": "center" } } ] ``` The agent sends the cuts in one `edit_timeline` call. They land all together, or none do. ##### The chapter list The agent reads the markers with `get_timeline` mode `collection` and `collection` `marker`. It writes one line per marker: the time as minutes and seconds, then the name. YouTube reads chapters from a list like this in the description. The list starts at 00:00 and goes in order, and each chapter has a minimum length. See YouTube's video chapters help. ```text 00:00 Welcome and agenda 03:10 Why most onboarding fails 11:45 The three-step fix 24:30 Pricing 31:05 Q and A ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: the upload, every cut, marker, CTA and caption edit, `capture` and `export`. - `audio.content` and `audio.waveform`: the dry run shows the price before anything starts. - Costs credits: `audio.transcript`, once per file. Later calls to follow it cost nothing. The upload and transcript of a long webinar take a while. The cuts take a few minutes. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are times that moved after a cut. | Symptom | Fix | | --- | --- | | A later cut lands in the wrong place | The cuts went first to last, so times moved. Read the timeline again and cut from the last span to the first. | | Captions run ahead of the speech | The word times were not moved for the cuts before them. Recompute and replace the caption clip. | | A word is cut in half | Move the span's edge to the gap between words from the transcript, then cut again. | | `audio.transcript` returns a status, not words | It is still running. Call again with the same file after `retry_after_s`. | | The upload PUT fails | Call `start_upload` again for a new `upload_url`, and PUT once more. | | `unavailable` | The timeline is starting. Retry the same request in a few seconds. | | CLI exit 3 | The edit changed since your read, or the token is the main timeline's. Run `invideo edit show ` and rebuild. | | The download folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./out`. | | CLI exit 7 | Nothing ran. Run the same command again. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | Avoid: cutting on main | Instead: create a branch, so the full recording stays one click away. | #### Prompts to try Each prompt is a real variation of this job. ```text Cut this webinar to the 20-minute core talk only. Drop the Q and A. Add a CTA card every ten minutes and at the end. ``` ```text Keep the Q and A, but cut any question nobody answered and every pause over three seconds. Give me the chapter list for YouTube. ``` ```text Make the evergreen replay, then a second branch with only the demo section and the CTA, for a short follow-up. ``` #### When to use something else invideo does not run the webinar, host the replay page, or send the follow-up emails. Use your webinar tool for the live session, and your video host or email tool to publish and send. A clickable button inside the player comes from your video host. In invideo, the CTA is text on screen. #### Related - [Cut ums, pauses and retakes, as reversible timeline edits](/how-to/creators/cut-ums-and-retakes) - [Edit a long YouTube video: cut the dead parts, add b-roll, music and captions](/how-to/creators/edit-a-long-youtube-video) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Edit a podcast episode and pull clips from it](/how-to/creators/podcast-edit-and-clips) - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Make a personalized video for every prospect from one recording Source: https://docs.invideo.io/how-to/marketing/sales-outreach-video.md Record one sales video, then get one copy per prospect with their name, their company and their website on screen, each as its own MP4. Record one sales outreach video, or prospecting video, and get a personalized copy for every prospect on your list. Each copy shows the prospect's name and company as text, and a screenshot of their website beside you. Each one is its own MP4, named for the prospect, ready to attach or link in your email. Use invideo for this when you want one template timeline and a copy per row, so a fix to the template is one edit and every copy stays editable. Your agent never sends the emails or messages. You send them from your own email or sales tool. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Use pitch.mp4 as the template. For each row in prospects.csv, make a copy with "Hi {first_name}" and the company name on screen, and a screenshot of their website on the right for the first ten seconds. Export one MP4 per prospect named by company. Do five, show me, then do the rest. ``` In a chat app, you drag the recording and paste the list into the chat. In a terminal, the agent reads the CSV and the folder. #### What you need These are the inputs the agent asks for. - One recording of you, talking to the camera. Leave space on one side for the screenshot, and keep your opening line general, like "Hi there". - The prospect list as a CSV: first name, company, website. - The text to show, like "Hi Priya, this one is for Acme". - How long the screenshot stays on screen. - The shape. 16:9 is usual for email. Use 1:1 or 9:16 for LinkedIn messages. #### Steps The agent builds the template once on a branch, then copies it per prospect. The agent makes a project with `new_project`, uploads the recording with `start_upload` and `add_media`, and keeps the prospect list in a brief made with `new_brief`. Expected result: a sequence URL for the recording and a brief URL. The agent makes a timeline with `new_timeline` and creates a branch with `timeline_history`. It places the recording with `place_media` and `linked_audio` true. It adds a text clip with `add_text`, with a placeholder like "Hi NAME, this one is for COMPANY", and an empty spot for the screenshot. Expected result: a template timeline and a new `state_token`. The agent shows you a `capture` of it before going on. invideo does not capture web pages. The agent opens each prospect's site with its own browser or screenshot tool, saves the image, then uploads it with `start_upload` and `add_media` on the timeline URL. Expected result: one image in the media bin per prospect, with an id. The agent runs `duplicate_timeline` with the prospect's company as `name`. It reads the copy with `get_timeline` and `timeline_id` for the new clip ids. Then it changes the text with `set_text` and places the screenshot with `place_media` and `set_position`. Expected result: one timeline per prospect, each with its own name, company and site. This step is optional and costs credits. The agent uploads a short, clean clip of your voice with `start_upload` and `add_media`. It runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick for the voice is `seed_audio_1_0.ta2a`, and for the lips `sync_lipsync_v3.video`. It calls `generate` with `dry_run: true`, that clip's sequence URL as `reference_audio_1`, and a `prompt` that tags you as `@Audio1` with the line, like "Hi Priya". It tells you the price, then calls `generate` with `max_credits` set to that price and an `idempotency_key` per prospect. It runs the lip sync the same way, dry run first, with the recording as `video` and the new line as `audio`. It reads each result with `read` and places it over your opening line with `place_media`. Expected result: a sequence URL per prospect where your lips match the name. Use only your own voice. Some models decline to copy a voice without consent. The agent runs `capture` at the text and the screenshot on the first few copies, and `check_timeline`. It reads each name against the CSV. Expected result: the right name, company and site on every checked copy. The agent runs `export` with `format` video, the copy's `timeline_id`, a `file_name` like `acme-priya`, and one `idempotency_key` per prospect. It runs the list in parts and marks each done row in the brief. Expected result: one export card per prospect with status `completed`. The terminal version of the same job: ```bash invideo project new --title "Outreach Q4" invideo agent register --name export INVIDEO_AS= invideo asset upload ./pitch.mp4 invideo context new-brief --name "Q4 prospects" \ --description "One video per row of prospects.csv" invideo edit new --name "Outreach template" invideo asset upload ./shots/acme.png invideo edit show --json invideo edit change --timeline T1 --token \ --operations @copy-acme.json invideo edit show --timeline T2 --mode window invideo edit change --timeline T2 --token \ --operations @text-acme.json invideo gen models --query "seed audio" invideo gen model --model seed_audio_1_0.ta2a invideo gen run --model seed_audio_1_0.ta2a --dry-run \ -i reference_audio_1= -i prompt='Warm. @Audio1: "Hi Priya"' invideo gen run --model seed_audio_1_0.ta2a \ --max-credits --idempotency-key acme-priya-name \ -i reference_audio_1= -i prompt='Warm. @Audio1: "Hi Priya"' invideo gen models --query "lip sync" invideo gen model --model sync_lipsync_v3.video invideo gen run --model sync_lipsync_v3.video --dry-run \ -i video= -i audio= invideo gen run --model sync_lipsync_v3.video \ --max-credits --idempotency-key acme-priya-sync \ -i video= -i audio= invideo edit capture --timeline T2 --at 1,5 --out ./frames invideo edit export --format video --timeline T2 \ --file-name acme-priya --idempotency-key acme-priya-v1 --json invideo status --wait invideo notebook show --out ./videos mv ./videos/export.mp4 ./videos/acme-priya.mp4 ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`, and `` is a notebook page from `invideo notebook show `. `` comes from the `invideo edit show` right before each change, because the first change makes the old token stale. `` and `` are the `url` values that `invideo asset upload` returns. `` is the sequence URL from the voice run, and `` is each dry run's `estimated_credits`. `` is `.sequences[0]` of what the export returns. `invideo status` does not download, and `invideo notebook show` saves the file as `export.mp4`, so the agent renames it. The key edits copy the template, then set the text and place the screenshot on the copy. These are two calls, because the copy's clip ids come from a read in between. The ops files are bare lists. At 30 fps, frame 300 is 10 seconds. The file `copy-acme.json`, run on `T1`: ```json [ { "op": "duplicate_timeline", "timeline": "T1", "name": "Acme" } ] ``` The file `text-acme.json`, run on the copy `T2`. The ids `c12` and `c13` come from `invideo edit show` on `T2`, and `m4` is the screenshot's media bin id from `invideo asset upload`. ```json [ { "op": "set_text", "clip": "c12", "text": "Hi Priya, this one is for Acme" }, { "op": "place_media", "asset": "m4", "track": "V2", "at_f": 0, "source_start_seconds": 0, "source_end_seconds": 10, "mode": "place_on_top", "linked_audio": false }, { "op": "set_position", "clip": "c13", "x": 480, "y": 0 } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: the upload, every copy and text change, `capture`, every `export`. - Costs credits: nothing on this page, unless you add captions with `audio.transcript` or the spoken name with `seed_audio_1_0.ta2a` and `sync_lipsync_v3.video`. Each copy takes a minute or two of agent time and an export. A long list takes hours, so run it in parts. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are wrong ids on a copy, or a list that stops halfway. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `set_text` changed the template, not the copy | The clip id was the template's. Read the copy with `get_timeline` and its `timeline_id`, then use its ids. | | A name runs off the frame | Lower the font size with `set_text_style`, or put the company on a second line. | | The screenshot shows a cookie banner | Close the banner in the browser and take the screenshot again. | | A site blocks the browser, so there is no screenshot | Skip the screenshot for that row and tell the person. | | A session ends halfway through the list | Read the brief for the done rows and start from the next one. | | `timeout` on `export` | Do not export again. `read` the thread or call `status`. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` and rebuild. | | The download folder is empty | `invideo status` does not download. Run `invideo notebook show --out ./videos`. | | The file is `export.mp4`, not `acme-priya` | `file_name` does not name the saved file. Rename it after the download. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: exporting without `timeline_id` | Instead: pass the copy's id. Without it, you export the main timeline. | | Avoid: sending the emails for the person | Instead: hand over the files and the list. The person sends. | #### Prompts to try Each prompt is a real variation of this job. ```text Same template, but 9:16 for LinkedIn messages. Put the name at the top and the screenshot in the lower half. ``` ```text Add each prospect's logo in the corner instead of a site screenshot. The logos are in ./logos, named by company. ``` ```text Add burned-in captions to the template from my voice, then make the copies for the 40 new rows in prospects.csv. ``` #### When to use something else invideo does not send emails, track views or host a landing page per prospect. Use your email or sales engagement tool for that. To say each prospect's name out loud in your own voice, the agent can clone your voice with `seed_audio_1_0.ta2a` and re-sync your lips with `sync_lipsync_v3.video`, but test it on a few names first: a wrong name in your own voice hurts more than text on screen. For a live screen recording per prospect, use a screen recorder and bring each file in with `start_upload`. #### Related - [Make a personalized video message from Santa or an AI presenter](/how-to/personal/personalized-message-video) - [Turn a CSV into many videos with a script](/how-to/developers/csv-to-videos) - [Make a launch video from your product URL and screenshots](/how-to/marketing/launch-video) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Cut an event sizzle reel and a town hall recap from one day of footage Source: https://docs.invideo.io/how-to/marketing/event-and-town-hall-recap.md Turn a day of event or all-hands footage into a sizzle reel with music and titles, and a one-minute recap with captions and an SRT file. Turn a day of conference, launch event or all-hands footage into two videos: an event sizzle reel, or highlight reel, with music and titles, and a one-minute town hall recap of the speakers' best lines with captions. You also get an SRT captions file for your intranet player. Your agent finds the applause, the laughs and the strongest quotes, so you do not scrub through hours of footage. Use invideo for this when you need both cuts by the next morning from the same footage, each on its own branch you can review and change in the editor. The agent never posts to your intranet, your social accounts or Slack. You publish. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Here is yesterday's event footage in ./event. Make two cuts on two branches: a 60-second sizzle reel cut to upbeat music with the event name as a title, and a one-minute recap of the CEO's and the panel's best lines with captions. Give me an SRT for the recap. Price the transcripts and music first. ``` In a chat app, you drag the files into the project. In a terminal, the agent names the folder and uploads it. #### What you need These are the inputs the agent asks for. - The footage: stage cameras, the room camera, phone clips, the stream recording. - The names and titles of the speakers, spelled right. - The event name, date and logo, and your brand colors. - A music mood for the sizzle reel, or a track you own. - Who must be in the recap, and anything that must stay out, like a confidential slide. #### Steps The agent finds the moments first, then cuts the two videos from them. ##### Find the moments The agent builds one selects timeline, then branches it into the two cuts. Event files are large, so the agent uploads each with `start_upload`, PUTs the bytes, then calls `add_media` with the `upload_id`. Expected result: one sequence URL per file. The agent runs `media` `audio.onsets` and `audio.content` on each file for applause, cheers, laughs and music. It runs `video.sceneSplit` on long camera files to find the cuts, and `video.frames` at each candidate to look. Expected result: a list of moments with times and a frame each. The agent prices `audio.transcript` on the sequence URL of each talk and the panel with `dry_run`, tells you the price, starts it with `max_credits` set to that price, and calls again after `retry_after_s` for the words. It picks the short, complete lines that land without context. Expected result: a list of quotes with the speaker, the file and the times, shown to you. The agent makes a 16:9 timeline with `new_timeline`, places the picks with `place_media`, and marks each with `add_marker`. Then it runs `timeline_history` with `create_branch` twice, named `sizzle` and `recap`. Expected result: two branch URLs from one selects timeline. ##### Cut both videos The agent cuts each video on its own branch, then checks both before export. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_music_v2_5_instrumental`. It calls `generate` with `dry_run: true`, a `prompt` and a `duration`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL, which the agent reads with `read`. On the `sizzle` branch, the agent runs `audio.beats` on the track for the beats and `audio.markers` for the drops and phrases. It cuts on the beats with `split_clip`, `trim_clip` and `delete_clip`, puts the biggest moment on a drop, and adds the event title and the logo with `add_text` and `place_media`. Expected result: a tight cut that ends on the music's last beat. On the `recap` branch, the agent keeps the chosen lines in order, adds a lower third per speaker with `add_text`, and adds captions with `add_captions` from the transcript words. Expected result: a cut with captions that match the speech. The agent runs `capture` at each cut and `check_timeline` on both branches, then `export` each branch with `format` video. For the SRT, it reads the recap's caption slides with `get_timeline` mode `collection` and `collection` `caption_slide`, and writes the file. Expected result: two export cards with status `completed`, and an SRT file for the recap. The terminal version of the same job: ```bash invideo project new --title "Summit recap" invideo agent register --name export INVIDEO_AS= invideo asset upload ./event/*.mp4 invideo media audio.onsets invideo media audio.content invideo media video.sceneSplit --dry-run invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo edit new --name "Summit selects" invideo edit show --json invideo branch new --name sizzle --token invideo edit show --json invideo branch new --name recap --token invideo edit show --json invideo gen models --query "upbeat instrumental music" invideo gen model --model elevenlabs_music_v2_5_instrumental invideo gen run --model elevenlabs_music_v2_5_instrumental \ --dry-run -i prompt="driving, bright, festival energy" -i duration=60 invideo gen run --model elevenlabs_music_v2_5_instrumental \ --max-credits --idempotency-key summit-music-v1 \ -i prompt="driving, bright, festival energy" -i duration=60 invideo media audio.beats invideo media audio.markers invideo edit change --timeline T1 --token \ --operations @sizzle.json invideo edit show --json invideo edit change --timeline T1 --token \ --operations @recap.json invideo edit show --mode collection \ --collection caption_slide --json > slides.json invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./sizzle invideo edit export --format video --quality 1080 --json ``` Where the values come from: - `` comes from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`. `` is a notebook page from `invideo notebook show `. - `` is the `url` the upload returns for each file. Each `` is the dry run right before it. - `` is the sequence URL from the music run or the stock pick. - `` comes from `invideo edit show `, read fresh before each `branch new`. - `` and `` are the `.branch_url` each `invideo branch new` returns. Before each change, `` is the one `invideo edit show` returns on that branch; the main token is stale there. - `` is `.sequences[0]` of what each export returns. `invideo status` waits and does not download; `invideo notebook show` saves the file as `./sizzle/export.mp4`. The recap export gets its own `status` and `notebook show`. The file `./recap.json` holds a bare list of operations for the recap branch. On the MCP path, the same list goes in the `operations` field of `edit_timeline`. It adds a speaker's lower third and the caption for one line, both on `V3` (Titles). The lower third takes that span first, so `add_captions` puts the captions on the next free video track above it. At 30 fps, frame 90 is 3 seconds. ```json [ { "op": "add_text", "track": "V3", "start_f": 0, "end_f": 90, "text": "Maya Sen, CEO", "style": { "font_size": 42, "color": "#ffffff", "align": "left", "shadow": true } }, { "op": "add_captions", "track": "V3", "slides": [ { "text": "This year the team shipped more than in the last three.", "start_f": 0, "end_f": 96 } ] } ] ``` ##### The SRT file The agent turns each caption slide into one SRT block: a number, the start and end time as hours, minutes, seconds and milliseconds, then the text. It converts frames to time at the timeline's rate. Then it gives you the file to upload with the video. ```text 1 00:00:00,000 --> 00:00:03,200 This year the team shipped more than in the last three. ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: every edit, the SRT, `capture` and `export`. - Costs credits: `audio.transcript` on each talk, stock music or a generated track. - The `media` reads (`audio.onsets`, `audio.content`, `audio.beats`, `audio.markers`, `video.frames`, `video.sceneSplit`): the dry run shows the price before anything starts. The upload and the transcripts take the longest. Plan the evening after the event for both, and the cuts the next morning. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems come from long files or loud rooms. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The upload PUT fails | Call `start_upload` again for a new `upload_url`, and PUT once more. | | A file has no sound, so it has no audio cues | Pick its moments from `video.frames` and the scene cuts. | | You want stock music instead of a generated track | Run `search_library` in `stock_music`, and bring the pick in with `add_media`. | | The applause list is mostly crowd noise | Check each candidate with `video.frames`. Keep the ones where the stage shows a moment. | | A quote starts mid-word | Move the in point to the gap before the first word from the transcript. | | The SRT drifts from the speech | The frame-to-time math used the wrong rate. Read the timeline's rate with `get_timeline` and write it again. | | `audio.transcript` returns a status, not words | It is still running. Call again with the same file after `retry_after_s`. | | An edit on one branch shows up on the other | It does not. Check that the URL names the right branch. | | CLI exit 3 | The edit changed since your read, or the token is from main. Run `invideo edit show` on that branch's URL and use its `state_token`. | | The `./sizzle` folder is empty after `status` | `status` waits and does not download. Run `invideo notebook show --out ./sizzle`. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: one timeline for both cuts | Instead: one branch per deliverable, so a change to one never breaks the other. | | Avoid: keeping a confidential slide in frame | Instead: check each frame with `capture`, and cut or blur what the person named. | #### Prompts to try Each prompt is a real variation of this job. ```text Make the sizzle reel in 9:16 too, on a third branch, with the title at the top and no text near the bottom. ``` ```text The town hall has no slides worth showing. Cut the CEO's five best lines into one minute with captions and the CEO's name as a lower third. ``` ```text Make a 15-second teaser from the sizzle branch for tomorrow's newsletter, ending on the logo. ``` #### When to use something else invideo does not record or stream the event, post to your intranet, or make SCC caption files. Use your streaming tool to record, your intranet or video platform to publish, and a captioning tool such as Rev or 3Play Media if your platform needs SCC. For a multi-camera live switch during the event, use a production switcher. #### Related - [Repurpose one video for every platform, one branch each](/how-to/creators/repurpose-for-every-platform) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Make an SRT captions file for an LMS](/how-to/training/srt-for-an-lms) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Make an employer brand film with real employees Source: https://docs.invideo.io/how-to/marketing/employer-branding-video.md Cut employee interviews into an employer brand film with lower thirds in your brand style, then a 30 second video job ad per open role. Turn interviews with your real employees into an employer brand film, or recruitment video, and a 30 second video job ad for each open role. Your agent reads the interviews, picks the honest lines, adds b-roll of the office and the team, and puts name and role lower thirds in your brand fonts and colors. The job ads reuse the film's best moments with the role's title and link on screen. Use invideo for this when you hire for many roles: the job ad is one template timeline, and each role is a copy with new text, so a new opening takes minutes. The agent never posts the film or the job ads to LinkedIn, your careers page or a job board. You publish them. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Cut the interviews in ./interviews into a 90-second employer brand film. Pick honest lines about the work and the team, not slogans. Add b-roll from ./office, lower thirds with name and role in my brand kit, and captions. Then make a 30-second job ad for each role in roles.csv. Price the transcripts first. ``` In a chat app, you drag the files into the project. In a terminal, the agent names the folders and uploads them. #### What you need These are the inputs the agent asks for. - The interview recordings, one file per person, with their consent to appear. - Each person's name and role, spelled the way they want it. - B-roll of your office, your team at work, or your product. Stock fills the gaps. - Your brand kit: colors as hex codes, the font files, the logo. - The open roles: title, team, location, and the link to apply. - The shapes: 16:9 for the careers page, 9:16 or 1:1 for social. #### Steps The agent cuts the film first, then makes the job ads from it. ##### Cut the film The agent builds the film on a branch. The agent writes a context entry at `context/brands/acme.md` with `write`: colors, fonts, logo and text rules. It uploads the font files and the logo with `start_upload` and `add_media` on the timeline URL. Expected result: an entry URL, and a font id in the media bin for each font. The agent uploads each interview with `start_upload` and `add_media`. It prices `audio.transcript` on each interview's sequence URL with `dry_run`, tells you the price, starts it with `max_credits` set to that price, and calls again after `retry_after_s` for the words. Expected result: every word with its time and speaker. The agent reads each transcript and picks short, specific lines about the work, the team and growth. It skips lines that sound like an ad. It shows you the list with names and times before it cuts. Expected result: your yes, or your changes. The agent makes a 16:9 timeline with `new_timeline` and creates a branch with `timeline_history`. It places each line with `place_media` and `linked_audio` true, and lays b-roll over the cuts on a higher track, with stock from `search_library` in `stock_video` for gaps. Expected result: a cut where every line is a full sentence. The agent adds each person's name and role with `add_text`, then applies the brand font and colors with `set_text_style`. It adds captions with `add_captions` from the transcript words. Expected result: a lower third the first time each person speaks, in your brand style. The agent runs `capture` at each lower third and `check_timeline`, then runs `export`. Expected result: an export card with status `completed`. ##### Make the job ads The agent builds one job ad template, then one copy per role. The agent builds a 30 second job ad on its own timeline from the film's best moments, with a title card and an apply card made with `add_text`. For each role, it runs `duplicate_timeline`, reads the copy with `get_timeline`, and changes the cards with `set_text`. Expected result: one timeline per role. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_music_v2_5_instrumental`. It calls `generate` with `dry_run: true`, a `prompt` and a `duration` of 30, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL, which the agent reads with `read` and places on `A2` (Music) in each copy. The agent runs `capture` at each card and `check_timeline`, and reads each role title and link against your list. Then it runs `export` per timeline with `timeline_id`. Expected result: one export card per job ad with status `completed`. The terminal version of the same job: ```bash invideo project new --title "Employer brand" invideo agent register --name export INVIDEO_AS= invideo context write /context/brands/acme.md \ --markdown @acme.md --description "Acme brand kit" invideo asset upload ./interviews/*.mp4 invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo edit new --name "Brand film" invideo asset upload ./brand/Inter-Bold.otf ./brand/logo.png invideo gen models --query "instrumental music bed" invideo gen model --model elevenlabs_music_v2_5_instrumental invideo gen run --model elevenlabs_music_v2_5_instrumental \ --dry-run -i prompt="warm, hopeful, light piano" -i duration=30 invideo gen run --model elevenlabs_music_v2_5_instrumental \ --max-credits --idempotency-key job-ad-music-v1 \ -i prompt="warm, hopeful, light piano" -i duration=30 invideo edit show --json invideo branch new --name film-v1 --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @film.json invideo edit capture --at 3,20,45,80 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./film invideo edit export --format video --timeline T3 --json ``` Where the values come from: - `` comes from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`. `` is a notebook page from `invideo notebook show `. - `` is the `url` the upload returns for each interview. Each `` is the dry run right before it. - `` comes from `invideo edit show `, and on the branch from `invideo edit show `; the main token is stale there. `` is the `.branch_url` that `invideo branch new` returns. - `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves `./film/export.mp4`, which the agent renames, like `brand-film.mp4`. - `T3` is the id of a job ad copy, from what `duplicate_timeline` returns or `invideo edit show`. Each copy's export gets its own `status` and `notebook show`. The brand kit entry is plain markdown. The agent and anyone in the project read it before they work. ```text # Acme brand kit - Colors: navy #1a2b4c, coral #ff6b5b, white #ffffff - Font: Inter Bold for titles, Inter Regular for captions - Logo: bottom right, never over a face - Lower thirds: name in white, role in coral, left aligned ``` The file `./film.json` holds a bare list of operations. On the MCP path, the same list goes in the `operations` field of `edit_timeline`. This one adds a lower third on `V3` (Titles). ```json [ { "op": "add_text", "track": "V3", "start_f": 30, "end_f": 150, "text": "Priya Nair, Backend Engineer" } ] ``` The agent reads the new text clip's id with `get_timeline`, because a later op in the same call cannot use it. In a second call it styles the clip with the brand font. Here `t1` is that id and `f1` is the font's id from `add_media`. ```json [ { "op": "set_text_style", "clip": "t1", "style": { "font": "f1", "color": "#ffffff", "font_size": 44, "align": "left" } } ] ``` On each job ad copy, the agent sends `set_text` with the copy's own clip id from `get_timeline`, like `{ "op": "set_text", "clip": "t4", "text": "Now hiring: Backend Engineer, Berlin" }`. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: the brand kit, every edit and copy, `capture`, every `export`. - Costs credits: `audio.transcript` on each interview, each stock shot, and a music bed from `elevenlabs_music_v2_5_instrumental`. The film takes a few hours with your review of the lines. Each extra job ad takes minutes. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are a lower third in the wrong style, or a copy with the wrong ids. | Symptom | Fix | | --- | --- | | A lower third shows the default font | The `font` id is wrong or missing. Read the bin's fonts with `get_timeline` mode `collection`, then run `set_text_style` again. | | A line sounds cut off | Extend the clip to the end of the sentence from the transcript with `trim_clip`. | | `set_text` changed the template, not the copy | Read the copy with `get_timeline` and its `timeline_id`, then use its clip ids. | | `write` on the brand kit is refused | Someone changed it since your read. `read` it again and pass the new `revision`. | | `audio.transcript` returns a status, not words | It is still running. Call again with the same file after `retry_after_s`. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | CLI exit 3 | The edit changed since your read, or the token is from main. Run `invideo edit show ` and use its `state_token`. | | The saved file is called `./film/export.mp4` | `notebook show` always saves `./film/export.mp4`. Rename it per role. | | Avoid: putting a person in the film who has not agreed | Instead: ask the person for the list of people who signed a release. | | Avoid: changing `invideo_rules.md` for the brand | Instead: put the brand in `context/brands/`. The rules file is the person's. | #### Prompts to try Each prompt is a real variation of this job. ```text Make the job ads 9:16 for LinkedIn and Instagram, with the role title at the top and the apply link on the last card. ``` ```text Three new roles opened. Add them to roles.csv and make the job ads from the same template. ``` ```text Make a 15-second cut of the brand film for each team: engineering, sales and support, using only that team's people. ``` #### When to use something else invideo does not post job ads, track applicants, or film the interviews. Use your applicant tracking system or job board to publish, and record the interviews with a camera or a recording tool. For release forms and consent, use your HR or legal process. For a subtitle file a job board asks for, see the SRT steps on the event recap page. #### Related - [Cut an event sizzle reel and a town hall recap from one day of footage](/how-to/marketing/event-and-town-hall-recap) - [Edit a documentary or interview from the transcript, with b-roll and lower thirds](/how-to/film/documentary-and-interview-edit) - [Cut a customer testimonial or raw creator footage into an ad, or the case study set](/how-to/marketing/testimonial-to-ad) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Turn a blog post URL into a video Source: https://docs.invideo.io/how-to/marketing/article-to-video.md Give your agent a blog post URL and get a narrated video: a script you approve, a voiceover, stock b-roll, text slides, captions and music. Turn a blog post, article or newsletter issue into a video: blog to video, article to video, text to video from a URL. Your agent reads the post, writes a short script, and shows it to you first. Then it voices the script, lays stock b-roll and text slides under it, adds captions, and puts music under the voice that dips when the voice speaks. Use invideo for this when you want the result on an editable timeline: you can swap one shot, fix one caption, or re-voice one line without starting over. Use your own posts, or posts you have the right to adapt. The agent never publishes the video. You post it. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Turn https://acme.com/blog/onboarding-tips into a 60-second video. Read the post, write a script in my voice, and show it to me before you spend anything. Then voice it, use stock b-roll and text slides for the key points, add captions and soft music under the voice. 16:9 and 9:16. ``` In a chat app or a terminal, the prompt is the same. The agent reads the URL with its own browser or fetch tool. #### What you need These are the inputs the agent asks for. - The post's URL, or the text pasted into the chat if the post is behind a login. - The length: 30, 60 or 90 seconds. - A voice. The agent finds one with `search_library` and sends you the preview. - The shape: 16:9 for YouTube and your site, 9:16 for Reels, Shorts and TikTok. - Your logo and brand colors, if you want them on the slides. - A music mood, or no music. #### Steps The agent works on a branch, so the main timeline stays clean until you approve. invideo does not fetch web pages. The agent reads the URL with its own browser or fetch tool, outside invideo. Expected result: the post's title, headings and main points in the chat. The agent writes a short script from the post: a hook, three or four key points, and a closing line. It marks which point each slide shows. It shows you the script before it spends anything. Expected result: your yes, or your changes. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. It picks a voice from `search_library` in `elevenlabs_text_to_speech_voices` and sends you the preview. It calls `generate` with `dry_run: true`, the script as `prompt` and that `voice_id`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL with the full script as audio. The agent reads that URL with `read` and never calls `generate` again to check. The agent prices `audio.transcript` on the voice's sequence URL with `dry_run`, starts it with `max_credits` set to that price, and calls again after `retry_after_s` for the words. Expected result: every word with its start and end time, which set the captions and the slide changes. The agent searches `search_library` in `stock_video` with words from each point, and brings the picks in with `add_media` and `stock`. It makes a timeline with `new_timeline`, creates a branch with `timeline_history`, places the voice with `insert_media`, and the shots with `place_media`. It adds text slides for the key points with `add_text`. Expected result: a new `state_token` and a shot or slide under every line. The agent adds the words with `add_captions`. It finds music in `stock_music`, places it on `A2` (Music) with `insert_media`, and adds `ducker` to that track with `add_audio_effect`. A new timeline ducks under `A1` (Voice) by default, so the ducker follows the voice with no more setup. The agent sets `set_sidechain_source` only when the voice sits on another track. Expected result: music that drops under the voice and comes back between lines. The agent runs `capture` at each slide and `check_timeline`, and checks the voice and music with `audio.loudness`. Then it runs `export` with `format` video and `target_lufs`. Expected result: an export card with status `completed`. The terminal version of the same job: ```bash invideo project new --title "Onboarding tips video" invideo agent register --name export INVIDEO_AS= invideo gen models --query "narration voice from a script" invideo library search \ --library elevenlabs_text_to_speech_voices --query "warm narrator" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --dry-run -i prompt=@script.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key onboarding-voice-v1 \ -i prompt=@script.txt -i voice_id= invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo library search --library stock_video \ --query "team onboarding laptop" invideo library search --library stock_music \ --query "soft upbeat background" invideo asset add --stock invideo edit new --name "Blog video 16x9" invideo edit show --json invideo branch new --name blog-v1 --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @build.json invideo edit capture --at 2,15,30,55 --out ./frames invideo edit check invideo edit export --format video --quality 1080 \ --target-lufs -14 --json invideo status --wait invideo notebook show --out ./out ``` Where the values come from: - `` comes from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`. `` is a notebook page from `invideo notebook show `. - `` comes from the voice search. Each `` is the dry run right before it: `.estimated_credits` for the voice, `credits` for the transcript. - `` is the voice's sequence URL, which the paid voice run returns. - `` is a result's id from `invideo library search`. - `` comes from `invideo edit show `, and on the branch from `invideo edit show `; the main token is stale there. `` is the `.branch_url` that `invideo branch new` returns. - `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves the file as `./out/export.mp4`. The file `./build.json` holds a bare list of operations. On the MCP path, the same list goes in the `operations` field of `edit_timeline`. It adds a text slide and the first caption on `V3` (Titles), and the `ducker` on `A2` (Music). `A1` is the voice track, and a new timeline ducks under `A1` by default. ```json [ { "op": "add_text", "track": "V3", "start_f": 90, "end_f": 240, "text": "Tip 1: Send the welcome email before day one", "style": { "font_size": 56, "color": "#ffffff", "align": "center" } }, { "op": "add_captions", "track": "V3", "slides": [ { "text": "New hires decide in a week", "start_f": 0, "end_f": 60 } ] }, { "op": "add_audio_effect", "target": "A2", "target_kind": "track", "effect": "ducker" } ] ``` If the voice sits on another track, the agent adds `set_sidechain_source` to the same list, with `timeline` `T1` and that track's id from `get_timeline`. It works in the same call as `add_audio_effect`. For the 9:16 version, the agent creates a second branch, sets the size with `set_timeline_settings`, and fills the frame on each shot with `fill_frame`. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: reading the post, the script, every edit, the ducker, `capture`, `export`. - Costs credits: the TTS voice, `audio.transcript` on the voice, each stock shot and the stock music. One video takes under an hour, most of it your review of the script. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are a script that drifts from the post, or timing. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | The agent cannot open the URL | The page needs a login or blocks bots. Paste the text into the chat. | | The script says something the post does not | Ask the agent to quote the post line behind each claim, and cut what has none. | | The music does not drop under the voice | The ducker follows `A1` by default. If the voice is on another track, point it there with `set_sidechain_source`. | | A slide changes mid-sentence | Move the slide's edges to word times from the transcript with `trim_clip`. | | `timeout` on `generate` | Do not call it again. `read` the thread or call `status`. | | CLI exit 3 | The edit changed since your read, or the token is from main. Run `invideo edit show ` and use its `state_token`. | | The `./out` folder is empty after `status` | `status` waits and does not download. Run `invideo notebook show --out ./out`. | | CLI exit 5 | Credits ran out. Stop and tell the person. | | Avoid: voicing the script before the person reads it | Instead: show the script first. The voice costs credits. | | Avoid: adapting someone else's article | Instead: use the person's own posts, or ask them to confirm the rights. | #### Prompts to try Each prompt is a real variation of this job. ```text Turn my last three posts into three 30-second Shorts, 9:16, same voice, captions in the middle of the frame. ``` ```text Make a video from this newsletter issue. No voice: text slides and captions only, with music. Pasted text below. ``` ```text Turn this listicle into a 90-second video with one stock shot per tip and a title card for each number. ``` #### When to use something else invideo does not read web pages, so the reading happens in the agent's own browser or fetch tool. invideo does not publish to your blog, YouTube or social accounts. For a talking presenter instead of b-roll, see the avatar style in the video sales letter page. For a whiteboard drawing style, see the whiteboard explainer page. #### Related - [Make a video sales letter with slides, b-roll or an avatar](/how-to/marketing/video-sales-letter) - [Make a stock-footage commercial for your business, in short and long cuts](/how-to/marketing/stock-footage-commercial) - [Make a faceless YouTube video yourself, with AI help](/how-to/creators/faceless-youtube-video) - [Turn release notes or a changelog into a video every week](/how-to/training/release-notes-to-video) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Make monthly videos for a dentist Source: https://docs.invideo.io/how-to/marketing/local-business-monthly-videos.md Set up one branded template per local business, then make each month's short videos from a brief, in vertical and square. Make a monthly set of short social videos, or promo reels, for a local business: a dental clinic, a gym, a restaurant, a plumber or a cleaner. You set up a template once with the business's brand. Each month, a brief lists the four videos, and your agent makes each one from the template with the business's own photos, stock b-roll, a voiceover and captions, in vertical and square. Use invideo for this when you run videos for one business or many every month: the template, the brand kit and the brief live in the project, so next month starts where this month stopped. The agent never posts to Instagram, Facebook, TikTok or Google. The business owner, or you, posts. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Set up a monthly video project for Bright Smile Dental: a brand kit from the logo and colors in ./brand, and a 20-second vertical template with a voiceover, captions and an end card with the phone number. Then make November's four videos from the brief below, using the photos in ./november. Vertical and square. Price everything first. ``` In a chat app, you drag the photos into the project. In a terminal, the agent names the folders. #### What you need These are the inputs the agent asks for. - The business's logo, colors and font, or permission to pick a clean font. - The contact line for the end card: phone, address or booking link. - This month's four topics. Common ones by trade are below. - Photos and phone clips from the business: the team, the space, the work. - A voice, or captions with music only. - The shapes: 9:16 for Reels, Shorts and TikTok, 1:1 for the feed. Topics that work each month: - **Dentist:** meet the team, a patient question answered, the month's offer, a tour of the clinic. - **Gym:** a class of the week, a member story, a trainer's tip, the schedule. - **Restaurant:** the dish of the month, behind the kitchen door, an event night, the opening hours. - **Home service:** a before and after, a seasonal tip, a team intro, a customer review read out. #### Steps The agent sets up the business once, then repeats the last four steps each month. The agent writes a context entry at `context/brands/bright-smile.md` with `write`: colors, font, logo position and the contact line. It uploads the logo and the font with `start_upload` and `add_media` on the timeline URL. Expected result: an entry URL, and the logo and font in the media bin. The agent makes a 1080 by 1920 timeline with `new_timeline` and creates a `vertical` branch with `timeline_history`. It adds a title card and an end card with `add_text`, styled with `set_text_style`, and the logo with `place_media`. Expected result: a template the agent shows you with `capture`. The agent makes a brief with `new_brief`, named for the month. It adds one note per video: the topic, the script line, the photos to use, and the offer. You approve the brief before anything is made. Expected result: a brief URL with four notes. For each note, the agent runs `duplicate_timeline`, reads the copy with `get_timeline`, and changes the cards with `set_text`. It brings in the business's photos with `add_media` and fills gaps with stock from `search_library` in `stock_video`. Expected result: four timelines, one per video. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a `voice_id` from `search_library` in `elevenlabs_text_to_speech_voices`. For each script, it calls `generate` with `dry_run: true`, the script as `prompt` and that `voice_id`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and its own `idempotency_key` per video, and reads each sequence URL it gets back with `read`. It prices `audio.transcript` on each voice with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a voice sequence URL and a caption clip for every video. The agent creates a `square` branch from `vertical` with `timeline_history`. On it, it sets each timeline to 1080 by 1080 with `set_timeline_settings`, then re-centers each shot with `fill_frame` or `set_position`. Expected result: square versions with no face or text cut off. The agent runs `capture` on every video on both branches, and `check_timeline`. It reads the phone number and the offer on each end card. Then it runs `export` per timeline with `timeline_id`. It marks the brief's status as ready. Expected result: eight export cards with status `completed`. The terminal version, for one month: ```bash invideo project new --title "Bright Smile Dental videos" invideo agent register --name export INVIDEO_AS= invideo context write /context/brands/bright-smile.md \ --markdown @bright-smile.md invideo context new-brief --name "November" \ --description "Four videos: team, FAQ, whitening offer, clinic tour" invideo edit new --name "Template" \ --width 1080 --height 1920 invideo asset upload ./november/*.jpg invideo gen models --query "voiceover from a script" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --dry-run -i prompt=@nov-team.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key nov-team-voice \ -i prompt=@nov-team.txt -i voice_id= invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo edit show --json invideo branch new --name vertical --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @copy.json invideo edit show --json invideo edit change --timeline T2 --token \ --operations @november.json invideo edit capture --timeline T2 --at 1,8,18 --out ./frames invideo edit check invideo edit export --format video --timeline T2 --json invideo status --wait invideo notebook show --out ./nov mv ./nov/export.mp4 ./nov/nov-team-9x16.mp4 invideo context show invideo context edit --old "status: " \ --new "status: ready" ``` Where the values come from: - `` comes from `invideo project new`, and `` from `invideo edit new`. `` is the name you choose in `invideo agent register`. `` is a notebook page from `invideo notebook show `. - `` comes from a search in `elevenlabs_text_to_speech_voices`. Each `` is the dry run right before it. - `` is the voice's sequence URL, which the paid voice run returns. - `` comes from the `invideo edit show` right before each command: on `` for the branch, then on `` before each change. The main token is stale on the branch. `` is the `.branch_url` that `invideo branch new` returns for `vertical`. - `T2` is the copy's id, from the `invideo edit show ` after the copy landed. - `` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves `./nov/export.mp4`. - `` comes from `invideo context new-brief`, and `` is the status text that `invideo context show` prints. The square branch repeats the copy, size and export lines on its own `.branch_url`, from `invideo branch new --name square --token `, with a fresh token from `invideo edit show` on that branch. The key edits copy the template for one video, then set its title card and place a photo. These are two calls, because the copy's ids come from a read in between. Each file holds a bare list of operations; on the MCP path, the same list goes in the `operations` field of `edit_timeline`. The file `./copy.json`: ```json [ { "op": "duplicate_timeline", "timeline": "T1", "name": "Nov 1: Meet the team" } ] ``` The file `./november.json`, with the copy's clip id `c31` and the photo's bin id `m7` from `invideo edit show`. At 30 fps, frame 90 is 3 seconds. ```json [ { "op": "set_text", "clip": "c31", "text": "Meet Dr. Lee's team" }, { "op": "place_media", "asset": "m7", "track": "V1", "at_f": 90, "source_start_seconds": 0, "source_end_seconds": 3, "mode": "overwrite", "linked_audio": false } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: the brand kit, the brief, every copy and edit, the square branch, `capture`, every `export`. - Costs credits: the TTS voice, `audio.transcript` on each voice, and each stock shot. The first month takes a few hours with the setup. Later months take about an hour for four videos. For many businesses, run them in parts, one business at a time. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are a copy with the wrong ids, or a square crop that cuts a face. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `set_text` changed the template, not the copy | Read the copy with `get_timeline` and its `timeline_id`, then use its clip ids. | | The square version cuts off a face or the phone number | Move the clip with `set_position`, or move the text up with `set_text_style` and `set_position`. Capture again. | | A photo looks stretched | Use `fill_frame` on the clip. It scales evenly and crops the extra. | | The brief edit is refused | The text in `old_text` must match the brief once, as `read` shows it. Read the brief again. | | `timeout` on `export` | Do not export again. `read` the thread or call `status`. | | CLI exit 3 | The edit changed since your read, or the token is from main. Run `invideo edit show ` and use its new `state_token`. | | The saved file is called `./nov/export.mp4` | `notebook show` always saves `./nov/export.mp4`. Rename it per video. | | CLI exit 5 | Credits ran out. Stop and tell the person. | | Avoid: health or result claims in a script | Instead: the owner approves every script line, and the agent writes no claims of its own. | | Avoid: posting the videos | Instead: hand over the files with a caption line for each. The person posts. | #### Prompts to try Each prompt is a real variation of this job. ```text Make December's four videos for Iron Peak Gym from the brief. No voiceover: captions and upbeat music only. ``` ```text I run videos for six restaurants. Set up a project per restaurant with its own brand kit and template, then make this month's dish videos. ``` ```text Turn this five-star Google review into a 15-second video for the plumbing company, with the reviewer's first name only. ``` #### When to use something else invideo does not schedule or post to social accounts or Google Business Profile, and it does not shoot the footage. Use a social scheduler such as Buffer or Later to post, and a phone to film at the business. For a stock-only commercial with no business photos, see the stock-footage commercial page. #### Related - [Make a stock-footage commercial for your business, in short and long cuts](/how-to/marketing/stock-footage-commercial) - [Turn listing photos into a vertical real-estate reel](/how-to/marketing/real-estate-reel) - [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) ## Training and L&D ### Slides to narrated video Source: https://docs.invideo.io/how-to/training/slides-to-narrated-video.md Turn a PDF or PowerPoint deck into a narrated training video with one slide per image, a voiceover and optional captions. Turn a slide deck into a narrated video: a PowerPoint to video, a PDF to video, a deck with a voiceover. You get one image per slide, a narration for each slide, and an editable timeline where each slide stays on screen while its line is spoken. The same steps run for one deck or a folder of decks. Use invideo for this when you want the slides and the voice on a real timeline, so you can fix one slide or one line later without rebuilding the video. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a narrated video from deck.pdf in a new invideo project. One image per slide. Write a short script for each slide from its text, show me the script, then voice it with a calm narrator. Hold each slide while its line plays. Add captions. Show me frames before you export. ``` In a chat app, you drag the deck into the project. In a terminal, your agent names the file or the folder of decks and uploads them. #### What you need These are the inputs your agent asks for. - The deck as a PDF, or an office file such as PPTX. - The script, or permission for the agent to write one from the slide text. Speaker notes do not come through `document.pages`, so paste them if you want them used. - A voice. Your agent finds one with `search_library` and sends you the preview. - The shape. Slides are usually 16:9. - Captions on or off. #### Steps The agent works on a branch, so the main timeline stays clean until you approve. The agent uploads the file with `start_upload` and `add_media`. A PDF or office file goes to the project's files, not to a sequence. It sees the file's URL under `…/assets`, in a dated folder, and uses that URL as it is. The agent calls `media` with op `document.pages` on the file's URL that the upload returned. The dry run shows its price before anything starts. It sees an image sequence of each page on a new thread. The agent reads each slide image and writes one short line per slide. It shows you the script before it spends anything. It sees your yes, or your changes. 1. The agent runs `find_models` with "narration voice", picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a voice from `search_library` in `elevenlabs_text_to_speech_voices`. Your agent can search for others with `find_models`. 2. It calls `generate` per slide with the line as `prompt`, the `voice_id` and `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` per slide with `max_credits` set to that price and an `idempotency_key`, like `deck-slide-01`. It gets a thread URL and, when the result lands, one sequence URL per slide. It reads each URL with `read` and never calls `generate` again to check. The agent makes a timeline with `new_timeline`, creates a branch with `timeline_history`, and places each voice clip on an audio track and each slide on a video track with `insert_media`. It reads the new clips with `get_timeline`, then sets each slide's length to its line with `trim_clip` in a second call. It sees a new `state_token` after each `edit_timeline` call. The agent prices `audio.transcript` with `dry_run` on each voice clip's sequence URL and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. It sees a caption clip on a video track above the slides. The agent calls `capture` at a few slide changes and `check_timeline`, then `export` with format `video`. It sees an export card with status `completed`. The terminal version of the same job: ```bash invideo project new --title "Onboarding deck" invideo asset upload ./deck.pdf invideo media document.pages invideo library search \ --library elevenlabs_text_to_speech_voices --query "calm narrator" invideo gen models --query "narration voice" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@slide-01.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key deck-slide-01 \ -i prompt=@slide-01.txt -i voice_id= invideo status --wait invideo notebook show invideo edit new --name "Onboarding v1" invideo edit show --json invideo branch new --name deck-v1 --token invideo edit show --json invideo edit change --timeline T1 \ --token --operations @layout.json invideo edit show --json invideo edit change --timeline T1 \ --token --operations @lengths.json invideo edit capture --at 2,15,40 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the `url` that `invideo asset upload` returns for the deck. It sits in a dated folder, so never type the path. - `` comes from the `library search` line, a voice of `elevenlabs_text_to_speech.elevenlabs_tts_v4`. - `` is a notebook page of the project, listed by `invideo notebook show `. - `` is the dry run's `.estimated_credits`. - `` is the `url` the paid `gen run` returns. `notebook show` on it lists the voice line's sequence URL. - `` is the `branch_url` that `invideo branch new` returns. - `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read again before each change. - `` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The file behind `@layout.json` is the bare list of ops that `--operations` takes. It places one voice line and its slide at the start of the line. The `asset` values are sequence URLs: the voice take from `generate`, and the slide image from `document.pages`. ```json [ { "op": "insert_media", "asset": "", "track": "A1", "at_f": 0, "ripple": false }, { "op": "insert_media", "asset": "", "track": "V1", "at_f": 0, "ripple": false } ] ``` The file behind `@lengths.json` sets the slide's length to its line, in a second call. `to_f` is the voice clip's end frame. `c2` and its current end, `from_f`, come from `invideo edit show` after the first call. `from_f` must be where the edge is now, as the agent last read it. ```json [ { "op": "trim_clip", "clip": "c2", "edge": "tail", "from_f": 150, "to_f": 450, "mode": "leave_gap", "linked": false } ] ``` ##### Many decks For a folder of decks, the agent runs the same steps once per deck, one timeline per deck. Run it in parts: a few decks per session, then check those videos before the next batch. The agent keeps a list of which decks are done in a brief made with `new_brief`, so a new session picks up where the last stopped. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: every timeline edit, `capture` and each export. - `document.pages`: the dry run shows its price before anything starts. - Costs credits: the voice from `elevenlabs_text_to_speech.elevenlabs_tts_v4`, and `audio.transcript` if you want captions. A single deck takes a few minutes of agent time plus the voice generation. A large batch takes hours. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are timing or file type. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `document.pages` returns CLI exit 2 "Nothing at that URL" | The path was typed, not taken from the upload. Pass the `url` that `invideo asset upload` or `add_media` returned. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | `document.pages` returns no thread | The agent reads the project and checks the file type. | | `document.pages` makes nothing | The file must be a PDF or office file in the project's files. Upload it again with `start_upload`. | | A slide changes before its line ends | The slide clip is shorter than its voice clip. Trim the slide's tail to the voice clip's end with `trim_clip`. | | `trim_clip` is refused as stale | `from_f` must match the edge as last read. Call `get_timeline` and send the new value. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` and rebuild the ops. | | CLI exit 5 | Credits ran out. Stop the batch and tell the person. | | `timeout` on `generate` | Do not call it again. `read` the thread or call `status`. | | Avoid: resend `generate` to check on it | Instead: `read` the URL after `retry_after_s`. | | Avoid: edit main | Instead: create a branch with `timeline_history`. | #### Prompts to try Each prompt is a real variation of this job. ```text Turn every PDF in ./decks into a narrated video. Same voice for all. Do a few decks, show me the frames, then do the next few. ``` ```text Make a video from training.pptx. Use my speaker notes below as the script, one note per slide. No captions. 16:9. ``` ```text Narrate this deck in a warm female voice, and add burned-in captions at the bottom in white with a dark background. ``` #### When to use something else invideo does not read speaker notes from a PPTX. Paste them, or let your agent read the file on your computer first. For animated slide builds, export the deck from PowerPoint or Keynote as a video and bring that in. For a presenter on camera, record yourself or use an avatar tool such as HeyGen or Synthesia. #### Related - [Update one line and re-render, keep the rest](/how-to/training/update-one-line) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Turn a syllabus into a course of lesson videos](/how-to/training/online-course) - [Make an SRT captions file for an LMS](/how-to/training/srt-for-an-lms) - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Update one line and re-render Source: https://docs.invideo.io/how-to/training/update-one-line.md Change one spoken line or one on-screen word in a finished training video, re-voice only that line, and export again with nothing else changed. Update one line in a finished video: a new price, a renamed button, a changed policy. Your agent re-voices only that line, fits it into the cut, fixes the on-screen text, and exports again. Every other clip, cut and caption stays exactly as it was. Use invideo for this when the video lives on an invideo timeline, so a one-line fix is a few edits and a free export, not a new video. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt with the timeline URL. ```text In this invideo timeline , the line "Click Save" is now "Click Publish". Make a branch, re-voice only that line in the same voice, change the on-screen text to match, keep everything else, and show me frames around the change before you export. ``` In a chat app, you paste the timeline URL. In a terminal, the agent can find it with `invideo project list` and `invideo project show`. #### What you need Your agent needs the old video and the new words. - The timeline URL of the video, or the project name. - The old line and the new line, word for word. - The voice the video used. The agent finds it in the notebook: `read` shows the generation that made the narration and its inputs. - Any on-screen text that should change too. #### Steps The agent never edits main for this job. It works on a branch you can compare and throw away. The agent reads the timeline with `get_timeline`, then creates a branch with `timeline_history` action `create_branch`. It sees the new branch's URL. Every later edit goes to that URL. The agent prices `audio.transcript` with `dry_run` on the narration's sequence URL and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. When the timeline has captions, it reads the caption slides with `get_timeline` mode `collection` instead. It sees the clip id and the frames where the line sits. 1. The agent runs `read` on the thread that made the original narration, for its model id and `voice_id`, such as `elevenlabs_text_to_speech.elevenlabs_tts_v4`. It reads the model's inputs with `get_model`. If the model is gone, it runs `find_models` with the job in words and tells you the voice may change. 2. It calls `generate` with that model, that `voice_id`, the new line as `prompt` and `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It gets a thread URL and, when the result lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. The agent splits the old line out with `split_clip`, opens any extra time the new take needs on every track with `edit_time_range` mode `insert`, and removes the old line with `delete_clip` mode `leave_gap`. Then it places the new take in the gap with `place_media` mode `overwrite`, so nothing else moves. It sees a new `state_token`. The agent changes a text clip with `set_text`, or one caption slide with `set_caption_slide_text`. Words that did not change keep their timing. It sees the clip with the new words. The agent calls `capture` before, on and after the change, and listens with `media` `audio.waveform` on the new take for a click or a gap. It calls `check_timeline`. It sees frames and findings. The agent calls `export` on the branch URL with format `video`. It sees an export card with status `completed`. You compare it with the old export, and on your yes the agent makes the branch the default with `timeline_history` action `set_default`. The terminal version: ```bash invideo edit show --json invideo branch new --name fix-publish-line --token invideo media audio.transcript --dry-run invideo media audio.transcript \ --max-credits invideo notebook show # only when the original model is gone: invideo gen models --query "narration voice" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt="Click Publish." -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key fix-publish-line \ -i prompt="Click Publish." -i voice_id= invideo edit show --json invideo edit change --timeline T1 --token \ --operations @fix.json --dry-run invideo edit change --timeline T1 --token \ --operations @fix.json invideo edit show --json invideo edit change --timeline T1 --token \ --operations @place.json invideo edit capture --at 41,43,45 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the video's timeline URL, from `invideo edit new` or the editor. `` comes from `invideo edit show ` for `branch new`. - `` is the `branch_url` that `invideo branch new` returns. After that, `` comes from `invideo edit show `, read again before each change, because the main token is stale on the branch. - `` is the narration's sequence URL, `…/notebook/seq-N.M`, from `invideo notebook show `. - `` is the thread that made the original narration, and `` is the `voice_id` it shows. - `` is the video's project. `` is a notebook page of the project, listed by `invideo notebook show `. - `` is each dry run's `.estimated_credits`. - `` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The file behind `@fix.json` is the bare list of ops that `--operations` takes, sent in one `edit change`. It lands all or none. The agent splits at the later frame first, so `c12` still covers the earlier frame. `c12` is the narration clip and `c20` the text clip, from `invideo edit show`. ```json [ { "op": "split_clip", "clip": "c12", "at_f": 1290 }, { "op": "split_clip", "clip": "c12", "at_f": 1230 }, { "op": "edit_time_range", "timeline": "T1", "start_f": 1230, "end_f": 1260, "mode": "insert" }, { "op": "set_text", "clip": "c20", "text": "Click Publish" } ] ``` After the splits, the agent reads the timeline again for the new clip ids. The file behind `@place.json` then deletes the old line's clip with `delete_clip` mode `leave_gap` and places the new take with `place_media` mode `overwrite`. Its `asset` is the take's sequence URL from the paid `gen run` thread. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: the one new voice take, and a transcript if the video had none. - Free: the branch, every edit, `capture` and `export`. The whole fix takes a few minutes. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are a voice that does not match or a stale read. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | CLI exit 3 on the first change after `invideo branch new` | The main token is stale on the branch. Run `invideo edit show ` and use its `state_token`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | The new line sounds like another person | Use the same model and the same `voice_id` as the original take. `read` the old sequence for its inputs. | | The picture drifts after the change | The time was changed on one track only. Use `edit_time_range`, which changes every unlocked track. | | `split_clip` or `trim_clip` refused as stale | Read again with `get_timeline` and use the new frames. | | CLI exit 3 | Someone edited since your read. Run `invideo edit show` and rebuild the ops. | | A caption still shows the old words | Change that slide with `set_caption_slide_text`. `set_text` works only on a caption with one slide. | | The new take is shorter than the old line | Take the spare time out of every track with `edit_time_range` mode `close_gap`. | | A click at the seam | Add a short fade with `set_audio_fades` on the new take. | | Avoid: re-generate the whole narration | Instead: re-voice only the changed line. | | Avoid: edit main | Instead: branch with `timeline_history`, and set it default after approval. | #### Prompts to try Each prompt is a real variation of this job. ```text Our support email changed. Find every place the old email is said or shown in this timeline, fix each one on a branch, and list the timecodes. ``` ```text Replace the image on the pricing slide with new-ui.png and keep its timing. ``` ```text The intro line is too long. Re-voice it shorter and close the gap, then show me before and after frames. ``` #### When to use something else If the video was made outside invideo and you only have the MP4, the fix needs the original project. Bring the MP4 in and cut around the line, but a replaced line in mixed audio is hard to hide. For a presenter on camera, record the line again. Lip sync with `sync_lipsync_v3.video` fixes a mouth for a short span, but a new recording looks more natural. #### Related - [Turn slides into a narrated video, one deck or hundreds](/how-to/training/slides-to-narrated-video) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Translate a training video and retime the cut to fit the new voice](/how-to/training/translate-and-retime) - [Check your video before you say it is done](/how-to/check-your-video) - [Timeline edit operations](/reference/edit-operations) ### Make a training explainer from a document Source: https://docs.invideo.io/how-to/training/explainer-from-a-document.md Turn a policy, SOP or handbook page into a narrated explainer video with b-roll, text slides and captions, and no talking avatar. Turn a document into a training explainer video: a policy, an SOP, a handbook chapter, a compliance memo. Your agent reads it, writes a short script, voices it, covers it with stock or generated b-roll and text slides, and adds captions. No avatar and no presenter on camera. Use invideo for this when you want the script, the voice and every shot on one editable timeline, so a reviewer can ask for a change and the agent fixes that one part. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Read handbook-ch3.pdf and make a short training explainer in invideo. Write the script first and show it to me. Then voice it with a clear narrator, add stock b-roll and a text slide for each key rule, and add captions. No avatar. Show me frames before you export. ``` In a chat app, you attach the document to the chat. In a terminal, the agent reads the file from the folder you name. #### What you need The document is the source. The rest are choices. - The document: PDF, DOCX, a web page you saved, or text you paste. - The length you want, and who watches it. - A voice style. The agent sends you voice previews from `search_library`. - Brand colors and a font, if you have them. A font file comes in with `add_media`. - The shape: 16:9 for an LMS or a meeting screen, 9:16 for phones. #### Steps The agent writes, you approve, then it spends. The agent reads the document and writes a script in short scenes, each with one line of narration and one key rule to show. It sees your approval or your changes. 1. The agent runs `find_models` with "narration voice", picks one, and reads its inputs with `get_model`. A good pick is `seed_tts_2_0`. Your agent can search for others with `find_models`. It picks a voice with `search_library` in `seed_tts_2_0_voices`, the library for that model. 2. It calls `generate` with the script as `prompt`, the `voice_id` and `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It gets a thread URL and, when the result lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. The agent searches `search_library` in `stock_video` for each scene and sends you the previews. Where stock has nothing that fits, it generates the shot. 1. It runs `find_models` with the shot in words, and reads its pick with `get_model`. A good pick is `seedance_2_5.r2v`. Your agent can search for others with `find_models`. 2. It calls `generate` with a `prompt`, `generate_audio` false and `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It reads the shot's sequence URL with `read`. It sees stock ids and sequence URLs. The agent makes a timeline with `new_timeline` and a branch with `timeline_history`. It places the voice on an audio track and the b-roll on a video track with `insert_media` or `place_media`, adding stock with `add_media` and `stock`. It sees a new `state_token`. For each key rule, the agent adds a text clip with `add_text` over the b-roll, styled with your font and colors. It sees the text clips in `get_timeline`. The agent prices `audio.transcript` with `dry_run` on the voice's sequence URL and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. It sees a caption clip. The agent calls `capture` at each scene change and `check_timeline`, then `export` with format `video`. It sees an export card with status `completed`. The terminal version: ```bash invideo project new --title "Handbook chapter 3" invideo library search --library stock_video \ --query "office team meeting" invideo library search --library seed_tts_2_0_voices \ --query "calm female trainer" invideo gen models --query "narration voice" invideo gen model --model seed_tts_2_0 invideo gen run --model seed_tts_2_0 --dry-run \ -i prompt=@script.txt -i voice_id= invideo gen run --model seed_tts_2_0 \ --max-credits --idempotency-key handbook-3-voice \ -i prompt=@script.txt -i voice_id= invideo status --wait invideo notebook show invideo media audio.transcript --dry-run invideo media audio.transcript \ --max-credits invideo edit new --name "Chapter 3 v1" invideo asset add --stock invideo edit show --json invideo branch new --name chapter-3 --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @scenes.json invideo edit capture --at 3,20,45,80 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` comes from the `seed_tts_2_0_voices` search. It works only with `seed_tts_2_0`. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is each dry run's `.estimated_credits`. - `` is the `url` the paid `gen run` returns. `` is the voice file that `notebook show` on it lists. - `` comes from the `stock_video` search. - `` is the `branch_url` that `invideo branch new` returns. - `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read again before each change. - `` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The file behind `@scenes.json` is the bare list of ops that `--operations @scenes.json` takes. It holds one text slide for one rule. `start_f` and `end_f` are frames at the timeline's frame rate. ```json [ { "op": "add_text", "track": "V2", "start_f": 360, "end_f": 540, "text": "Report every spill at once", "style": { "font_size": 72, "font_weight": 700, "color": "#ffffff", "background_color": "#1a1a1acc", "align": "center" } } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: the voice, the transcript for captions, each stock clip you add, and each generated shot. - Free: searching stock, every edit, `capture` and each export. Generated shots cost the most. Stock is cheaper, and text slides are free. A short explainer takes under an hour. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems come from the script or the shots. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `generate` refuses the voice: "voice_ids are model-specific" | The voice comes from another model's library. Search `seed_tts_2_0_voices` for `seed_tts_2_0`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | The script misses a rule | Ask the agent to list every rule in the document first, then map each to a scene. | | Stock looks generic | Search with concrete words from the scene. Or generate the shot, after a dry run. | | A generated shot has sound you do not want | Set `generate_audio` to false, or mute its audio clip with `set_audio_muted`. | | Text is hard to read on busy b-roll | Add a `background_color` to the text style, or blur the b-roll with the `gaussian_blur` effect through `add_effect`, or darken it with `edit_grade`. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | CLI exit 5 | Credits ran out. Stop and tell the person. | | Avoid: say done after the last edit | Instead: `capture` and `check_timeline` first. | #### Prompts to try Each prompt is a real variation of this job. ```text Turn our new expense policy into a short explainer. Text slides only, no b-roll, our brand colors, and captions. ``` ```text Make a short safety explainer from sop-forklift.docx. Use stock warehouse footage. Vertical for phones. ``` ```text Read this onboarding page and make a short explainer for each section. Use the same voice and style for all of them. ``` #### When to use something else If you want a talking presenter, use an avatar tool such as HeyGen or Synthesia, then bring the clip in for captions and b-roll. invideo does not check that the script is legally correct. Your policy owner reviews the script before the agent voices it. #### Related - [Turn slides into a narrated video, one deck or hundreds](/how-to/training/slides-to-narrated-video) - [Make a whiteboard explainer from your script](/how-to/training/whiteboard-explainer) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [When to use HeyGen or Synthesia vs invideo](/compare/heygen-synthesia) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Translate a training video and retime the cut to fit the new voice Source: https://docs.invideo.io/how-to/training/translate-and-retime.md Translate and dub a training video: approve the translated script, voice it, then stretch the cut so the new voice fits at a natural pace. Translate a training video into another language: a translated voiceover, a dub, a localized version. Your agent transcribes the original, translates the script, and waits for your approval. Then it voices the new script and changes the cut so the new voice fits, holding a slide longer or opening a pause, instead of speeding the voice up. Use invideo for this when you want the translated voice at a natural pace, with the picture retimed on an editable timeline, and a branch per language you can compare. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Translate this training video into German. Transcribe it, translate the script, and show me the German script before you voice anything. Then voice it, mute the English voice, and retime the cut so the German fits. Never speed up the voice. Work on a branch called de. ``` In a chat app, you paste the timeline URL or drag the video in. In a terminal, the agent uploads the file you name. #### What you need The script approval is the step that matters most. - The video, on an invideo timeline or as a file. - The target language. - A person who reads that language and approves the script. The agent translates, but a native speaker catches the errors. - A voice: a stock voice from `search_library`, or a clone of the original speaker with their consent. - A glossary of product names and terms that must stay as they are. #### Steps The agent works on one branch per language. The agent prices `audio.transcript` with `dry_run` on the video's sequence URL from `add_media` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. It sees every word with its time and speaker. The agent translates line by line and keeps each line's original start and end. It writes the script to a brief with `new_brief`, so you can read and edit it in invideo. It sees your approval, or applies your changes with `edit`. 1. The agent runs `find_models` with "narration voice" and the language, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a voice whose languages include the target, from `search_library` in `elevenlabs_text_to_speech_voices`. For the original speaker's voice, a good pick is `seed_audio_1_0.ta2a`, with their clips as `reference_audio_1` to `reference_audio_3`. Your agent can search for others with `find_models`. 2. It calls `generate` per line with `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` per line with `max_credits` set to that price and an `idempotency_key`, like `line-07-de`. It gets a thread URL and, when the result lands, one sequence URL per line. It reads each URL with `read` and never calls `generate` again to check. The agent creates a branch with `timeline_history`, and mutes the original voice there with `set_audio_muted`. It sees a new `state_token`. The agent places each new line at its original start with `place_media`. Where a line runs long, it opens time on every track with `edit_time_range` mode `insert`, or holds a slide longer with `trim_clip` on its tail. Where a line runs short, it removes the extra time with `edit_time_range` mode `close_gap`. It never uses `retime` on the voice. It sees each line end before the next starts. The agent changes text clips with `set_text`, and adds captions with `add_captions` from a transcript of the new voice. It sees the translated text in `capture` frames. The agent calls `capture` at each changed spot and `check_timeline`, then `export` on the branch. It sees an export card with status `completed`. The terminal version: ```bash invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo library search \ --library elevenlabs_text_to_speech_voices --query "German narrator" invideo gen models --query "German narration voice" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@line-07-de.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key line-07-de \ -i prompt=@line-07-de.txt -i voice_id= invideo status --wait invideo notebook show invideo edit show --json invideo branch new --name de --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @retime-de.json invideo edit capture --at 10,42,75 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out/de ``` Where each value comes from: - `` is the video's `url` from `invideo asset upload`, a `…/notebook/seq-N.M` URL. - `` is each dry run's `.estimated_credits`. - `` is the video's project. `` is a notebook page of the project, listed by `invideo notebook show `. - `` comes from the `library search` line. It works only with `elevenlabs_text_to_speech.elevenlabs_tts_v4`. - `` is the `url` the paid `gen run` returns. `notebook show` on it lists the take's sequence URL. - `` is the video's timeline URL, from `invideo edit new` or the editor. `` comes from `invideo edit show ` for `branch new`. - `` is the `branch_url` that `invideo branch new` returns. After that, `` comes from `invideo edit show `, read again before each change, because the main token is stale on the branch. - `` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/de/export.mp4`, and the agent renames it. The file behind `@retime-de.json` is the bare list of ops that `--operations` takes. Here one line runs long, so the agent opens the extra frames on every track and places the take. `c4` is the original voice clip's id from `invideo edit show`. The `asset` is the take's sequence URL from the thread. ```json [ { "op": "set_audio_muted", "target": "c4", "muted": true }, { "op": "edit_time_range", "timeline": "T1", "start_f": 1260, "end_f": 1290, "mode": "insert" }, { "op": "place_media", "asset": "", "track": "A1", "at_f": 1170, "source_start_seconds": 0, "source_end_seconds": 4, "mode": "overwrite", "linked_audio": false } ] ``` ##### No one-shot dub invideo has no model that translates a whole video in one call. For a quick draft with no script step, use a dubbing service, named at the end of this page. Use the steps above when the wording matters. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: the transcript, each voice take, and stem separation if needed. - Free: the branch, every edit, `capture` and `export`. The voice and the edit take under an hour per language. Your review of the script takes the longest. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are lines that do not fit. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the video's sequence URL from `add_media` or `invideo asset upload`. | | CLI exit 3 on the first change after `invideo branch new` | The main token is stale on the branch. Run `invideo edit show ` and use its `state_token`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | A line overlaps the next | Open time with `edit_time_range` mode `insert` at the end of the line, or hold the slide longer. | | The picture drifts out of sync | The time changed on one track only. Use `edit_time_range`, which moves every unlocked track. | | The music cuts out with the old voice | The voice and music share one clip. Split stems with `media` `audio.separate` on the video's sequence URL, after a dry run, and keep the music stem. | | Brand names are translated | Keep them in the script as they must be said, and list them in the brief. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` and rebuild. | | Avoid: speed up the voice to fit | Instead: retime the cut. Fast speech is hard to follow in training. | | Avoid: voice before approval | Instead: show the script and wait for a yes. | #### Prompts to try Each prompt is a real variation of this job. ```text Make Spanish (Mexico) and Portuguese (Brazil) versions of this video, one branch each. Use the glossary in our brief. Show me both scripts first. ``` ```text Give me a quick French draft of the first few lines only, so I can see if the length works before we do the rest. ``` ```text Translate only the on-screen text and captions into Japanese. Keep the English voice. ``` #### When to use something else invideo does not judge translation quality. A native speaker or a translation vendor reviews the script. For a one-shot dub with no script step, use ElevenLabs Dubbing or HeyGen video translation, then bring the file into invideo for the cut and captions. For a speaker on camera, the new voice does not match their lips. Re-sync the mouth with a lip sync model, as on [Dub existing footage](/how-to/training/dub-existing-footage). #### Related - [Dub existing footage](/how-to/training/dub-existing-footage) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Make an SRT captions file for an LMS](/how-to/training/srt-for-an-lms) - [Localize a winning ad](/how-to/marketing/localize-a-winning-ad) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Dub existing footage Source: https://docs.invideo.io/how-to/training/dub-existing-footage.md Dub, translate or re-voice footage you already have: new speech timed to the video, the music kept, and the lips re-synced where faces show. Dub existing footage: translate it, re-voice it, or replace a speaker's voice in a video you already shot. Your agent makes new speech timed to the picture, keeps the music and effects, and re-syncs the lips where a face is on screen. You get the dubbed video on an editable timeline, with the original sound still there to switch back. Use invideo for this when you want speech timing, lip sync and the final mix in one project, with the original kept and a branch per language. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Dub interview.mp4 into Spanish (Spain) in invideo. Show me the Spanish lines first. Keep the music. Re-sync the speaker's lips. Mute the original voice on a branch, don't delete it, and show me frames before you export. ``` In a chat app, you drag the video into the project. In a terminal, the agent uploads the file you name. #### What you need These are the inputs for a good dub. - The footage, with its sound. - The target language, or the new lines if you are re-voicing in the same language. - Who approves the new lines. - The voice: a stock voice, or the original speaker's voice cloned with their consent from short clean clips. - Whether faces are on screen. Lip sync costs more and is needed only where a mouth shows. #### Steps There are two ways to make the speech. The agent picks one with you. Both make one take per line, placed at the line's original time. - `seed_audio_1_0.ta2a` speaks your lines in the original speaker's voice, from one to three reference clips tagged `@Audio1` to `@Audio3`. - `elevenlabs_text_to_speech.elevenlabs_tts_v4` with a stock voice, as on [Translate a training video and retime the cut to fit the new voice](/how-to/training/translate-and-retime). invideo has no model that dubs a whole video in one call. For that, use a dubbing service, named at the end of this page. The agent adds the file with `add_media`. It prices `audio.transcript` with `dry_run` on the file's sequence URL and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. It sees every word with its time and speaker. The agent translates or rewrites the lines, keeps their times, and shows you the script. It sees your yes or your changes. The agent runs `media` `audio.separate` on the footage's sequence URL with `dry_run`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it runs it with `max_credits` set to that price and an `idempotency_key`. It sees new sequences for the voice and the rest of the sound. 1. The agent runs `find_models` with the job in words, such as "seed audio speech in a reference voice", picks a model, and reads its inputs with `get_model`. A good pick to keep the speaker's voice is `seed_audio_1_0.ta2a`, with a clean clip of the speaker as `reference_audio_1`, tagged `@Audio1` in the `prompt`. For a stock voice, a good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4` with a `voice_id` from `elevenlabs_text_to_speech_voices`. Your agent can search for others with `find_models`. 2. It calls `generate` per line with `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` per line with `max_credits` set to that price and an `idempotency_key`, like `line-01-es`. It gets a thread URL and, when the result lands, one audio sequence URL per line. It reads each URL with `read` and never calls `generate` again to check. Where a face speaks on screen, the agent re-syncs the lips. The lip sync models take one audio file. 1. The agent joins the line takes into one track with `media` `audio.concat`. 2. It runs `find_models` with "lip sync", and reads its pick with `get_model`. A good pick is `sync_lipsync_v3.video`. Your agent can search for others with `find_models`. 3. It calls `generate` with the footage as `video`, the joined speech as `audio` and `dry_run: true`, and tells you the price. 4. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It reads the new video's sequence URL with `read`, and looks at it with `media` `video.frames` before it uses it. The agent creates a branch with `timeline_history`. On the branch it mutes the original sound with `set_audio_muted` and places the music stem and each new line at its original start with `insert_media`. It sees a new `state_token`. The agent calls `capture` on faces mid-sentence, `media` `audio.loudness` on the mix, and `check_timeline`. Then it calls `export`. It sees an export card with status `completed`. The terminal version: ```bash invideo edit new --name "Interview ES" invideo asset upload ./interview.mp4 invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo media audio.separate --dry-run invideo media audio.separate --max-credits \ --idempotency-key stems-1 invideo gen models --query "seed audio reference voice" invideo gen model --model seed_audio_1_0.ta2a invideo gen run --model seed_audio_1_0.ta2a --dry-run \ --input line-01-es.json invideo gen run --model seed_audio_1_0.ta2a \ --max-credits --idempotency-key line-01-es --input line-01-es.json invideo gen models --query "lip sync" invideo gen model --model sync_lipsync_v3.video invideo gen run --model sync_lipsync_v3.video --dry-run \ -i video= -i audio= invideo gen run --model sync_lipsync_v3.video \ --max-credits --idempotency-key lipsync-1 \ -i video= -i audio= invideo status --wait invideo notebook show invideo edit show --json invideo branch new --name dub-es --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @mix.json invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` The file `line-01-es.json` holds the model's inputs alone, as `get_model` lists them, with no `inputs` wrapper. The dry run and the paid run read the same file, so the run that spends is the run that was priced. ```json { "prompt": "@Audio1, calm and clear: \"Bienvenidos al curso.\"", "reference_audio_1": "" } ``` Where each value comes from: - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is the `url` that `invideo asset upload ` returns, a `…/notebook/seq-N.M` URL. - `` is the sequence URL of a clean clip of the speaker, such as the voice stem `audio.separate` makes. - `` is each dry run's `.estimated_credits`. - `` is a notebook page of the project, listed by `invideo notebook show `. - `` is the joined track from `audio.concat`. `` is the `url` the paid `gen run` returns, and `notebook show` on it lists the new video. - `` is the `branch_url` that `invideo branch new` returns. - `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read again before each change. - `@mix.json` reads a bare JSON list of ops: `set_audio_muted` on the original sound and `insert_media` for each new line. - `` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The MCP `generate` call for one line, in the speaker's own voice, as a dry run. Over MCP the inputs go inside `inputs`. The paid call is the same with `max_credits` set to the price and an `idempotency_key`, without `dry_run`. ```json { "model": "seed_audio_1_0.ta2a", "dry_run": true, "inputs": { "prompt": "@Audio1, calm and clear: \"Bienvenidos al curso.\"", "reference_audio_1": "" } } ``` For a file without a timeline, `media` `video.replaceAudio` on the file's sequence URL, with `audio_input`, makes a new video with the new sound. The timeline path keeps the original, so prefer it. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: the transcript, stem separation, the new speech, and lip sync, which is the largest part. - Free: every edit, branch and export. - The tool ops in `media`, like `audio.concat`: the dry run shows the price before anything starts. A short clip takes a few minutes of agent time plus generation. Lip sync takes longer. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are length, voice or lips. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | CLI exit 2 "inputs is not an input of this model" | The `--input` file has an `inputs` wrapper. Put the model's inputs at the top level of the file. | | `audio.transcript` or `audio.separate` refused with `code: "not_found"` | The call named a media bin asset. Pass the footage's sequence URL from `add_media` or `invideo asset upload`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | A new line overlaps the next | Shorten the line, or open time on every track with `edit_time_range` mode `insert`. | | `seed_audio_1_0.ta2a` refuses the inputs | It needs `reference_audio_1`, and each clip must meet the limits `get_model` lists. | | `sync_lipsync_v3.video` refuses the speech | It takes one audio file. Join the takes with `audio.concat`, or export the dubbed timeline with `export` mode `audio` and pass that. | | The lips drift at the end | The speech and video lengths differ. Set `sync_mode` on `sync_lipsync_v3.video`, or trim the speech first. | | The music is gone | The original sound was muted whole. Place the music stem from `audio.separate`. | | The cloned voice sounds off | Use clean reference clips with one speaker and no music. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `timeout` on `generate` | Do not call it again. `read` the thread or call `status`. | | Avoid: delete the original sound | Instead: mute it with `set_audio_muted` on a branch. | #### Prompts to try Each prompt is a real variation of this job. ```text Re-voice this narrator in a younger female voice, same words, same timing. No lip sync, the narrator is off screen. ``` ```text Make a quick German draft of this English video in a stock voice, one take per line. Keep the music. I'll decide on lip sync after. ``` ```text Dub only the first speaker in this panel into French. Keep the others in English. ``` #### When to use something else Clone a voice only with the speaker's consent. For many speakers, many languages and a review workflow, a dubbing service such as ElevenLabs Dubbing or HeyGen video translation does the whole job, and invideo finishes the cut and captions. invideo does not judge translation quality, so a native speaker reviews the lines. #### Related - [Translate a training video and retime the cut to fit the new voice](/how-to/training/translate-and-retime) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Localize a winning ad](/how-to/marketing/localize-a-winning-ad) - [Use ElevenLabs with invideo](/integrations/elevenlabs) - [Models](/reference/models) ### Make an SRT captions file for an LMS Source: https://docs.invideo.io/how-to/training/srt-for-an-lms.md Get an SRT or VTT subtitles file for your training video, with words you checked on the timeline, ready to upload to your LMS. Get a captions file for your learning platform: an SRT file, a VTT file, subtitles your LMS shows as closed captions. Your agent transcribes the video, puts the captions on the timeline so you can fix any word, then reads the caption slides back and writes the file. The video itself stays clean, with no captions burned in, unless you want them. Use invideo for this when you want to correct the captions by eye on the timeline first, and get the same words as a sidecar file and, if you like, burned into the video. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make an SRT captions file for this training video . Transcribe it, put the captions on the timeline on a branch so I can fix words, then write lesson-01.srt from the caption slides. Keep each caption short. Export the video without the captions burned in. ``` In a chat app, the agent gives you the SRT text to save. In a terminal, it writes the file into your folder. #### What you need These are the inputs and the choices. - The video, on an invideo timeline or as a file. - The format your LMS takes: SRT or VTT. Most take both. - Words that the transcript may get wrong: names, product terms, acronyms. - Burned-in captions as well, or the sidecar file only. #### Steps The timeline is where you check the words. The file comes from the timeline. The agent prices `audio.transcript` with `dry_run` on the video's sequence URL from `add_media` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. It sees every word with its time and speaker. The agent creates a branch with `timeline_history`, then groups the words into short slides and adds them with `add_captions`, with `slides` and `words`. It sees a caption clip in `get_timeline`. The agent fixes each wrong word you or the terms list point to with `set_caption_slide_text`, and a slide's edges with `trim_caption_slide`. It sees the new text with the word times kept. The agent calls `get_timeline` with mode `collection` and collection `caption_slide`. It pages with `next_offset` and the same `snapshot` until it has every slide. It sees each slide's text and its start and end. The agent turns each slide into one numbered cue and writes the SRT or VTT file itself. Times in a read are rational, `{value, rate}`, which is `value / rate` seconds. It sees a file that starts at cue 1 and has no overlaps. The agent turns the caption clip off with `set_clip_enabled`, then calls `export`. For burned-in captions too, it exports once more with the clip on. It sees an export card with status `completed`. The terminal version: ```bash invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo edit show --json invideo branch new --name captions --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @captions.json invideo edit show --mode collection \ --collection caption_slide --json > slides.json invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the video's `url` from `invideo asset upload`, a `…/notebook/seq-N.M` URL. - `` is the dry run's `.estimated_credits`. - `` is the video's timeline URL, from `invideo edit new` or the editor. `` comes from `invideo edit show ` for `branch new`. - `` is the `branch_url` that `invideo branch new` returns. After that, `` comes from `invideo edit show `, read again before each change, because the main token is stale on the branch. - `` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The file behind `@captions.json` is the bare list of ops that `--operations` takes. It adds the caption clip with its first slides. `start_f` and `end_f` are frames at the timeline's frame rate. ```json [ { "op": "add_captions", "track": "V3", "slides": [ { "text": "Welcome to the safety course.", "start_f": 0, "end_f": 75 }, { "text": "First, find your nearest exit.", "start_f": 84, "end_f": 165 } ] } ] ``` The SRT file the agent writes from those slides: ```text 1 00:00:00,000 --> 00:00:02,500 Welcome to the safety course. 2 00:00:02,800 --> 00:00:05,500 First, find your nearest exit. ``` A VTT file starts with a `WEBVTT` line, and its times use a full stop before the milliseconds. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: the transcript, once per file. - Free: the caption clip, every fix, reading the slides, writing the file, `export`. The file takes a few minutes after the transcript is ready. Your word check takes the longest. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are times or missing slides. | Symptom | Fix | | --- | --- | | `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the video's sequence URL from `add_media` or `invideo asset upload`. | | CLI exit 3 on the first change after `invideo branch new` | The main token is stale on the branch. Run `invideo edit show ` and use its `state_token`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | The SRT is missing the end | The read was paged. Continue with `next_offset` and the same `snapshot`. | | A `snapshot` is refused | The timeline changed. Read again from the first page. | | A word is timed wrong | Split or join the timed pieces with `split_caption_fragment` and `merge_caption_fragment`. | | Captions are early or late in the LMS | The caption clip starts later than the video. Times in the file are timeline times, so export from the same start. | | Cues overlap | Two slides share frames. Trim one with `trim_caption_slide`, then read again. | | The LMS rejects the file | Check the format: SRT uses a comma before milliseconds, VTT a full stop and a `WEBVTT` first line. | | `set_text` refused on captions | That caption clip has several slides. Use `set_caption_slide_text`. | | Avoid: write the file from the raw transcript | Instead: write it from the caption slides, which hold your fixes. | #### Prompts to try Each prompt is a real variation of this job. ```text Write VTT captions for every lesson in this project, one file per lesson, named after each timeline. ``` ```text Make English and Spanish SRT files for this video. Translate the English caption slides line by line and keep the same times. ``` ```text Burn the captions into the video in white on a dark bar, and also give me the SRT file. ``` #### When to use something else invideo does not write SCC files, the broadcast caption format. Convert the SRT with a captioning tool such as Subtitle Edit. Uploading the file is done in your LMS, in the video's caption or subtitle settings. For legal caption quality on public content, see [Make closed captions and audio description for ADA Title II and Section 508](/how-to/training/captions-for-ada-508). #### Related - [Make closed captions and audio description for ADA Title II and Section 508](/how-to/training/captions-for-ada-508) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Turn a syllabus into a course of lesson videos](/how-to/training/online-course) - [Use Whisper timings with invideo](/integrations/whisper) - [Timeline edit operations](/reference/edit-operations) ### Make a whiteboard explainer from your script Source: https://docs.invideo.io/how-to/training/whiteboard-explainer.md Make a whiteboard-style explainer from your script: sketch frames from an image model, lines that draw themselves on, and a narrated voiceover. Make a whiteboard explainer or a whiteboard animation from your script: black line drawings on white, arrows and underlines that draw themselves on, and a voiceover. Here your agent builds it on a timeline from your script, scene by scene. Use invideo for this when you want the drawings, the voice and the timing on one editable timeline, so a changed sentence means one new scene, not a new video. invideo has no library of hand-drawn art and no drawing hand. Your agent makes the drawings with an image model, such as `flux_2_lora.ballpoint_pen_sketch`, and draws simple lines and arrows itself as shapes. For the classic hand that draws each picture, use a whiteboard tool, named at the end of this page. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a whiteboard explainer in invideo from script.txt. One scene per paragraph. Black marker drawings on white, one per scene. Draw an arrow or underline on as each key word is said. Calm narrator. Show me the first scenes before you make the rest. ``` In a chat app, you paste the script. In a terminal, the agent reads the file you name. #### What you need The script sets the length. The rest is style. - The script, split into scenes, or permission for the agent to split it. - The style: marker, ballpoint, colored pens, plain white or a board texture. - A voice. The agent sends previews from `search_library`. - The shape: 16:9 for most explainers. #### Steps The agent makes the first scenes, so you approve the style before it spends more. The agent splits the script into scenes, each with its line of narration and one picture to draw. It sees your yes on the scene list. 1. The agent runs `find_models` with "narration voice", picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a voice from `search_library` in `elevenlabs_text_to_speech_voices`. Your agent can search for others with `find_models`. 2. It calls `generate` with the script as `prompt`, the `voice_id` and `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It gets a thread URL and, when the result lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. 4. It prices `audio.transcript` with `dry_run` on the voice's sequence URL and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. It sees when each key word is said. 1. The agent runs `find_models` with "hand-drawn whiteboard image", picks one, and reads its inputs with `get_model`. A good pick for a sketch look is `flux_2_lora.ballpoint_pen_sketch`. For a character that stays the same across scenes, a good pick is `nano_banana_2_1`, which takes `reference_images`. Your agent can search for others with `find_models`. 2. For each scene it calls `generate` with the `prompt`, `aspect_ratio` 16:9 and `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, like `scene-01`. It gets a thread URL and, when the result lands, one image sequence URL per scene. It reads each URL with `read` and never calls `generate` again to check. The agent makes a 16:9 timeline with `new_timeline` and a branch with `timeline_history`. It places the voice and the drawings with `insert_media`, and fits each drawing to its line with `trim_clip`. It sees a new `state_token`. The agent puts a plain white clip before each drawing and adds a `wipe` with `add_transition` between them, so the drawing is wiped on. For a slow push-in, it adds a `zoom_x` and a `zoom_y` lane with `add_keyframe_lane` and points with `add_keyframes`. It sees the reveal in `capture` frames. For an arrow, a circle or an underline, the agent adds a shape with `add_shape`, preset `path`, an SVG path and a black stroke. In a second call, `trim_shape_path` grows the drawn part from nothing to the full line, timed to the word. It sees the line grow in `capture` frames. The agent calls `capture` mid-reveal and mid-line in each scene, and `check_timeline`. Then it calls `export`. It sees an export card with status `completed`. The terminal version: ```bash invideo gen models --query "hand-drawn whiteboard image" invideo gen model --model flux_2_lora.ballpoint_pen_sketch invideo gen run --model flux_2_lora.ballpoint_pen_sketch \ --dry-run -i prompt=@scene-01.txt -i aspect_ratio=16:9 invideo gen run --model flux_2_lora.ballpoint_pen_sketch \ --max-credits --idempotency-key scene-01 \ -i prompt=@scene-01.txt -i aspect_ratio=16:9 invideo gen models --query "narration voice" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@script.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key whiteboard-voice \ -i prompt=@script.txt -i voice_id= invideo status --wait invideo notebook show invideo media audio.transcript --dry-run invideo media audio.transcript \ --max-credits invideo edit new --name "Whiteboard v1" invideo edit show --json invideo branch new --name scenes-1-2 --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @scene-01.json invideo edit show --json invideo edit change --timeline T1 --token \ --operations @draw-on.json invideo edit capture --at 1,2.5,4 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is each dry run's `.estimated_credits`. - `` comes from `invideo library search` in `elevenlabs_text_to_speech_voices`. It works only with `elevenlabs_text_to_speech.elevenlabs_tts_v4`. - `` is the `url` the paid `gen run` returns. `` is the voice file that `notebook show` on it lists. - `` is the `branch_url` that `invideo branch new` returns. - `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read again before each change. - `` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. Each ops file is the bare list of ops that `--operations` takes. The file behind `@scene-01.json` adds an underline shape. `at_f` and `duration_f` are frames at the timeline's frame rate. ```json [ { "op": "add_shape", "track": "V3", "at_f": 90, "duration_f": 150, "preset": "path", "d": "M 0 0 L 600 0", "width": 600, "height": 20, "x": 0, "y": 260, "fill": "#00000000", "stroke": { "color": "#111111", "width": 10, "cap": "round" } } ] ``` The file behind `@draw-on.json` goes in the next call and draws the line on. `c14` is the new shape clip and `` its path, both from `invideo edit show` after the first call. `at_seconds` counts from the start of the shape clip. ```json [ { "op": "trim_shape_path", "clip": "c14", "path": "", "at_seconds": 0, "enabled": true, "start": 0, "end": 0 }, { "op": "trim_shape_path", "clip": "c14", "path": "", "at_seconds": 1.5, "enabled": true, "start": 0, "end": 100 } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: one drawing per scene, the voice, and the transcript for word times. - Free: the shapes, the line draw-on, the reveals, every edit, `capture` and `export`. Your cost grows with the number of scenes and the length of the script. A short explainer takes under an hour. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are style drift or timing. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the voice's sequence URL from the `generate` result. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | Each drawing looks like a different artist | Use `nano_banana_2_1` with the first approved drawing in `reference_images`. | | The wipe goes through black | `add_edge_transition` fades from black. Use `add_transition` between a white clip and the drawing. | | A line appears at once | `trim_shape_path` needs a point with `end: 0` at the start and a later point with `end: 100`. If it still jumps, read `timeline_catalog` for `trim_shape_path`, and start a lane for the trim with `create_shape_keyframe_lane`. | | The line draws at the wrong moment | Read the word times from `audio.transcript` and set `at_f` from them. | | `trim_clip` refused as stale | Read with `get_timeline` and use the edge's current frame. | | Avoid: make every scene before approval | Instead: make the first scenes and show frames. | #### Prompts to try Each prompt is a real variation of this job. ```text Make a whiteboard explainer for our refund policy. Blue and black marker. Circle each number as it is said. ``` ```text Turn this script into a whiteboard video with one recurring character, a woman in a blue jacket, in every scene. ``` ```text Redo scene 4 only. The new line is in scene-04.txt. Keep every other scene as it is. ``` #### When to use something else For a hand that draws each picture stroke by stroke, use a whiteboard tool such as VideoScribe or Doodly. You can export from there and bring the video into invideo for voice, captions and the final cut. #### Related - [Make a training explainer from a document, without an avatar](/how-to/training/explainer-from-a-document) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Make a lyric video or text animation for your song](/how-to/creators/lyric-video) - [Timeline edit operations](/reference/edit-operations) - [Models](/reference/models) ### Voice a script or narrate a course Source: https://docs.invideo.io/how-to/training/voice-a-script-or-narrate-a-course.md Get a voiceover for a script or narration for every lesson of a course, from a stock voice or a consented clone, as clean audio files. Get a voiceover or narration for your script: an AI voiceover, text to speech, a narrated course, one voice across every lesson. Your agent finds voices and sends you previews, voices the script, cleans up a rough recording if you have one, and delivers audio files or places the voice on a timeline. Use invideo for this when you want the voice to land on the same timeline as your slides or footage, and fix one line later without a new session. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Voice script.txt in invideo. Send me a few calm, clear narrator voices to preview first. After I pick one, voice it in parts, one take per paragraph, and export the narration as a WAV file. ``` In a chat app, you paste the script and listen to the previews in the chat. In a terminal, the agent reads the file and prints the preview links. #### What you need Your agent asks for these. - The script, or one script per lesson. - The voice you want, in words: calm, warm, young, British, and so on. - The language of the script. - For a clone: short clean clips of the speaker, and their consent. - What you want back: audio files, or the voice placed on a timeline. #### Steps The agent previews before it spends. The agent runs `find_models` with the job in words, such as "narration voice", picks one, and reads its inputs with `get_model`. A good pick is `seed_tts_2_0`, which has `speech_rate` and `silence_duration`. `elevenlabs_text_to_speech.elevenlabs_tts_v4` takes emotion tags in the text, and `gemini_3_1_flash_tts` takes a second speaker, for a dialogue. Your agent can search for others with `find_models`. It sees the model's input schema. The agent calls `search_library` with the voice library of the model it picked, and a query such as "calm narrator". A voice id works only with its own model. `elevenlabs_text_to_speech.elevenlabs_tts_v4` takes a voice from `elevenlabs_text_to_speech_voices`. `seed_tts_2_0` takes a voice from `seed_tts_2_0_voices`, which returns a list to browse when the query is left out. Each voice has a `preview`. Your workspace's own cloned voices are listed too. It sees voice ids and preview links, and sends you the links. 1. The agent calls `generate` with `dry_run: true`, one paragraph and your chosen `voice_id`, and tells you the price. 2. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It gets a thread URL and, when the result lands, a sequence URL. It reads that URL with `read`, never with a second `generate`, and sends you the link. The agent voices the rest, one take per paragraph or lesson, the same way. It runs a dry run and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key` per take. It sees one sequence URL per take, and reads each with `read`. If you recorded some lines yourself, the agent runs `media` `audio.clean` on the recording's sequence URL with `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it runs it with `max_credits` set to that price and an `idempotency_key`. It sees a new sequence beside your original, which stays. The agent runs `media` `audio.loudness` and `audio.content` on each take. It looks for long silences and level jumps between takes. It sees the loudness and the speech and silence spans. For files, the agent places the takes on `A1` in order with `insert_media`, each take's sequence URL as the `asset`. It calls `export` with `mode` `audio`, `audio_format` `wav`, and `target_lufs` for your platform. For a video, it places the voice with `insert_media` next to the picture. It sees an export card with status `completed`. The terminal version: ```bash invideo gen models --query "narration voice" invideo gen model --model seed_tts_2_0 invideo library search \ --library seed_tts_2_0_voices --query "calm narrator" invideo gen run --model seed_tts_2_0 --dry-run \ -i prompt=@lesson-01.txt -i voice_id= invideo gen run --model seed_tts_2_0 --max-credits \ --idempotency-key lesson-01 -i prompt=@lesson-01.txt \ -i voice_id= invideo status --wait invideo notebook show invideo media audio.loudness invideo edit new --name "Narration" invideo edit show --json invideo edit change --timeline T1 --token \ --operations @takes.json invideo edit export --format video --mode audio \ --audio-format wav --target-lufs -16 --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` comes from `invideo project new`, and `` from `invideo edit new`. - `` is a notebook page of the project, listed by `invideo notebook show `. - `` comes from the `seed_tts_2_0_voices` search. For `elevenlabs_text_to_speech.elevenlabs_tts_v4`, search `elevenlabs_text_to_speech_voices` instead. A voice id from one library is refused by the other model. - `` is the dry run's `.estimated_credits`. - `` is the `url` the paid `gen run` returns, and `` is the take that `notebook show` on it lists. - `` comes from `invideo edit show`. `@takes.json` reads a bare JSON list of `insert_media` ops, one per take, on `A1`. - `` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the file in `./out`. ##### Clone a voice, with consent Clone a voice only when the speaker agrees, in writing. The agent brings in short clean clips of them with `add_media`. It runs `find_models` with "seed audio", and reads the inputs of its pick with `get_model`. A good pick is `seed_audio_1_0.ta2a`. Your agent can search for others with `find_models`. The first clip goes in `reference_audio_1`, and more clips in `reference_audio_2` and `reference_audio_3`. The prompt tags each clip as `@Audio1` to `@Audio3`. This is the full MCP `generate` call, as the dry run. The agent tells you its price. For a price of 1 credit or more it waits for your yes. Then it sends the paid call, the same with `max_credits` set to the price and an `idempotency_key`, without `dry_run`. It returns a thread URL, and the agent reads the clone take's sequence URL with `read`. `` is the sequence URL `add_media` returned for a clip. ```json { "model": "seed_audio_1_0.ta2a", "dry_run": true, "inputs": { "prompt": "@Audio1, warm and steady: \"Welcome to lesson one.\"", "reference_audio_1": "" } } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: every voice take, a clone take, and `audio.clean`. - Free: searching voices, the previews, every edit and each export. - `audio.loudness` and `audio.content`: the dry run shows the price before anything starts. TTS prices go by the length of the text. A short script takes a few minutes. A full course takes longer, so run it in parts. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are a wrong voice id or a text that is too long. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `generate` refuses the voice: "voice_ids are model-specific" | The voice comes from another model's library. Search the library `get_model` names on the voice input: `seed_tts_2_0_voices` for `seed_tts_2_0`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | `generate` refuses the text | It is longer than the model takes. Split it into paragraphs. | | Takes sound different from each other | Use the same model, voice and settings for every take. | | A word is said wrong | Spell it as it sounds in the prompt, then voice that line again. | | Long pauses between takes | Trim them on the timeline with `trim_clip`, or lower `silence_duration` on `seed_tts_2_0`. | | `timeout` on `generate` | Do not call it again. `read` the thread or call `status`. | | CLI exit 5 | Credits ran out. Stop and tell the person. | | Avoid: clone a voice without consent | Instead: use a stock voice, or ask the speaker first. | #### Prompts to try Each prompt is a real variation of this job. ```text Narrate every lesson in ./course with the same voice. Do a few lessons, send them to me, and wait for my yes before the rest. ``` ```text Make a dialogue from dialogue.txt with gemini_3_1_flash_tts. Speaker A is calm, speaker B is curious. ``` ```text Clean up my own recording, intro.wav, and voice the missing last line in a clone of my voice. I consent to the clone. ``` #### When to use something else For a long audiobook with chapter files and a narrator's review, a dedicated tool such as ElevenLabs Studio fits better, and you can bring its files into invideo. A human voice actor still beats TTS for brand voices and emotional reads. #### Related - [Turn slides into a narrated video, one deck or hundreds](/how-to/training/slides-to-narrated-video) - [Turn a syllabus into a course of lesson videos](/how-to/training/online-course) - [Dub existing footage](/how-to/training/dub-existing-footage) - [Use ElevenLabs with invideo](/integrations/elevenlabs) - [Models](/reference/models) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Turn release notes or a changelog into a video every week Source: https://docs.invideo.io/how-to/training/release-notes-to-video.md Turn this week's release notes or changelog into a short branded video, built from last week's video as the template. Turn release notes into a video: a changelog video, a "what's new" update, a weekly product update for customers or the team. Your agent reads the notes, writes a short script, voices it, and places your screenshots with on-brand text. From the second week on, it copies last week's timeline and swaps only what changed. Use invideo for this when the same video repeats every week, so your brand kit and last week's timeline do most of the work and only the news is new. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make this week's "What's new" video in our invideo project from CHANGELOG.md, the newest section. Copy last week's timeline. Use the brand entry in context/brands. Use the screenshots in ./shots, one per change. Voice a short script. Show me frames before you export. ``` In a chat app, you paste the notes and drag the screenshots in. In a terminal, the agent reads the changelog and the screenshot folder. #### What you need The first week takes setup. Later weeks need only the news. - The release notes: a changelog file, a page you paste, or a list. - One screenshot or short screen recording per change. invideo does not capture pages, so you or your agent's own browser or screenshot tool makes them. - The brand kit, once: colors, fonts as TTF, OTF, WOFF or WOFF2 files, and the logo. - The voice, once. The agent keeps the same `voice_id` every week. #### Steps The first run sets up the brand entry. Every later run starts at the copy step. The agent writes a context entry at `…/context/brands/acme.md` with `write`: colors as hex, the font names, where the logo is. It brings the fonts in with `add_media` on the timeline's URL. It sees the entry's URL, and each font's id in what `add_media` returns. The agent reads the newest release notes and writes one short line per change, with an opening and a closing line. It shows you the script. It sees your yes or your changes. 1. On the first run, the agent runs `find_models` with "narration voice", picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a voice from `elevenlabs_text_to_speech_voices`. Your agent can search for others with `find_models`. On later runs, it runs `read` on last week's thread for the same model and `voice_id`. 2. It calls `generate` with the script as `prompt`, that `voice_id` and `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, like `week-44-voice`. It gets a thread URL and, when the result lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. The agent calls `edit_timeline` with `duplicate_timeline` on last week's timeline, named for this week. The copy shares nothing with the old one. It sees the new timeline's id in what `edit_timeline` returns. The agent brings in the screenshots with `add_media`, then sends one `edit_timeline` call on the copy: `place_media` mode `replace` for each screenshot and the voice, `set_text` and `set_text_style` for the titles, and `trim_clip` to fit the cut. It sees a new `state_token`. The agent calls `capture` on every screenshot and title and `check_timeline`, then `export` with `timeline_id` set to the new timeline. It sees an export card with status `completed`. The terminal version: ```bash invideo context write /context/brands/acme.md \ --markdown @acme-brand.md invideo asset upload ./shots/*.png invideo gen models --query "narration voice" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@this-week.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key week-44-voice \ -i prompt=@this-week.txt -i voice_id= invideo status --wait invideo notebook show invideo edit show --json invideo edit change --timeline T3 --token \ --operations @copy.json invideo edit show --timeline T4 --json invideo edit change --timeline T4 --token \ --operations @swap.json invideo edit capture --timeline T4 --at 2,10,20,40 \ --out ./frames invideo edit check invideo edit export --format video --timeline T4 --quality 1080 \ --json invideo status --wait invideo notebook show --out ./out ``` Where each value comes from: - `` is the project the weekly videos live in. `` is its edit's URL, from `invideo edit new` on the first run. - `` comes from last week's thread, read with `invideo notebook show`. It works only with `elevenlabs_text_to_speech.elevenlabs_tts_v4`. - `` is a notebook page of the project, listed by `invideo notebook show `. `` is the dry run's `.estimated_credits`. - `` is the `url` the paid `gen run` returns. `notebook show` on it lists the voice's sequence URL. - `` comes from `invideo edit show`. The copy makes the old token stale, so the agent reads the edit again before the swap. - `T3` is last week's timeline and `T4` the copy, both from `invideo edit show`. - `` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it. The copy is one op. The swap uses the new timeline's clip ids, read after the copy. Each file is the bare list of ops that `--operations` takes, and the timeline it acts on comes from `--timeline`. The file behind `@copy.json`: ```json [ { "op": "duplicate_timeline", "timeline": "T3", "name": "What's new, week 44" } ] ``` The file behind `@swap.json`. `m21` is the new screenshot's bin id from `invideo asset upload`. `c31` is the old screenshot and `c35` the title, on `T4`, from `invideo edit show`. `` is the font's id in the media bin, from what `add_media` returns. ```json [ { "op": "place_media", "asset": "m21", "track": "V1", "at_f": 150, "source_start_seconds": 0, "source_end_seconds": 5, "mode": "replace", "replace_clip": "c31", "linked_audio": false }, { "op": "set_text", "clip": "c35", "text": "Dark mode is here" }, { "op": "set_text_style", "clip": "c35", "style": { "font": "", "color": "#5b3df5", "font_weight": 700 } } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: the voice each week, and captions if you add them with a transcript. - Free: the brand entry, the copy, every swap, `capture` and `export`. The first video takes under an hour. Later weeks take a few minutes of agent time. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are ids from the wrong timeline. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | The edit changed last week's video | The ops used the old timeline's ids. Read the copy with `get_timeline` and use its ids. | | The export is last week's video | Pass `timeline_id` for the new timeline in `export`. | | The font does not change | `font` takes the font's id from the media bin, not its name. Bring the file in with `add_media` on the timeline's URL. | | `write` refused on the brand entry | Someone changed it since your read. `read` it again and pass the new `revision`, or change one part with `edit`. | | A screenshot is cropped | Fit it with `fit_frame`, or ask for screenshots at the timeline's shape. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` and rebuild. | | Avoid: rebuild the video from scratch each week | Instead: copy last week's timeline with `duplicate_timeline`. | #### Prompts to try Each prompt is a real variation of this job. ```text Make a short vertical version of this week's update for LinkedIn, from the same timeline, with captions. ``` ```text Set up our brand kit in invideo from brand.pdf: colors, fonts and logo. Then make the first weekly update from the notes below. ``` ```text Make this week's update for the internal team only. Add the bug fixes section too. No voice, only text and music. ``` #### When to use something else invideo does not capture web pages or record screens. Use your agent's browser, a screenshot tool, or a screen recorder, then bring the files in. To run this every week without you, a CI job can run the CLI. See [Run invideo in CI and on servers](/how-to/ci-and-servers). #### Related - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [Turn a CSV into many videos with a script](/how-to/developers/csv-to-videos) - [Update one line and re-render, keep the rest](/how-to/training/update-one-line) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Check your video before you say it is done](/how-to/check-your-video) ### Turn a syllabus into a course of lesson videos Source: https://docs.invideo.io/how-to/training/online-course.md Turn a course syllabus into a set of lesson videos that share one look, one voice and one template, made lesson by lesson from a shared plan. Turn a syllabus into a video course: many lesson videos, e-learning modules, a course series with one look. Your agent keeps the syllabus as a brief in the project, builds one lesson as the template, then copies it for each lesson with new titles, new narration and new visuals. Every lesson stays an editable timeline. Use invideo for this when you want every lesson to match, and the plan, the template and every lesson in one project that you and your agent both work from. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a video course in invideo from syllabus.md. Save the syllabus as a brief. Build lesson 1 first as the template and show it to me. After my yes, make the other lessons from it, a few at a time, and mark each one done in the brief. ``` In a chat app, you paste the syllabus and drag in slides or footage. In a terminal, the agent reads the syllabus and the lesson folders. #### What you need The syllabus drives everything. - The syllabus: lesson titles, learning goals, and a script or notes per lesson. - Material per lesson: slides, screen recordings, footage, or permission for stock and text slides. - One voice for the whole course. - The look: brand colors, fonts, an intro and an outro. #### Steps The template lesson is the step to get right. Every later lesson copies it. The agent calls `new_brief` with the course name and a one-line description. Then it adds one note per lesson with `edit`, under headings like `lesson-01`. It sees the brief's URL, which you open in invideo. The agent builds lesson 1 on a branch made with `timeline_history`: an intro, the title with `add_text`, the narration, the visuals, captions and an outro. It voices the narration as the voice step below shows, and saves the model and the `voice_id` in the brief. It sees lesson 1's timeline URL, and sends it to you. You watch lesson 1 in the editor, and the agent makes your changes before it copies anything. It sees your yes. For each lesson, the agent calls `edit_timeline` with `duplicate_timeline`, named for the lesson. Each copy shares nothing with the template. It sees the new timeline's id. 1. The agent runs `find_models` with "course narration voice" once, picks one, and reads its inputs with `get_model`. A good pick is `seed_tts_2_0`, with a voice from `seed_tts_2_0_voices`. Your agent can search for others with `find_models`. Every lesson uses the model and `voice_id` saved in the brief. 2. It calls `generate` with the lesson's script as `prompt`, the `voice_id` and `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key` like `course-voice-02`. It gets a thread URL and, when the result lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. The agent sends one `edit_timeline` call on the copy: `set_text` for the title, `place_media` mode `replace` for the visuals and the new narration, and `trim_clip` to fit the cut. It sees a new `state_token` per lesson. The agent calls `capture` and `check_timeline` on the lesson, then `export` with its `timeline_id` and an `idempotency_key` like `course-lesson-02`. Then it adds the timeline and export URLs to the lesson's note with `edit`. It sees an export card with status `completed`, and the brief shows the lesson as done. Run it in parts: a few lessons per session, and check them before the next batch. A new session reads the brief and goes on from there. The terminal version. `invideo context edit` changes part of the brief: ```bash invideo edit show --json invideo edit change --timeline T1 --token \ --operations @copy-lesson-02.json invideo gen models --query "course narration voice" invideo gen model --model seed_tts_2_0 invideo gen run --model seed_tts_2_0 --dry-run \ -i prompt=@lesson-02.txt -i voice_id= invideo gen run --model seed_tts_2_0 \ --max-credits --idempotency-key course-voice-02 \ -i prompt=@lesson-02.txt -i voice_id= invideo status --wait invideo notebook show invideo edit show --timeline T2 --json invideo edit change --timeline T2 --token \ --operations @fill-lesson-02.json invideo edit capture --timeline T2 --at 2,30,90 \ --out ./frames invideo edit check invideo edit export --format video --quality 1080 \ --timeline T2 --idempotency-key course-lesson-02 --json invideo status --wait invideo notebook show --out ./lessons/lesson-02 invideo context edit --old "Lifting safely. todo." \ --new "Lifting safely. done." ``` Where each value comes from: - `` is the template's branch, the `.branch_url` that `invideo branch new ` returned when lesson 1 was built. - `` is the `state_token` from `invideo edit show `. Each change makes the old token stale, so the agent reads the branch again before the next change. - `T2` is the copy's timeline id, from `invideo edit show` after the copy. - `` is the course voice saved in the brief, a `seed_tts_2_0_voices` id. - `` is the course project, from `invideo project new`. `` is a notebook page of the project, listed by `invideo notebook show `. - `` is the dry run's `.estimated_credits`. `` is the `url` the paid `gen run` returns, and `notebook show` on it lists the voice's sequence URL. - `` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./lessons/lesson-02/export.mp4`, and the agent renames it to `lesson-02`. The `--file-name` export option does not name the saved file. - `` is the brief's URL from `new_brief` or `invideo context new-brief`. The brief, as `read` shows it, part way through. `` and `` are each lesson's timeline URL and export URL, which the agent writes in. ```text # Safety basics course > Short lessons for new warehouse staff. > status: in progress ## lesson-01 Fire exits. done. ## lesson-02 Lifting safely. done. ## lesson-03 Forklift zones. todo. ``` The copy and the fill for one lesson. Each file is the bare list of ops that `--operations` takes. The file behind `@copy-lesson-02.json`: ```json [ { "op": "duplicate_timeline", "timeline": "T1", "name": "Lesson 2: Lifting safely" } ] ``` The file behind `@fill-lesson-02.json`. `c40` is the title clip's id on `T2`, from `invideo edit show --timeline T2`: ```json [ { "op": "set_text", "clip": "c40", "text": "Lesson 2: Lifting safely" } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: the narration per lesson, transcripts for captions, stock clips, and any generated visuals. - Free: the brief, the template, every copy and edit, `capture` and `export`. The template lesson takes under an hour. Each later lesson takes a few minutes of agent time plus the voice. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems come from long runs and the wrong timeline. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `generate` refuses the voice: "voice_ids are model-specific" | The voice comes from another model's library. Use a `seed_tts_2_0_voices` id with `seed_tts_2_0`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | A lesson changed the template | The ops used the template's ids. Read the copy with `get_timeline` and use its ids. | | An export shows the wrong lesson | Pass that lesson's `timeline_id` in `export`. | | A new session starts over | Read the brief first. It lists the lessons that are done. | | `edit` on the brief is refused | `old_text` must be in it once, as `read` shows it. Read it again. | | Two exports for one lesson | Pass an `idempotency_key` per lesson. A retry then finds the first export. | | CLI exit 5 | Credits ran out. Stop the batch, tell the person, and note where you stopped in the brief. | | Avoid: make every lesson before the template is approved | Instead: get a yes on lesson 1 first. | #### Prompts to try Each prompt is a real variation of this job. ```text Add a new lesson to the course from the notes below, from the same template, and add it to the brief. ``` ```text Change the intro in every lesson to the new logo. Start with lesson 1 and show me before you do the rest. ``` ```text Make a short trailer for the course from the best moments of each lesson. ``` #### When to use something else invideo makes the lesson videos. Packaging them as SCORM, quizzes and learner tracking happen in your LMS or an authoring tool such as Articulate Rise or iSpring. Upload the MP4s and caption files there. #### Related - [Turn slides into a narrated video, one deck or hundreds](/how-to/training/slides-to-narrated-video) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Make an SRT captions file for an LMS](/how-to/training/srt-for-an-lms) - [Turn a CSV into many videos with a script](/how-to/developers/csv-to-videos) - [Update one line and re-render, keep the rest](/how-to/training/update-one-line) ### Make closed captions and audio description for ADA Title II and Section 508 Source: https://docs.invideo.io/how-to/training/captions-for-ada-508.md Make closed captions as an SRT or VTT file and an audio description track for a training video, ready for your accessibility review. Make an accessible training video: closed captions, subtitles for deaf and hard of hearing viewers, and audio description for blind and low vision viewers. Your agent makes a captions file your player can turn on and off, and a separate audio description track or a described version of the video. These are the parts that ADA Title II and Section 508 reviews look for. Use invideo for this when you want the captions and the description on the same timeline as the video, so a fix to the cut, the captions or the description stays in step. invideo makes the files. It does not certify that a video meets ADA Title II, Section 508 or WCAG. An accessibility reviewer does that. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make this training video accessible. On a branch: closed captions as lesson.vtt from caption slides I can check, and an audio description track that describes what is on screen in the pauses. Give me the clean video, the VTT, a described version of the video, and the description as its own audio file. ``` In a chat app, the agent gives you the VTT text to save and the export cards. In a terminal, it writes the files into your folder. #### What you need These are the inputs and the choices. - The video, on an invideo timeline or as a file. - Your player or LMS, and what it takes: SRT or VTT, a second audio track, or a second video. - Names and terms the transcript may get wrong. - Who reviews the result for compliance. #### Steps Captions come first, then the description, then the files. The agent prices `audio.transcript` with `dry_run` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. It runs it on the video's sequence URL from `add_media`. It sees every word with its time and speaker. The agent creates a branch with `timeline_history` and adds the captions with `add_captions`, with speaker names and the sounds that matter to deaf viewers, like "[alarm rings]". It sees a caption clip, and you check the words. Closed captions are a sidecar file the viewer turns on, unlike burned-in open captions. The agent reads the slides with `get_timeline` mode `collection`, collection `caption_slide`, and writes the SRT or VTT file itself. It sees a file with one cue per slide. The agent runs `media` `audio.content` for the silence spans, and `capture` at each scene to see what is on screen. It writes short lines that describe what a viewer cannot hear: text on screen, actions, a chart's point. You approve the lines. It sees your yes. 1. The agent runs `find_models` with "narration voice", picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. Your agent can search for others with `find_models`. It finds a voice with `search_library` in `elevenlabs_text_to_speech_voices`. 2. It calls `generate` with `dry_run: true`, each line as `prompt` and the `voice_id`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key` per line. It gets a thread URL and, when the result lands, a sequence URL per line. It reads each URL with `read` and never calls `generate` again to check. The agent copies the timeline with `duplicate_timeline`, adds an audio track named "Audio description" with `add_track`, and places each line in its gap with `insert_media`. The clean timeline stays untouched. It sees the track in `get_timeline`. The agent exports the files your player needs, one `export` each. 1. The clean video: the clean timeline, with the captions off through `set_clip_enabled`. 2. The described version: the described copy. 3. The description alone: `export` with `mode` `audio`, with the other tracks muted through `set_audio_muted`. It sees one export card per file. The terminal version: ```bash invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo edit show --json invideo branch new --name accessible --token invideo edit show --json invideo edit change --timeline T1 --token \ --operations @captions.json invideo edit show --mode collection \ --collection caption_slide --json > slides.json invideo media audio.content invideo gen models --query "narration voice" invideo library search \ --library elevenlabs_text_to_speech_voices --query "clear narrator" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt="A worker lifts the red lever." -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ --max-credits --idempotency-key ad-line-01 \ -i prompt="A worker lifts the red lever." -i voice_id= invideo status --wait invideo notebook show invideo edit show --json invideo edit change --timeline T1 --token \ --operations @track.json invideo edit show --json invideo edit change --timeline T1 --token \ --operations @lines.json invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./described invideo edit export --format video --mode audio \ --audio-format wav --json invideo status --wait invideo notebook show --out ./ad-track ``` Where each value comes from: - `` is the video's `url` from `invideo asset upload`, a `…/notebook/seq-N.M` URL. - `` is the `url` the paid `gen run` returns. `notebook show` on it lists the line's sequence URL. - `` is each dry run's `.estimated_credits`. - `` is the video's timeline URL, from `invideo edit new` or the editor. `` is its project. - `` is the `branch_url` that `invideo branch new` returns. - `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read again before each change. - `` comes from the `elevenlabs_text_to_speech_voices` search. It works only with `elevenlabs_text_to_speech.elevenlabs_tts_v4`. - `` is a notebook page of the project, listed by `invideo notebook show `. - `@captions.json`, `@track.json` and `@lines.json` each read a bare JSON list of ops, like the two lists below. - `` and `` are `.sequences[0]` of each export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves each file in its folder, and the agent renames them, for example to `lesson-described`. The `--file-name` export option does not name the saved file. The file behind `@track.json` adds the description track and turns off the burned-in captions. `c22` is the caption clip's id from `invideo edit show`. ```json [ { "op": "add_track", "kind": "audio", "name": "Audio description" }, { "op": "set_clip_enabled", "clip": "c22", "enabled": false } ] ``` The file behind `@lines.json` places the first line, in the next call. `A4` is the new track's id from `invideo edit show`. The `asset` is the voice line's sequence URL, from `invideo notebook show` on the paid `gen run` thread. ```json [ { "op": "insert_media", "asset": "", "track": "A4", "at_f": 615, "ripple": false } ] ``` A VTT file the agent writes: ```text WEBVTT 00:00:00.000 --> 00:00:02.500 [upbeat music] 00:00:02.800 --> 00:00:05.500 TRAINER: Welcome to the safety course. ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Costs credits: the transcript and the voice for each description line. - Free: the captions, the files, every edit and each export. - `audio.content`: the dry run shows its price before anything starts. A short video takes under an hour, plus your review. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems are files the player does not take. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the video's sequence URL from `add_media` or `invideo asset upload`. | | `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show --out `. | | A caption word is wrong | The agent fixes the slide with `set_caption_slide_text`. | | A description line does not fit its gap | On the described copy, open time with `edit_time_range` mode `insert`, and fill the picture with a still from `media` `video.extractFrameAtTime` on the video's sequence URL. | | The player shows no captions | It needs the sidecar file. Upload the SRT or VTT in the player's caption settings. | | Captions show twice | The video has burned-in captions and the file is on. Export with the caption clip off, using `set_clip_enabled`. | | The audio file has the whole mix | Mute every other track with `set_audio_muted` before `export` with `mode` `audio`. | | The VTT is missing the end | The read was paged. Continue with `next_offset` and the same `snapshot`. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` and rebuild. | | Avoid: say the video is compliant | Instead: say the files are ready for the accessibility review. | #### Prompts to try Each prompt is a real variation of this job. ```text Make SRT captions for every lesson in this project, with speaker names and sound tags, for our accessibility review. ``` ```text Write an audio description script for this video and show it to me. Do not voice it until I approve it. ``` ```text Make a described version of this video where the video pauses for each description, and keep the normal version too. ``` #### When to use something else Compliance review is outside invideo. An accessibility reviewer or your organization's accessibility office checks the video against WCAG, the Web Content Accessibility Guidelines, which the ADA Title II rule and Section 508 both point to. They confirm which WCAG version and level applies to you. The criteria to ask about are Captions (Prerecorded) and Audio Description (Prerecorded). For SCC broadcast captions, convert the SRT with a captioning tool such as Subtitle Edit. #### Related - [Make an SRT captions file for an LMS](/how-to/training/srt-for-an-lms) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Check your video before you say it is done](/how-to/check-your-video) - [Timeline edit operations](/reference/edit-operations) ## Film ### Make an AI short film with a character that stays the same Source: https://docs.invideo.io/how-to/film/short-film-consistent-character.md A short film made with AI video models where your character keeps the same face, hair and clothes in every shot, cut on a timeline you can edit. You get an AI short film, also called an AI film or a generated short, where the main character looks the same in every shot. Same face, same hair, same jacket. The shots come from reference-to-video models, and your agent cuts them on an invideo timeline with sound, titles and credits. Use invideo for this when you want the character, the shot list and the cut in one project: the agent keeps the character in the project's context, generates each shot from the same references, and the film stays editable after the cut. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a short film about Maya, a night-shift nurse who finds a lost dog. Use the photos in ./maya as her reference. Write a shot list as a brief, generate each shot with Maya from the same references, and check that she looks the same in every shot. Put each act on its own branch. Tell me the price before you generate anything. ``` In a chat app, you drag the reference photos into the project, then name them in the chat. In a terminal, you name the folder and the agent uploads it. #### What you need The references matter most. A character drifts when the model has to guess. - **Reference images of the character.** A front view, a side view and a full-body view, in even light. A character sheet on one image also works. - **The story.** A few lines per act, or a full script. - **The look.** Era, place, light and lens words, like "rainy city at night, 35mm, warm street light". - **The shape.** 16:9 or 21:9 for a film, 9:16 for a vertical short. - **The credits.** Your name, everyone who worked on it, and anything else you want on the end card. #### Steps The agent works on a branch per act and tells you what changed at each step. The agent makes a project with `new_project` and adds each photo with `add_media`. For local files, it calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id`. Expected result: a sequence URL for each photo. The agent writes the character to `context/world/maya.md` with `write`: her face, hair, clothes and voice, with a link to each reference photo by its sequence URL. Then it makes a brief with `new_brief` and adds a `shot-list` note with `edit`, where each shot has a number, the act, the framing, the action and the prompt. Expected result: the entry in `read` on the project, and a brief URL. You change the shot list before any generation starts. The agent follows the generation pattern for every shot, with the same reference photos each time. 1. It runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `seedance_2_5.r2v`. Your agent can search for others with `find_models`, such as `veo_31.ingredients`, `wan_30_video.wan_30_reference` and `minimax_h3_max.reference`. 2. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, then reads the sequence URL with `read` when the result lands. It never calls `generate` again to check. Expected result: a thread URL, then a sequence URL per shot with status `completed`. For a shot that must start and end on exact frames, like a door opening into the next scene, the agent makes the frames first, then the shot. 1. It runs `find_models` for an image from references, and `find_models` for video from a first and last frame. Good picks are `nanobanana_pro` for the frames and `seedance_2_5.frames` for the shot. Your agent can search for others with `find_models`. It reads each pick's inputs with `get_model`. 2. It calls `generate` for the two frames from the same references, then for the shot, each with `dry_run: true` first, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it runs each paid call with `max_credits` set to that price and an `idempotency_key`, and reads each sequence URL with `read`. Expected result: a shot that starts and ends where you asked. The agent runs `media` with `video.frames` on each shot, then compares the face, hair and clothes by eye with the reference photos. Expected result: a list of shots that pass and shots that drift. You approve the takes you like, and the agent marks them with `mark_sequence`. The agent makes a timeline with `new_timeline` and creates a branch per act with `timeline_history` action `create_branch`. It places the approved takes with `insert_media`, adds music and sound, and ends with a credits card made with `add_text` that names the models used. Expected result: a branch URL per act, and a new `state_token` after each edit. The agent runs `capture` across each act and `check_timeline`, and looks at the character in every captured frame. Then it runs `export` with `format` video. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo project new --title "Night Shift" invideo asset upload ./maya/*.jpg invideo context write /context/world/maya.md --markdown @maya.md invideo context new-brief --name "Night Shift" \ --description "A short film in acts" invideo gen models --query "video from reference images" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ --input shot-01.json invideo gen run --model seedance_2_5.r2v --max-credits \ --idempotency-key shot-01 --input shot-01.json invideo status --wait invideo notebook show invideo media video.frames --at 0,2,4 --out ./check invideo edit new --name "Night Shift cut" --fps 24 invideo branch new --name act-1 --token invideo edit show invideo edit change --timeline T1 --token \ --operations @act-1.json invideo edit capture --at 0,12,24,36 --out ./frames invideo edit export --format video --quality 1080 ``` Where the values come from: `` from `invideo project new`, and `` from `invideo notebook show `. `` is the price the dry run returns, its `estimated_credits`, and `` is the `url` the paid run returns. `` is the shot's sequence URL, which `invideo notebook show ` lists when the job is `completed`. `` comes from `invideo edit new`. `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read fresh, because the main token is stale on the branch. `` is the `branch_url` that `branch new` returns. The file in `--operations @act-1.json` is a bare list of ops. The file in `--input shot-01.json` is the bare inputs object, keyed by the names `get_model` lists, without the model id. The dry run and the paid run send the same file. ``, `` and `` are the sequence URLs `invideo asset upload` returns for the photos. ```json { "prompt": "Maya, in blue scrubs, kneels by a wet dog. Rain, 35mm.", "reference_images": [ "", "", "" ], "aspect_ratio": "21:9", "duration": "6" } ``` The key MCP call prices one shot from the character's references. This fence is the full MCP `generate` call. On the MCP path the inputs sit under `inputs`. The agent sends the call again without `dry_run`, with `max_credits` set to that price. ```json { "url": "", "model": "seedance_2_5.r2v", "inputs": { "prompt": "Maya, in blue scrubs, kneels by a wet dog. Rain, 35mm.", "reference_images": [ "", "", "" ], "aspect_ratio": "21:9", "duration": "6" }, "dry_run": true, "idempotency_key": "night-shift-shot-07" } ``` The credits card goes in one `edit_timeline` call. This fence is the bare list of ops that `--operations @act-1.json` takes. `start_f` and `end_f` are frames at the timeline's frame rate, after the last shot. ```json [ { "op": "add_text", "track": "V3", "start_f": 2880, "end_f": 3000, "text": "Directed by Ana Ruiz\nShots: Seedance 2.5, Kling 4.0" } ] ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** every shot from `seedance_2_5.r2v`, `seedance_2_5.frames` or another video model, the frame images from `nanobanana_pro`, and any music or sound you generate. Shots made again because the character drifted cost again. - **Free:** the character entry, the brief, the cut, the credits card, `capture` and every export. `video.frames` shows its price in the dry run before anything starts. Each shot takes a few minutes to generate. A short film with retakes takes an afternoon or more. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from thin references or a prompt that changes the character's look. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | The face changes from shot to shot | Pass the same reference photos in every shot, and describe the character the same way in every prompt. Generate the drifting shot again. | | The clothes change | Name the clothes in the character entry and in the prompt. Add a full-body reference photo. | | The character drifts in a frames shot | `seedance_2_5.frames` takes no reference images. Make the first and last frames from the references with `nanobanana_pro` instead. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | Status `needs_confirmation` | Only you can confirm it, in invideo. The agent tells you where. | | CLI exit 5 | A limit on credits or quota. Check the balance before the next shot. | | A call times out | Retry with the same `idempotency_key`. It finds the first generation. | | Avoid: calling `generate` again to check a shot | Instead: `read` the thread URL or call `status`. | | Avoid: editing main | Instead: one branch per act from `timeline_history`. You pick what goes to main. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a character sheet for Kai from these photos with nanobanana_pro, save Kai to the project's world, then generate a few shots of Kai walking through a market. Show me frames of each shot next to the sheet. ``` ```text Shot 4 drifts: her hair is shorter. Generate it again with the same references and a prompt that names her long braid. Keep the old take. ``` ```text Cut act 2 on its own branch. End it on a short hold of the dog, then a credits card with everyone who worked on it and the models you used. ``` #### When to use something else invideo does not train a custom model on your character. For a character model trained on many photos, use a training tool such as a LoRA trainer, then bring the shots into invideo for the cut. Platforms such as YouTube, TikTok and Meta ask you to label realistic AI content when you upload. The credits card names the models, but the label itself is a setting in each platform's upload screen. #### Related - [Generate a missing shot or extend a clip inside your edit](/how-to/film/generate-a-missing-shot) - [Make storyboards and previs before the shoot](/how-to/film/storyboards-and-previs) - [Use Claude Code as your film editor on an invideo timeline](/how-to/film/claude-code-as-film-editor) - [Check your video before you say it is done](/how-to/check-your-video) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Get started with AI filmmaking](/guides/get-started-with-ai-filmmaking) ### Color grade log footage and match shots Source: https://docs.invideo.io/how-to/film/color-grade-log-footage.md Your log footage converted to normal color, graded with a LUT and color controls, and matched shot to shot on a timeline you can keep changing. You get log footage turned into normal-looking video, also called color correction and color grading. Your agent tells invideo which camera profile the clips were shot in, applies your LUT, sets exposure, white balance and curves per clip, and matches the shots so a scene looks like one place and one time. Use invideo for this when you want the grade on the same timeline as the cut: every grade stays editable, your agent can change one control on many clips in one call, and you see each change live in the browser. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text These clips in ./scene-12 are Sony S-Log3, S-Gamut3.Cine. Set the color profile, apply my LUT ./looks/teal-warm.cube at a light strength, then match every shot to the wide shot. Show me frames side by side before and after. Work on a branch. ``` In a chat app, you drag the clips and the .cube file into the project. In a terminal, you name the folders and the agent uploads them. #### What you need Tell the agent the camera and its log profile. A wrong profile makes every later step wrong. - **The footage.** The original camera files, in log. - **The camera and profile.** For example Sony S-Log3 with S-Gamut3.Cine, or Panasonic V-Log. - **A LUT, if you have one.** A .cube or PNG file: the camera maker's conversion LUT, or a creative look. - **The hero shot.** The shot the others should match, usually the wide. - **The look in words.** "Warm skin, cool shadows, low contrast" is enough. - **The delivery.** SDR for the web, or HDR for a platform that takes it. #### Steps The agent grades on a branch and shows you frames after each step. The agent sets up in three calls. 1. It makes a timeline with `new_timeline`. 2. It creates a branch with `timeline_history` and `action: "create_branch"`. 3. It adds the clips and the .cube file with `add_media` on the branch URL. Expected result: a media bin id for each clip and for the LUT. The agent sends `set_media_color_profile` for each log file in the bin, with the `profile` that matches the camera, like `slog3_sgamut3cine` or `vlog_vgamut`. Then it sets the timeline to `rec709` with `set_timeline_working_space`, or to `rec2020` for an HDR grade. Expected result: clips that look normal, not flat and gray. The agent places the clips, then sends `apply_lut` on each clip with the LUT's bin id and a `strength` between 0 and 1. Expected result: a new `state_token`, and the look on every clip. The agent adds a grade with `edit_grade` kind `add` where a clip needs its own fix. In a second call, with the grade id from `get_timeline`, it sets `exposure`, `temperature`, `tint`, `contrast` and `saturation` with `set_grade_parameter`, and shapes the contrast with `set_grade_curve` on the `master` curve. For a face in shadow or a hot sky, it adds a mask with `edit_grade_mask` and a `circle`, `rectangle` or `gradient` shape. In a second call, with the mask id from `get_timeline`, it places the mask with `set_grade_mask_parameter` (`center`, `size`, `feather`). Expected result: each shot correct on its own, and any mask changes the grade only inside it. The agent runs `capture` at a time in the hero shot and a time in each other shot, and compares them side by side by eye. It looks at skin, a white or gray object, and the shadows. It nudges `temperature`, `tint` and `exposure` on the shot that is off, and captures again. Expected result: shots that cut together without a jump in color. For one look over the whole scene, the agent adds an adjustment clip with `add_adjustment` above the top video track, then adds a grade on it with `edit_grade`. A change to that grade changes every shot below it. Expected result: one place to change the look of the scene. The agent runs `check_timeline` and `capture` at every cut, and looks for clipped highlights and crushed blacks. Then it runs `export` with `format` video. Expected result: an export card with status `completed`, a 1080p MP4. The same job from a terminal: ```bash invideo edit new --name "Scene 12 grade" --fps 24 invideo asset upload ./scene-12/*.mp4 ./looks/teal-warm.cube invideo edit show --json invideo branch new --name grade-v1 --token invideo edit show --json invideo edit catalog --ops set_media_color_profile,apply_lut invideo edit change --timeline T1 --token \ --operations @grade.json invideo edit capture --at 2,9,15,22 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read fresh after each change, because the main token is stale on the branch. `` is the `branch_url` that `branch new` returns. The file in `--operations @grade.json` is a bare list of ops, like the `operations` list below. The key MCP calls set the profile, the working space and the LUT, then one correction. Each fence is a full MCP `edit_timeline` call. The ids `m1`, `m9` and `c3` come from `get_timeline`, and so does `` on the MCP path. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "set_media_color_profile", "asset": "m1", "profile": "slog3_sgamut3cine" }, { "op": "set_timeline_working_space", "timeline": "T1", "working_space": "rec709" }, { "op": "apply_lut", "clip": "c3", "lut": "m9", "strength": 0.7 } ] } ``` The agent reads the grade id, ``, and a fresh token with `get_timeline` after `apply_lut` makes the grade, then sends the corrections in the next call. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "set_grade_parameter", "clip": "c3", "grade": "", "parameter": "temperature", "value": 0.1 }, { "op": "set_grade_curve", "clip": "c3", "grade": "", "which": "master", "points": [[0, 0.04], [0.25, 0.22], [0.75, 0.8], [1, 0.97]] } ] } ``` ##### HDR delivery `export` makes a 1080p SDR MP4. For an HDR file, the agent grades in `rec2020`, exports at 1080p, then runs the export through an HDR model with `generate`: `topaz_hyperion_2_5_sdr_hdr` gives HDR10, HLG or ProRes, and `ltx_video_hdr_upscale` gives ProRes, HLG or DNxHR. Both take the export card's URL as their `video` input, with no download. They charge per second of the source video. The agent follows the generation pattern. 1. It runs `find_models` with the job in words, picks one, and reads its `output_format` and `resolution` choices with `get_model`. A good pick is `topaz_hyperion_2_5_sdr_hdr`. Your agent can search for others with `find_models`. 2. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It gets a thread URL and, when the result lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. ```bash invideo gen models --query "SDR to HDR conversion" invideo gen model --model topaz_hyperion_2_5_sdr_hdr invideo gen run --model topaz_hyperion_2_5_sdr_hdr --dry-run \ -i video= -i output_format=hdr10_hevc_mp4 invideo gen run --model topaz_hyperion_2_5_sdr_hdr \ --max-credits --idempotency-key scene12-hdr \ -i video= -i output_format=hdr10_hevc_mp4 ``` Where the values come from: `` from `invideo project new`. `` is `.sequences[0]` of the export answer. `` comes from `invideo notebook show `. `` is the price the dry run returns, its `estimated_credits`. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the color profile, the LUT, every grade, mask and curve, `capture`, and the export. - **Costs credits:** only the HDR conversion with `topaz_hyperion_2_5_sdr_hdr` or `ltx_video_hdr_upscale`, priced per second of video. A scene grade takes the agent a few minutes. Matching shots with you takes longer, because you judge the frames. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from the wrong profile or a LUT stacked on a grade. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | The footage looks flat and gray | The color profile is not set. Send `set_media_color_profile` with the camera's profile. | | The footage looks too dark and too saturated | The LUT converts log, and the profile also converts it. Use one of them, not both. | | The camera's profile is not in the `set_media_color_profile` list | Skip the profile. Use the camera maker's conversion LUT with `apply_lut` instead. | | `apply_lut` is refused | The clip has more than one grade. Remove one with `edit_grade` kind `remove`, then apply the LUT. | | The LUT is too strong | Lower `strength` on `apply_lut`, or `lut_strength` with `set_grade_parameter`. | | A mask is in the wrong place | Move it with `set_grade_mask_parameter` and `center`, then `capture` again. | | `edit_timeline` refused with an old token | Someone edited first. Read with `get_timeline`, then rebuild the ops. | | CLI exit 3 | The edit changed since your read. Run `invideo edit show` and rebuild. | | Avoid: matching shots by numbers alone | Instead: `capture` both shots and compare them by eye. Skin and neutrals tell you more than a value. | | Avoid: grading main | Instead: grade on a branch, so you can compare looks. | #### Prompts to try Each prompt is a real variation of the job. ```text These are Panasonic V-Log clips. Set the profile, then give me a warm, soft look and a cool, high-contrast look, each on its own branch. ``` ```text The close-up at 00:42 is warmer than the wide at 00:30. Match it to the wide and show me both frames before and after. ``` ```text Darken the sky in every exterior shot with a gradient mask, keep the faces as they are, and add a light vignette over the whole film. ``` #### When to use something else Your agent sees captured frames, not scopes like a waveform or a vectorscope, so it matches by eye. For a grade that must hit exact broadcast levels, finish in DaVinci Resolve: export with `format` set to `davinci` and grade there. `set_media_color_profile` covers the profiles in its list. For other log profiles, like ARRI LogC or Canon Log, use the camera maker's conversion LUT with `apply_lut`. #### Related - [How should I choose a LUT for my footage?](/guides/how-should-i-choose-a-lut-for-my-footage-in-invideo-editor) - [What to adjust when a LUT looks too strong](/guides/what-should-i-adjust-when-a-lut-makes-my-shot-look-too-strong) - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) - [Generate a missing shot or extend a clip inside your edit](/how-to/film/generate-a-missing-shot) - [Check your video before you say it is done](/how-to/check-your-video) ### Generate a missing shot or extend a clip inside your edit Source: https://docs.invideo.io/how-to/film/generate-a-missing-shot.md Fill a gap in your cut with a generated shot that starts and ends on your own frames, or extend a clip that ends too early, then match it to the scene. You get a new shot in the gap where your edit needs one, also called a pickup shot, an insert or a bridge shot. Or you get a clip that runs longer than the camera rolled. Your agent takes the last frame of the shot before the gap and the first frame of the shot after, generates the shot between them, places it on the timeline, and matches its color and size to the scene. Use invideo for this when the gap is inside a cut you are still editing: the agent reads your timeline, makes the shot from your own frames, and drops it in place, and you can move or trim it like any other clip. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it the timeline URL and this prompt. ```text There is a gap at 01:12 on this timeline. Generate a shot that starts on the last frame before the gap and ends on the first frame after it: she walks from the door to the window. Run a dry run first and tell me the price. Match the grade to the shots around it. Work on a branch. ``` In a chat app, you paste the timeline URL into the chat. In a terminal, you paste it into the prompt, and the agent saves the frames it checks to a folder. #### What you need The frames around the gap do most of the work. Describe only what happens between them. - **The timeline URL.** And the time of the gap, or the clip that ends too early. - **What happens in the shot.** The action, the camera move, the length. - **The look of the scene.** The LUT or grade the shots around it use. - **Sound.** Say if the shot needs its own sound, or if the scene's sound runs under it. #### Steps The agent works on a branch and shows you frames before and after. The agent creates a branch with `timeline_history`, then reads the timeline with `get_timeline` mode `window` around the gap. It notes the clip before, the clip after, the gap's length in frames, and the timeline's frame rate. Expected result: the two clip ids and the gap's start and end frames. The agent runs `media` with `video.extractFrameLast` on the clip before the gap and `video.extractFrameFirst` on the clip after it. Both take the source file's sequence URL from `add_media` or `invideo asset upload`, and work on the whole source file. Expected result: two image sequences, one per frame. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `seedance_2_5.frames`, which takes a first frame and a last frame. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no errors in the inputs. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL and, when the result lands, a sequence URL. The agent reads that URL with `read` and never calls `generate` again to check. The agent first compares the shot's length, from `metadata`, with the gap's length. If the shot is as long as the gap or shorter, it sends `insert_media` with the new sequence URL, the track, the gap's start frame and `ripple` false. If the shot is longer, it sends `place_media` with `source_start_seconds` and `source_end_seconds` that fit the gap. Expected result: the gap is filled, the next clip starts on its old frame, and a new `state_token`. The agent runs `media` with `metadata` on the new shot and on its neighbors. Then it applies the scene's LUT with `apply_lut`, or adds a grade with `edit_grade` and sets it with `set_grade_parameter`. Expected result: the same size and a close match in color. The agent runs `capture` a few frames before the gap, inside it, and a few frames after, and compares the three by eye. It runs `check_timeline`. Then it runs `export`. Expected result: no jump at either cut, and an export card with status `completed`. ##### Extend a clip or make a new angle The same pattern covers two other jobs. Only the model and its inputs change. - **A clip that ends too early.** A good pick is `seedance_2_5.extend`, with the clip as its `extend_video`. `flux_3.start_video` also continues a video. - **A new angle of the same scene.** A good pick is `seedance_2_5.r2v`, with frames from the scene as reference images. The agent reads each model's inputs with `get_model`, and prices each run with `dry_run: true` before the paid call. The same job from a terminal: ```bash invideo edit show --mode window --start-seconds 68 \ --end-seconds 78 invideo branch new --name pickup-shot --token invideo edit show invideo media video.extractFrameLast invideo media video.extractFrameFirst invideo gen models --query "video from first and last frame" invideo gen model --model seedance_2_5.frames invideo gen run --model seedance_2_5.frames --dry-run \ --input shot.json invideo gen run --model seedance_2_5.frames \ --max-credits --idempotency-key pickup-0112 --input shot.json invideo status --wait invideo notebook show invideo edit change --timeline T1 --token \ --operations @place.json invideo edit capture --at 71,72.5,74 --out ./frames invideo edit check invideo edit export --format video --quality 1080 --json ``` Where the values come from: `` from `invideo edit new`. `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read fresh, because the main token is stale on the branch. `` is the `branch_url` that `branch new` returns. `` and `` are the `url` values that `invideo asset upload` returned for the two clips. `` comes from `invideo project new`, and `` from `invideo notebook show `. `` is the price the dry run returns, its `estimated_credits`, and `` is the `url` the paid run returns. The file in `--input shot.json` is the bare inputs object, keyed by the names `get_model` lists, without the model id. The dry run and the paid run send the same file, so the run you priced is the run you pay for. `` and `` are the sequence URLs that the two frame pulls return. ```json { "prompt": "She walks from the door to the window", "first_frame": "", "last_frame": "" } ``` The file in `--operations @place.json` is a bare list of ops. The shot is longer than the gap here, so the ops use `place_media` with a source range. `at_f` is the gap's start frame, and the source range is as long as the gap. ```json [ { "op": "place_media", "asset": "", "track": "V1", "at_f": 1728, "source_start_seconds": 0, "source_end_seconds": 2.5, "mode": "overwrite" } ] ``` `` is the sequence URL of the generated shot, which `invideo notebook show ` lists when the job is `completed`. On the MCP path, the agent sends the same list as `operations` in `edit_timeline`, with the branch's URL as `url`, `timeline_id` `T1` and the branch's `expected_state_token` from `get_timeline`. The agent then reads the new clip's id with `get_timeline` and sends `apply_lut` on it in a second call. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** the shot from `seedance_2_5.frames`, `seedance_2_5.extend`, `flux_3.start_video` or `seedance_2_5.r2v`, and an upscale with `video.upscale`, priced per second of video. - **Free:** the placing, the grade, `capture` and the export. The frame pulls and `metadata` show their price in the dry run before anything starts. A shot takes a few minutes to generate. Matching it to the scene takes the agent a few minutes more. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from the wrong frames or a shot that does not fit the gap. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | The shot starts on a different frame | The clip is trimmed. Check its trim with `inspect_objects`, then pull the frame with `video.extractFrameAtTime` and `time_seconds` at the trimmed edge. | | The next clip lost its first frames | The shot was longer than the gap, and `insert_media` covered the next clip. Restore the branch's checkpoint with `timeline_history`, then use `place_media` with a source range that fits the gap. | | `insert_media` is refused | The span is not free. Read the timeline again with `get_timeline`, then use `place_media` with a source range that fits. | | A frame pull is refused as `not_found` | The op got a bin id like `m4`. Pass the source file's sequence URL instead. | | The new shot looks softer than its neighbors | Compare with `metadata`, then run `video.upscale` with `dry_run` first. | | The colors jump at the cut | Apply the same LUT with `apply_lut`, then adjust `temperature` and `exposure` with `set_grade_parameter`. | | The generated sound clashes with the scene | Generate with the model's audio switched off, or mute the clip with `set_audio_muted`. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | CLI exit 5 | A limit on credits or quota. Check the balance. | | A call times out | Retry with the same `idempotency_key`. It finds the first generation. | | Avoid: generating without a dry run | Instead: run `dry_run` first and tell the person the price. | | Avoid: calling `generate` again to check on a shot | Instead: `read` the thread URL or call `status`. | #### Prompts to try Each prompt is a real variation of the job. ```text The shot at 00:48 ends too early. Extend it with seedance_2_5.extend, keep the same camera move, and trim it to fit. ``` ```text I need a close-up of the letter on the table between 02:10 and 02:13. Use frames from the wide shot as references and match the grade. ``` ```text Give me a slow push and a locked-off take of the bridge shot at 01:12, each on its own branch. Show me frames of both. ``` #### When to use something else A generated shot is a new picture, not a recording. For a shot that must show a real place, a real product or a real person exactly, shoot a pickup with a camera and bring it in with `add_media`. For frame-accurate VFX work, like a matte painting or rotoscoping, use a compositing tool such as Nuke or After Effects, then bring the render into the gap. #### Related - [Make an AI short film with a character that stays the same](/how-to/film/short-film-consistent-character) - [Color grade log footage and match shots](/how-to/film/color-grade-log-footage) - [When to use a video effect instead of generating a new shot](/guides/when-should-i-use-a-video-effect-instead-of-generating-a-new-shot) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Check your video before you say it is done](/how-to/check-your-video) ### Make a music video with lip sync and beat sync Source: https://docs.invideo.io/how-to/film/music-video-lip-sync.md A music video cut on the beat of your song, with speed ramps on the drops and the singer's lips synced to the vocal, on a timeline you can keep editing. You get a music video cut to your song, with cuts on the beat, also called beat sync, and the singer's mouth matched to the vocal, also called lip sync. Your agent reads the song's tempo, beats and sections, cuts your performance and b-roll shots on them, ramps the speed into the drops, and re-syncs the lips on performance shots that drift. Use invideo for this when you want the beat map and the cut in one place: the agent reads the beats, places every cut on a frame you can move later, and runs lip sync only on the shots that need it. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a music video for ./song.wav from the clips in ./shots. Cut on the beat in the verses and on alternate beats in the chorus. Ramp the speed into the drop. Lip-sync the performance shots to the vocal. Price the lip sync first. Work on a branch. ``` In a chat app, you drag the song and the clips into the project. In a terminal, you name the folders and the agent uploads them. #### What you need A clean song file gives the best beat map. Performance shots work best when the singer faces the camera. - **The song.** The final master, as WAV or MP3. - **Performance shots.** The singer miming or singing the track. Name the section each one covers. - **B-roll.** Shots for the verses and the breaks. - **The vocal, if you have it.** A vocal stem makes lip sync more exact. Without one, the agent splits it from the song. - **The shape.** 16:9 for YouTube, 9:16 for Reels and TikTok. #### Steps The agent works on a branch and tells you the timecodes of each section. The agent sets up in three calls. 1. It makes a timeline with `new_timeline`. 2. It creates a branch with `timeline_history` and `action: "create_branch"`. 3. It adds the files with `add_media` on the branch URL. Expected result: a sequence URL and a media bin id for the song and each shot. The agent runs `media` with `audio.sections` for verse, chorus and bridge, `audio.markers` for the tempo, phrases and drops, and `audio.beats` for strong and weak beats. It turns each time into a frame: seconds times the frame rate. Then it places the song on the music track `A2` with `insert_media`, and adds a marker per section with `add_marker`, named "Verse 1", "Chorus 1" and so on. Expected result: section markers you can see on the timeline. The agent places each shot with `place_media`, starting on a beat frame, and cuts with `split_clip` and `trim_clip` so each cut lands on a beat. It sends all the cuts in one `edit_timeline` call. Expected result: a new `state_token`, and cuts that land on the beat. The agent sends `retime` kind `ramp` on the shot before a drop, with `start_speed`, `end_speed` and the frame range. For a hit, it uses kind `freeze` to hold one frame. Expected result: the shot speeds up or holds where you asked. The shot's own sound is silent while its speed changes, so the song carries the sound. The agent works through each performance shot in four calls. 1. It cuts the song to the shot's length with `media` `audio.trim` on the song's sequence URL, or splits the vocal first with `audio.separate`. Each runs with `dry_run: true` first, and the agent tells you the price. For a price of 1 credit or more it waits for your yes. Then it runs it with `max_credits` set to that price and an `idempotency_key`. 2. It runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `sync_lipsync_v3.video`. Your agent can search for others with `find_models`. 3. It calls `generate` with the shot as `video`, the audio slice as `audio` and `dry_run: true`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. When the result lands, it reads the sequence URL with `read`, and never calls `generate` again to check. 4. It swaps the synced take in with `place_media` mode `replace`. Expected result: a synced take in the same place on the timeline. The agent runs `media` with `video.frames` on each synced take at a few sung words, and `capture` on the timeline at the same moments. It checks that the mouth is open on the open vowels. It runs `check_timeline`, then `export`. Expected result: an export card with status `completed`, and a list of any shot where the lips drift. The same job from a terminal: ```bash invideo edit new --name "Music video" --fps 24 invideo asset upload ./song.wav ./shots/*.mp4 invideo edit show invideo branch new --name cut-v1 --token invideo edit show invideo media audio.sections --asset m1 invideo media audio.markers --asset m1 invideo media audio.beats --asset m1 invideo edit change --timeline T1 --token \ --operations @beat-cuts.json invideo media audio.trim --start-time 42.5 \ --end-time 50.5 --dry-run invideo media audio.trim --start-time 42.5 \ --end-time 50.5 --max-credits --idempotency-key slice-chorus-1 invideo gen models --query "lip sync a video to audio" invideo gen model --model sync_lipsync_v3.video invideo gen run --model sync_lipsync_v3.video --dry-run \ -i video= -i audio= -i sync_mode=cut_off invideo gen run --model sync_lipsync_v3.video \ --max-credits --idempotency-key sync-chorus-1 \ -i video= -i audio= -i sync_mode=cut_off invideo status --wait invideo notebook show invideo edit capture --at 43,45,47,49 --out ./frames invideo edit export --format video --quality 1080 ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read fresh, because the main token is stale on the branch. `` is the `branch_url` that `branch new` returns. `m1` is the song's bin id, which the reads that return at once take with `--asset`. `` and `` are the `url` values `invideo asset upload` returns. `` is the sequence URL `audio.trim` returns. `` comes from `invideo notebook show `. `` is the price each dry run returns, `credits` on a `media` op or `estimated_credits` on `gen run`. `` is the `url` of the paid `gen run`. The file in `--operations @beat-cuts.json` is a bare list of ops, like the `operations` list below. The key MCP call cuts on two beats and ramps into the drop. This fence is the full MCP `edit_timeline` call. Each `at_f` is a beat time in seconds times the frame rate. The later cut goes first, because the right half of a split is a new clip. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "split_clip", "clip": "c4", "at_f": 264 }, { "op": "split_clip", "clip": "c4", "at_f": 252 }, { "op": "retime", "clip": "c6", "kind": "ramp", "from_f": 1008, "to_f": 1056, "start_speed": 1, "end_speed": 3, "shape": "ease_in" } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Free:** the cuts, the speed ramps, `capture` and the export. `audio.sections`, `audio.markers`, `audio.beats` and `audio.trim` show their price in the dry run before anything starts. - **Costs credits:** each lip sync with `sync_lipsync_v3.video` or `kling_lipsync`, and a vocal split with `audio.separate`. The beat map and the cut take the agent a few minutes. Each lip sync takes a few minutes more. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Generated lip sync can drift on fast lyrics, on profile shots, and when the face is small in the frame. Check every synced take. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | The cuts feel a little late | Move them a frame or two earlier with `trim_clip`. People hear the beat before they see the cut. | | The beats land between frames | Round each beat to the nearest frame. | | The lips drift late in a shot | Lip-sync a shorter slice, or split the shot with `split_clip` and sync each part. | | The lips do not move on a profile shot | Lip sync needs a visible mouth. Use a front-facing shot, or keep the profile shot on b-roll. | | The synced take is a different length | Set `sync_mode` on `sync_lipsync_v3.video` to `cut_off`, so the output ends with the shorter input. | | `retime` is refused | The clip loops. Place the shot again from the media bin with `place_media`, then retime the new clip. | | `audio.trim` or `audio.separate` is refused as `not_found` | It got a bin id like `m1`. Pass the song's sequence URL instead. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | Avoid: saying the sync is fine without looking | Instead: check `video.frames` at sung words on every synced take. | | Avoid: calling `generate` again to check on a sync | Instead: `read` the thread URL or call `status`. | #### Prompts to try Each prompt is a real variation of the job. ```text Cut a 9:16 version of the chorus only, one cut per beat, with a freeze frame on the last beat before the drop. ``` ```text Split the vocal from ./song.wav, then lip-sync the close-ups to the vocal with kling_lipsync. Show me frames at a few sung words in each. ``` ```text Cut on every beat on one branch, and on every phrase from audio.markers on another. Tell me which one you would pick and why. ``` #### When to use something else invideo has no audio-reactive effect that moves with the music on its own. For visuals that pulse with the sound, use a visualizer tool. Or cut on the beats as above, and add a zoom on the hits with a keyframe lane: `add_keyframe_lane` with `zoom_x` and `zoom_y`, then `add_keyframes`. For a music video shot on many cameras at once, sync the cameras by timecode in a multicam editor like Premiere Pro or DaVinci Resolve first, then bring the angles in. #### Related - [Cut a trailer or teaser from your film](/how-to/film/trailer-or-teaser) - [Make an AI short film with a character that stays the same](/how-to/film/short-film-consistent-character) - [Make a lyric video or text animation for your song](/how-to/creators/lyric-video) - [Make a Spotify Canvas and a music visualizer](/how-to/creators/spotify-canvas-and-visualizer) - [Check your video before you say it is done](/how-to/check-your-video) ### Claude Code as your AI film editor Source: https://docs.invideo.io/how-to/film/claude-code-as-film-editor.md Claude Code cuts your film on an invideo timeline from the transcript, adds sound design and a mixed soundtrack, captions it, checks it and exports it. You get Claude Code working as your film editor, also called an AI video editor or an agentic editor. It reads your footage folder, cuts the film on an invideo timeline from the transcript, designs the sound, mixes dialogue, music and effects on buses, adds captions, checks the result and exports it. You watch every edit land in the browser and change anything by hand. Use invideo for this when you want Claude Code to do the editing on a real timeline: every cut, sound and caption is a timeline object you can move, and each round of changes sits on its own branch for you to review. #### Quickest path Set up invideo in Claude Code first with [Set up invideo in Claude Code](/start/claude-code). The general setup for every client is on [invideo for AI agents](/agents). Then give Claude Code, your agent, a full brief like this one. ```text You are my film editor. The footage for my short "Low Tide" is in ./footage, with the script in ./script.pdf. Make an invideo project, upload everything, and work on a branch called first-cut. 1. Transcribe the dialogue. Tell me the price first. 2. Cut the film in script order. Pick the take with the cleanest read of each line. Keep a beat of air after each line. 3. Design the sound: waves and gulls under the beach scenes, a door creak at the cabin. Generate what you need, price it first. 4. Mix on buses for dialogue, music and effects. Compress and EQ the dialogue, duck the music under it, limit the master. 5. Add captions from the transcript. 6. Check every cut and the loudness, then export at the loudness target of the platform. Give me the timeline URL and a list of what needs my eye. ``` In Claude Code the agent names the folder and uploads the files itself. In a chat app, you drag the files into the project and the rest is the same. #### What you need Claude Code works from files on your machine, so keep them in one folder. - **The footage.** Camera files, with sound or with separate sound files. - **The script or an outline.** So the agent can cut in story order. - **Music.** Your track, or words for the mood if the agent should find stock or generate it. - **The sound you want.** Places and moments: "waves under the beach", "a door creak at 02:10". - **The delivery.** The shape, the frame rate, and the loudness target of the platform. #### Steps Claude Code uses the invideo CLI for this whole loop. It works on a branch and tells you what changed after each step. Claude Code sets up in four calls. 1. It makes a project with `invideo project new`. 2. It registers a name with `invideo agent register` and sets `INVIDEO_AS`. 3. It makes a timeline with `invideo edit new`. 4. It uploads the footage folder into the timeline's media bin with `invideo asset upload`. Expected result: a sequence URL and a media bin id for every file. Claude Code creates a branch with `invideo branch new`. Then the agent prices `audio.transcript` with `--dry-run` on each dialogue file's sequence URL from the upload, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `--max-credits` set to that price, and calls again after `retry_after_s` for the words. Expected result: every word with its time and speaker. Claude Code reads the transcript against the script and picks a take for each line. It places each take with `place_media`, with the source start and end of the line and `linked_audio` true. It sends the whole scene in one `edit_timeline` call. Expected result: a new `state_token` and the scene in order. Claude Code follows the generation pattern for each sound. 1. It runs `invideo gen models` (`find_models`) with the sound job in words, and reads the inputs of its pick with `invideo gen model` (`get_model`). A good pick for a single sound is `elevenlabs_sfx`, which returns an audio file. A good pick for sound from the picture is `mmaudio_v2.mmaudio_v2_video_to_audio`, which takes the shot as its `video` and returns the shot with its new sound. Your agent can search for others with `find_models`. 2. It runs `invideo gen run` with `--dry-run` and the real inputs, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it runs `invideo gen run` with `--max-credits` set to that price and an `--idempotency-key`. When the result lands, it reads the sequence URL with `invideo notebook show`, and never runs `gen run` again to check. 4. For a shot from `mmaudio_v2.mmaudio_v2_video_to_audio`, it pulls the sound out with `invideo media audio.extract`. The dry run shows its price before anything starts. 5. It places each sound on the effects track `A3` with `insert_media`. Expected result: a sequence URL per sound, and the sounds on the timeline. Claude Code creates buses with `create_audio_bus` and routes each track with `set_audio_routing`. It adds `eq` and `compressor` to the dialogue bus with `add_audio_effect`, `ducker` to the music bus, and `limiter` to the timeline. A new timeline ducks under `A1` by default, so the ducker already reacts to the voice on `A1`. In a second call, it sets each effect with `set_audio_effect_parameter` by the ids that `invideo edit show` returns. Expected result: the buses and effects in `get_timeline`. Claude Code turns the transcript words into slides and sends `add_captions` with slides and words, in timeline frames. Expected result: a caption clip. Claude Code runs `invideo edit check`, then `invideo edit capture` at each cut and caption, and `invideo media audio.loudness` on the dialogue and music sources. Then it runs `invideo edit export` with `--format video` and `--target-lufs` set to the platform's target. Expected result: an export card with status `completed`, and a list of what needs your eye. The same loop as CLI commands: ```bash invideo project new --title "Low Tide" invideo agent register --name editor export INVIDEO_AS=editor invideo edit new --name "Low Tide cut" --fps 24 invideo asset upload ./footage/* invideo edit show invideo branch new --name first-cut --token invideo edit show invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo gen models --query "door creak sound effect" invideo gen model --model elevenlabs_sfx invideo gen run --model elevenlabs_sfx --dry-run \ -i prompt="old wooden door creaks open slowly" invideo gen run --model elevenlabs_sfx \ --max-credits --idempotency-key door-creak \ -i prompt="old wooden door creaks open slowly" invideo status --wait invideo notebook show invideo edit change --timeline T1 --token \ --operations @mix.json invideo edit check invideo edit capture --at 0,30,60,90 --out ./frames invideo edit export --format video --target-lufs -14 --json invideo status --wait invideo notebook show --out . ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read fresh, because the main token is stale on the branch. `` is the `branch_url` that `branch new` returns. `` is the `url` that `invideo asset upload` returns for a dialogue file. `` is the price each dry run returns, its `estimated_credits` or `credits`. `` is the `url` of the paid `gen run`. `` comes from `invideo notebook show `. `` is `.sequences[0]` of the export answer. `invideo status` waits but does not download. `notebook show` with `--out` saves the file as `export.mp4`. The key edit sets up the mix. This fence is the full MCP `edit_timeline` call. The file in `--operations @mix.json` holds only its `operations` list, as a bare list. The new timeline has `A1` for voice, `A2` for music and `A3` for effects. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "create_audio_bus", "timeline": "T1", "name": "Dialogue" }, { "op": "create_audio_bus", "timeline": "T1", "name": "Music" }, { "op": "add_audio_effect", "target": "A2", "target_kind": "track", "effect": "ducker" }, { "op": "add_audio_effect", "target": "A1", "target_kind": "track", "effect": "compressor" }, { "op": "add_audio_effect", "target": "T1", "target_kind": "timeline", "effect": "limiter" } ] } ``` The buses and effects get their ids when this call lands. Claude Code reads them with `invideo edit show`. In the next call it routes the tracks to the buses with `set_audio_routing`. The ducker already reacts to the voice on `A1`, the default sidechain source of a new timeline. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** the transcript with `audio.transcript`, each sound from `elevenlabs_sfx` or `mmaudio_v2.mmaudio_v2_video_to_audio`, generated music, and stock you place. - **Free:** uploads, every edit (the cut, the buses and audio effects, captions), checks with `invideo edit capture` and `invideo edit check`, and every export. `audio.extract` and `audio.loudness` show their price in the dry run before anything starts. A short film's first cut takes Claude Code under an hour. Your review takes the longest. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from sign-in, a stale token, or mixing MCP and the CLI. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `invideo: command not found` | The CLI is not on PATH. Install it as [Set up invideo in Claude Code](/start/claude-code) shows, then run `invideo --version`. | | `edit_timeline` refused with an old token | Someone edited first. Read with `get_timeline`, then rebuild the ops. | | `completion_unknown` or a timeout on an edit | Retry the identical request with the same token. A conflict means it landed. | | The transcript returns status running | Call `audio.transcript` again after `retry_after_s`. Only the first call costs credits. | | The music does not duck | A new timeline ducks under `A1`. If the dialogue sits on another track, point the ducker at it with `set_sidechain_source`. | | `audio.transcript` is refused as `not_found` | It got a bin id like `m1`. Pass the file's sequence URL instead. | | `mmaudio_v2.mmaudio_v2_video_to_audio` returns a video, not a sound | The model returns the shot with its new sound. Pull the sound out with `invideo media audio.extract`. | | The output folder is empty after `status` | `status` does not download. Run `invideo notebook show --out .`. | | CLI exit 4 | Not signed in. Run `invideo auth login`. | | Avoid: mixing MCP tools and the CLI in one session | Instead: pick one per session. | | Avoid: saying done after the last edit | Instead: `capture` and `check_timeline` first. | | Avoid: editing main | Instead: a branch per round of changes. You decide what goes to main. | #### Prompts to try Each prompt is a real variation of the job. ```text Open the Low Tide project, start a branch called tighter, and tighten the beach scene without losing a line. Show me the cuts. ``` ```text Generate foley from the picture for the cabin scene with mmaudio, put it on the effects bus, and duck it under the dialogue. ``` ```text Make a captions-off version: turn off the caption clip, export, then turn it back on. Give me both files. ``` #### When to use something else For a surround mix or a final mix to a broadcast spec, export the audio with `export` mode `audio`, or the project with `format` `premiere` or `davinci`, and mix in a DAW like Pro Tools. For a feature-length film with many reels, the agent works one reel per timeline. Join the reels in your finishing tool. #### Related - [Set up invideo in Claude Code](/start/claude-code) - [Edit a documentary or interview from the transcript, with b-roll and lower thirds](/how-to/film/documentary-and-interview-edit) - [Clean up the dialogue and keep the original](/how-to/film/dialogue-cleanup) - [How to add AI sound design to a video](/guides/how-to-add-ai-sound-design-to-a-video-in-invideo-editor) - [What is audio ducking and when would I use ducker?](/guides/what-is-audio-ducking-and-when-would-i-use-ducker) - [Check your video before you say it is done](/how-to/check-your-video) ### Make storyboards and previs before the shoot Source: https://docs.invideo.io/how-to/film/storyboards-and-previs.md Storyboard frames for every shot, an animatic timed on a timeline, previs clips from the boards, and a greybox render dressed into a lookable shot. You get a storyboard for every shot, also called boards or a shot board, laid out on a timeline as an animatic with notes on lens, move and dialogue. Then your agent turns key boards into short previs clips, and turns your own greybox blocking render into a dressed shot, so everyone on the shoot sees the film first. Use invideo for this when you want the boards, the animatic and the previs in one project: each board is a clip you can retime, swap or redraw, and the timeline runs at your shoot's frame rate from the start. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Here is my shot list for scene 3 in ./shotlist.md. Make a storyboard frame for each shot with cinematic_cameras, using the lens and focal length I list. Lay them on a 24 fps timeline as an animatic with a note on each board. Then make previs clips of shots 3 and 7. Price it first. ``` In a chat app, you paste the shot list into the chat. In a terminal, you name the file and the agent reads it. #### What you need A shot list with framing and lens is enough. A script helps the agent time the animatic. - **The shot list.** Shot number, framing, lens, camera move, action and dialogue. - **The look.** Sketch boards, or photo-like frames that show light and lens. - **References.** Photos of the location, the cast or the props, if you have them. - **The shoot's frame rate and shape.** For example 24 fps and 2.39:1, or 25 fps and 16:9. - **A greybox render, for the recipe.** A simple blocking render from Blender, Unreal or another 3D tool. #### Steps The agent works on a branch and shows you each board as it lands. The agent follows the generation pattern for the boards. 1. It runs `find_models` with the job in words, picks an image model, and reads its inputs with `get_model`. A good pick is `cinematic_cameras`, which takes a lens, a focal length and an aperture, so each board looks like the lens you list. Your agent can search for others with `find_models`, such as `flux_2_lora.ballpoint_pen_sketch` for sketch boards, or `nanobanana_pro` and `gpt_image_26` for boards from reference images. 2. It calls `generate` with `dry_run: true` on one board, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it runs each board with `max_credits` set to that price and its own `idempotency_key`, reads each sequence URL with `read`, and names each board with `rename`, like "Shot 3 · 35mm push in". Expected result: an image sequence URL per shot. The agent makes a timeline with `new_timeline` at the shoot's frame rate, or sets it with `set_timeline_settings`. It places each board on `V1` with `insert_media` in shot order and sets its length to the shot's time with `trim_clip`. For a camera move on a still board, it adds the `dynamic_zoom` effect with `add_effect`, then sets its start and end framing with `set_effect_parameter` in a second call. Expected result: an animatic that runs as long as the scene. The agent adds a text clip on the board with `add_text`: the shot number, the lens, the move and the line of dialogue. It adds a marker per shot with `add_marker`. Expected result: notes you can read in every frame of the animatic. For a shot that needs motion, the agent runs `find_models` for video from a first frame and reads its pick with `get_model`. A good pick is `seedance_2_5.frames`, with the board as its first frame. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It reads the sequence URL with `read`, and swaps the clip in with `place_media` mode `replace`. Expected result: a moving shot where the board was. You give the agent your blocking render, and it brings it in with `add_media`. It runs `find_models` for a model that restyles a video and keeps its motion, and reads its pick with `get_model`. A good pick is `luma_ray_32.edit`, which restyles a video from a prompt. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, and reads the sequence URL with `read`. Expected result: the same blocking and camera move, with real-looking light, set and cast. The agent runs `capture` at each board and `check_timeline`. Then it runs `export` with `format` video and the `fps` of the shoot. For printed boards, it exports one still per shot with `mode` image and `still_at`. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo edit new --name "Scene 3 animatic" --fps 24 invideo gen models --query "storyboard frame with a real lens" invideo gen model --model cinematic_cameras invideo gen run --model cinematic_cameras --dry-run \ -i prompt="Rain on a bus window, a woman looks out" \ -i focal_length=35mm -i lens="Cine Prime" -i aspect_ratio=16:9 invideo gen run --model cinematic_cameras \ --max-credits --idempotency-key board-03 \ -i prompt="Rain on a bus window, a woman looks out" \ -i focal_length=35mm -i lens="Cine Prime" -i aspect_ratio=16:9 invideo status --wait invideo notebook show invideo asset upload ./greybox/shot-07.mp4 invideo gen models --query "restyle a video, keep its motion" invideo gen model --model luma_ray_32.edit invideo gen run --model luma_ray_32.edit --dry-run \ -i video= -i prompt="Night street, wet asphalt, neon" invideo gen run --model luma_ray_32.edit \ --max-credits --idempotency-key greybox-07 \ -i video= -i prompt="Night street, wet asphalt, neon" invideo edit change --timeline T1 --token \ --operations @animatic.json invideo edit capture --at 0,4,8,12 --out ./frames invideo edit export --format video --fps 24 invideo edit export --format video --mode image --still-at 4 ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` comes from `invideo notebook show `. `` is the price each dry run returns, its `estimated_credits`. A dry run returns a price and no URL, so `` is the `url` the paid run returns. `` is the `url` that `invideo asset upload` returns. `` comes from `invideo edit show `. The file in `--operations @animatic.json` is a bare list of ops, like the `operations` list below. The key MCP call lays a board with its note and marker. This fence is the full MCP `edit_timeline` call. `start_f` and `end_f` are frames at the timeline's frame rate. `` is the timeline's URL from `new_timeline`, `` comes from `get_timeline`, and `` is the sequence URL of the first board. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "insert_media", "asset": "", "track": "V1", "at_f": 0, "ripple": true }, { "op": "add_text", "track": "V3", "start_f": 0, "end_f": 96, "text": "1 · WS · 24mm · static · She waits at the stop" }, { "op": "add_marker", "at_f": 0, "name": "Shot 1" } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** each board from an image model, each previs clip from a video model, and each greybox dressed with `luma_ray_32.edit` or `id_v2v.restyle`. - **Free:** the animatic, the notes and markers, the frame rate, `capture`, the stills and the video export. Boards for a scene take a few minutes each. A previs clip takes a few minutes more. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from boards that disagree on the look, or a greybox the model cannot read. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | The boards look like different films | Pass the same reference images to every board, and keep the same style words in every prompt. | | A board has the wrong lens | Set `focal_length` and `lens` on `cinematic_cameras` instead of naming the lens in the prompt. | | The dressed greybox loses the camera move | Use an adhere preset in `strength` on `luma_ray_32.edit`, which keeps more of the source. Or restyle the render's first frame with `nanobanana_pro`, then run `id_v2v.restyle`, which keeps the source's motion. Price each with `dry_run` first. | | The previs clip runs at a different frame rate | Export with `fps` set to the shoot's rate. The timeline's rate sets the cuts. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | CLI exit 5 | A limit on credits or quota. Check the balance. | | Avoid: generating every board in one go without a price | Instead: run `dry_run` on one board, tell the person the price per board, then run the rest. | | Avoid: calling `generate` again to check on a board | Instead: `read` the thread URL or call `status`. | #### Prompts to try Each prompt is a real variation of the job. ```text Make pen-sketch boards for the whole shot list with flux_2_lora.ballpoint_pen_sketch. Time the animatic to my scratch voice track in ./scratch.wav. ``` ```text Here is my Blender greybox of the car chase. Dress it as a night city with luma_ray_32.edit and keep every camera move. Show me frames side by side with the greybox. ``` ```text Export one still per board for the shooting script, then a 25 fps video of the animatic for the people on set. ``` #### When to use something else invideo does not build 3D sets or block cameras in 3D. Make the greybox in a 3D tool such as Blender, Unreal Engine or Cascadeur, then bring the render in for the recipe above. For a printed storyboard book with panels and arrows, lay out the exported stills in a layout tool like Storyboarder or InDesign. #### Related - [Make an AI short film with a character that stays the same](/how-to/film/short-film-consistent-character) - [Generate a missing shot or extend a clip inside your edit](/how-to/film/generate-a-missing-shot) - [Make a sizzle reel or proof-of-concept to raise money](/how-to/film/sizzle-reel-for-financing) - [Get started with AI filmmaking](/guides/get-started-with-ai-filmmaking) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Edit a documentary or interview from the transcript Source: https://docs.invideo.io/how-to/film/documentary-and-interview-edit.md Your interviews transcribed, the quotes picked by what they mean, a paper edit you can change, and a cut with b-roll, lower thirds, music and chapters. You get a documentary or interview film cut from hours of interviews, also called a talking-head edit or a doc edit. Your agent transcribes every interview with speakers, reads them to find the quotes that say what your story needs, writes a paper edit for you to change, then cuts the film with b-roll, lower thirds, music under the voices, and chapter markers. Use invideo for this when you want the paper edit and the cut to stay connected: the quotes live in a brief you can edit, every quote lands on the timeline with its in and out points, and you can swap a quote without starting again. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Here are the interviews in ./interviews and b-roll in ./broll. The film is about why the town's last mill closed. Transcribe the interviews with speakers, price it first. Find the quotes that tell the story in chapters, write them as a paper edit, and wait for my changes. Then cut it with b-roll, lower thirds with names, and music under the voices. ``` In a chat app, you drag the files into the project. In a terminal, you name the folders and the agent uploads them, large files included. #### What you need The agent finds quotes by reading what people mean, so tell it what the film is about. - **The interviews.** Camera files with sound, or picture and separate sound. - **The names and titles.** Who each speaker is, for the lower thirds. - **The story.** The question the film answers, and the chapters if you know them. - **B-roll.** Shots of the places, people and things the interviews talk about. - **Music.** Your track, or a mood for stock or generated music. #### Steps The agent works on a branch. It stops after the paper edit for your changes. The agent sets up in three calls. 1. It makes the timeline with `new_timeline`, and a branch with `timeline_history` and `action: "create_branch"`. 2. For each large local file, it calls `start_upload` and PUTs the bytes to the `upload_url`. 3. It calls `add_media` with the `upload_id` and the branch URL. Expected result: a sequence URL and a media bin id for every interview and b-roll file. The agent prices `audio.transcript` with `dry_run` on each interview's sequence URL from `add_media` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. Expected result: every word with its time and speaker, for every interview. The agent reads the transcripts against your story and finds the lines that answer each question, even when the speaker uses other words. It makes a brief with `new_brief` and writes each quote into it with `edit`, in story order, with the speaker, the words, and the in and out times. Expected result: a brief URL. You reorder, cut or add quotes in the brief, and tell the agent when it is ready. The agent reads the brief with `read` and places each quote on `V1` with `place_media`, using its in and out times and `linked_audio` true. Then it places b-roll on `V2` with `insert_media` over the lines it illustrates, and lowers the b-roll's own sound with `set_audio_gain`. It sends a chapter in one `edit_timeline` call. Expected result: the interviews cut in paper-edit order with b-roll over the voices, and a new `state_token`. The agent adds each speaker's name and title with `add_text` the first time they appear, and fades it in and out with `set_keyframes` on opacity. It places your music, or the bed from the music section below, on `A2` and adds `ducker` to that track with `add_audio_effect`. A new timeline ducks under `A1`, where the interview sound sits, so no sidechain call is needed. It adds a marker per chapter with `add_marker`. Expected result: lower thirds, music that dips under every voice, and chapter markers. The agent runs `capture` at each lower third and each chapter start, and `check_timeline`. It checks that no lower third covers a face. Then it runs `export`. Expected result: an export card with status `completed`, and a chapter list with timecodes for YouTube. ##### Make a music bed when you have no track The agent follows the generation pattern. 1. It runs `find_models` with the music job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_music_v2_5_instrumental`. Your agent can search for others with `find_models`. 2. It calls `generate` with `dry_run: true`, a `prompt` and a `duration` within the range `get_model` gives, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It gets a thread URL and, when the result lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. The same job from a terminal: ```bash invideo edit new --name "The Mill, cut 1" --fps 25 invideo asset upload ./interviews/* ./broll/* invideo edit show invideo branch new --name paper-edit-v1 --token invideo edit show invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo gen models --query "quiet instrumental music bed" invideo gen model --model elevenlabs_music_v2_5_instrumental invideo gen run --model elevenlabs_music_v2_5_instrumental \ --dry-run -i prompt="quiet piano, slow, hopeful" -i duration=180 invideo gen run --model elevenlabs_music_v2_5_instrumental \ --max-credits --idempotency-key mill-music \ -i prompt="quiet piano, slow, hopeful" -i duration=180 invideo context new-brief --name "The Mill paper edit" \ --description "Quotes in story order, by chapter" invideo context write --markdown @paper-edit.md \ --revision invideo edit change --timeline T1 --token \ --operations @chapter-1.json invideo edit capture --at 5,62,140,233 --out ./frames invideo edit check invideo edit export --format video --quality 1080 ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read fresh, because the main token is stale on the branch. `` is the `branch_url` that `branch new` returns. `` is the `url` that `invideo asset upload` returns for each interview. `` is the price each dry run returns, its `estimated_credits`. `` comes from `invideo notebook show `. `` is the URL `context new-brief` returns, and `` comes from reading the brief with `invideo context show`. The file in `--operations @chapter-1.json` is a bare list of ops, like the `operations` list below. The key MCP call lays one quote, adds its lower third, and marks the chapter. This fence is the full MCP `edit_timeline` call. `at_f`, `start_f` and `end_f` are frames at the timeline's frame rate, and `m1` is the interview's bin id from `get_timeline`. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "place_media", "asset": "m1", "track": "V1", "at_f": 0, "source_start_seconds": 812.4, "source_end_seconds": 829.9, "mode": "append", "linked_audio": true }, { "op": "add_text", "track": "V3", "start_f": 25, "end_f": 150, "text": "Ruth Okafor\nMill worker, 1979 to 2019" }, { "op": "add_marker", "at_f": 0, "name": "Chapter 1: The town" } ] } ``` The fade goes in the next call, on the text clip's id: `set_keyframes` with `property` opacity and points from 0 to 1 over a short fade-in. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** a transcript per interview with `audio.transcript`, and any stock or generated music. - **Free:** uploads, reading the transcripts, the paper edit, the cut, b-roll, lower thirds, the ducker, markers, `capture` and the export. Transcripts of a day of interviews take a few minutes each. The paper edit takes the agent a few minutes, and your review takes the longest. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from quotes cut mid-word or speakers with the wrong label. | Symptom | Fix | | --- | --- | | A quote starts or ends mid-word | Move the edge a few frames out with `trim_clip`, then listen again. | | Two speakers share one label | Tell the agent who speaks first in that interview. It relabels them in the paper edit. | | A quote is in the brief but not on the timeline | The agent reads the brief again with `read` and places the missing line. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `audio.transcript` is refused as `not_found` | It got a bin id like `m1`. Pass the interview's sequence URL instead. | | The music does not dip under the voices | A new timeline ducks under `A1`. If the voices sit on another track, point the ducker at it with `set_sidechain_source`. | | A lower third covers a face | Move it with `set_position`, then `capture` again. | | The transcript returns status running | Call `audio.transcript` again after `retry_after_s`. Only the first call costs credits. | | An upload by URL fails on a large file | Use `start_upload`, then `add_media` with the `upload_id`. | | Avoid: searching for keywords only | Instead: read the transcript for what people mean. The best quote often uses other words. | | Avoid: cutting before you approve the paper edit | Instead: change the brief first. The cut follows it. | #### Prompts to try Each prompt is a real variation of the job. ```text Find every place where someone talks about the strike, even if they do not say "strike". List them with speaker and timecode, best first. ``` ```text Swap quote 7 in the paper edit for the one where Ruth talks about her father, then recut chapter 2 and show me the cut points. ``` ```text Make a short teaser from the paper edit: the strongest lines, b-roll under each, and the title card at the end. ``` #### When to use something else invideo does not clear archive footage or music rights for you. Clear archive clips with their owners, and use stock or generated music for anything you cannot clear. For a broadcast delivery with a closed-caption file to a network spec, or a surround mix, finish in Premiere Pro or DaVinci Resolve: export the project with `format` `premiere` or `davinci`. #### Related - [Turn dailies into string-outs and selects](/how-to/film/dailies-to-string-outs) - [Clean up the dialogue and keep the original](/how-to/film/dialogue-cleanup) - [Cut a trailer or teaser from your film](/how-to/film/trailer-or-teaser) - [Make titles readable over busy footage](/guides/how-do-i-make-titles-readable-over-busy-footage) - [What is audio ducking and when would I use ducker?](/guides/what-is-audio-ducking-and-when-would-i-use-ducker) - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) ### Cut a trailer or teaser from your film Source: https://docs.invideo.io/how-to/film/trailer-or-teaser.md A trailer and a shorter teaser cut from your finished film, with the best lines, title cards, hits on the music and a drop that lands, each on its own branch. You get a trailer and a teaser from your film, also called a promo, a sizzle or a cutdown. Your agent finds the strongest moments and lines, builds the cut to the music so the big moment lands on the drop, adds title cards, freeze frames and hits, and keeps each length on its own branch. Use invideo for this when you want the agent to do the first pass from the whole film: it reads the dialogue, the sound and the music for you, and every cut stays on a timeline you can change. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Cut a trailer and a teaser from my film ./final/the-mill.mov with the music ./trailer-track.wav. Use the best lines of dialogue. Land the title on the drop. Put the trailer and the teaser on their own branches. Price the transcript first. ``` In a chat app, you drag the film and the music into the project. In a terminal, you name the files and the agent uploads them. #### What you need A finished film or a locked cut works best, because the trailer uses final sound. - **The film.** The final export or the locked cut. - **The music.** A track with a build and a drop, or a mood for stock or generated music. - **The title and the cards.** The film's title, the tagline, the release date or festival laurels. - **The lengths.** For example a full trailer and a much shorter teaser. - **What not to show.** The ending, a twist, a cameo. #### Steps The agent works on branches and tells you the timecodes of every moment it picks. The agent makes a timeline with `new_timeline`. For a large film file, it calls `start_upload`, PUTs the bytes, then calls `add_media` with the `upload_id`. Expected result: a sequence URL and a media bin id for the film and the music. The agent reads the film three ways. 1. For the lines, the agent prices `audio.transcript` with `dry_run` on the film's sequence URL from `add_media` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. 2. It runs `audio.onsets` and `audio.content` for the loud and quiet moments. 3. It splits the film into its scenes with `video.sceneSplit` and looks at each with `video.frames`. Expected result: a list of lines and moments with timecodes. You strike anything that gives away the ending. The agent runs `audio.sections` and `audio.markers` on the music to find the build and the drop, and `audio.onsets` for the hits. Expected result: the times of the drop and each hit, turned into frames. The agent creates a branch called trailer with `timeline_history`. It places the music on `A2`, then each moment on `V1` with `place_media`, so the cuts land on the hits and the biggest moment lands on the drop. It places each line with `linked_audio` true. Expected result: a new `state_token` and a cut that follows the music. The agent adds title cards with `add_text` between shots, and holds a frame on a hit with `retime` kind `freeze`. For extra impact, it makes a sound with the generation pattern. 1. It runs `find_models` with the sound in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_sfx`. Your agent can search for others with `find_models`. 2. It calls `generate` with a `prompt` for the hit or the riser and `dry_run: true`, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, reads the sequence URL with `read` when the result lands, and places the sound on the effects track `A3`. Expected result: cards and hits on the beats you planned. From the finished trailer, the agent creates a teaser branch with `timeline_history` action `create_branch`. On it, it keeps the hook, one line and the title, and removes the rest with `edit_time_range` mode `close_gap`. Expected result: two branch URLs, one per length. On each branch, the agent runs `capture` at each card and the drop, and `check_timeline`. It checks that no card has a typo and the title lands on the drop. Then it runs `export` on each branch's URL with `target_lufs`. Expected result: two export cards with status `completed`. The same job from a terminal: ```bash invideo edit new --name "The Mill trailer" --fps 24 invideo asset upload ./final/the-mill.mov ./trailer-track.wav invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo media audio.onsets --asset m1 invideo media audio.sections --asset m2 invideo media audio.markers --asset m2 invideo edit show invideo branch new --name trailer --token invideo gen models --query "cinematic boom hit sound" invideo gen model --model elevenlabs_sfx invideo gen run --model elevenlabs_sfx --dry-run \ -i prompt="deep cinematic boom hit" -i duration=3 invideo gen run --model elevenlabs_sfx \ --max-credits --idempotency-key trailer-hit-1 \ -i prompt="deep cinematic boom hit" -i duration=3 invideo status --wait invideo notebook show invideo edit show invideo edit change --timeline T1 \ --token --operations @trailer.json invideo edit show invideo branch new --name teaser \ --token invideo edit show invideo edit change --timeline T1 \ --token --operations @teaser.json invideo edit capture --at 10,45,88,112 --out ./frames invideo edit capture --at 2,10,24 --out ./frames invideo edit export --format video --target-lufs -14 invideo edit export --format video --target-lufs -14 ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the `url` that `invideo asset upload` returns for the film; `m1` and `m2` are the bin ids, which the reads that return at once take with `--asset`. `` is the price each dry run returns, its `estimated_credits`, and `` is the `url` of the paid `gen run`. `` comes from `invideo notebook show `. `` and `` are the `branch_url` each `branch new` returns. `` comes from the latest `invideo edit show` on the URL the next command runs on: `` for the first `branch new`, then each branch, read fresh after each change. A token from another branch, or from before a change, is stale. The files in `--operations @trailer.json` and `--operations @teaser.json` are bare lists of ops, like the `operations` list below. The key MCP call lands a line before the drop and puts the title on the drop. This fence is the full MCP `edit_timeline` call. Each frame is the time in seconds times the frame rate. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "place_media", "asset": "m1", "track": "V1", "at_f": 2016, "source_start_seconds": 3121.0, "source_end_seconds": 3125.0, "mode": "overwrite", "linked_audio": true }, { "op": "add_text", "track": "V3", "start_f": 2112, "end_f": 2208, "text": "THE MILL" } ] } ``` The agent reads the new clip's id with `get_timeline`. In the next call, it sends `retime` kind `freeze` on it with `at_f` 2100 and `duration_f` 12 to hold the hit. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** the film's transcript with `audio.transcript`, each sound from `elevenlabs_sfx`, and stock or generated music. - **Free:** the cut, cards, freezes, branches and both exports. `audio.onsets`, `audio.content`, `audio.sections`, `audio.markers`, `video.sceneSplit` and `video.frames` show their price in the dry run before anything starts. The transcript of a feature takes a few minutes. The first pass of a trailer takes the agent under an hour. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a drop that misses, or a cut that gives too much away. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | The title misses the drop | Read the drop time again from `audio.markers`, round it to the frame, and move the card with `move_clip`. | | A line is cut mid-word | Move the edge a few frames out with `trim_clip`, then listen again. | | The trailer gives away the ending | Tell the agent which scenes are off limits. It removes them. Ask it to add them to `invideo_rules.md`, so later cuts skip them too. | | A silent scene has no moments picked | Silent scenes give no sound cues. The agent picks them by frames with `video.frames`. | | The teaser changed the trailer | It was edited on the same branch. Restore the trailer from its checkpoint with `timeline_history` action `restore`. | | `audio.transcript` is refused as `not_found` | It got a bin id like `m1`. Pass the film's sequence URL instead. | | `edit_timeline` refused with an old token | Someone edited first. Read with `get_timeline`, then rebuild the ops. | | Avoid: exporting main for both lengths | Instead: export each branch's URL. The branch in the URL is what gets exported. | | Avoid: calling `export` again to check on one | Instead: `status` or `read` the card's URL. | #### Prompts to try Each prompt is a real variation of the job. ```text Make a short vertical teaser for Instagram from the trailer branch: the hook, the title on the drop, and the date. Captions on the line. ``` ```text Give me a trailer built on dialogue and one built on music and images only, each on its own branch. Tell me which lands harder. ``` ```text Add a boom on every title card and a riser into the drop. Price the sounds before you make them. ``` #### When to use something else Theatrical trailers often need a rating card and a mix to a cinema spec. Make the rating card from the rating body's own artwork, and mix to a cinema spec in a DAW like Pro Tools. For a trailer music cue made to picture by a composer, cut the picture first, export it, and send it to the composer. #### Related - [Make a sizzle reel or proof-of-concept to raise money](/how-to/film/sizzle-reel-for-financing) - [Make a music video with lip sync and beat sync](/how-to/film/music-video-lip-sync) - [Edit a documentary or interview from the transcript, with b-roll and lower thirds](/how-to/film/documentary-and-interview-edit) - [Make a book trailer or a game trailer](/how-to/creators/book-or-game-trailer) - [Choose a transition that fits the cut](/guides/how-do-i-choose-a-transition-that-fits-the-cut-in-invideo-editor) - [Check your video before you say it is done](/how-to/check-your-video) ### Make a sizzle reel or proof-of-concept to raise money Source: https://docs.invideo.io/how-to/film/sizzle-reel-for-financing.md A short reel that sells your film or series to investors, mixing your footage, stock and generated concept shots, each generated shot labeled as concept. You get a sizzle reel for financing, also called a proof-of-concept, a pitch reel or a mood reel. It shows the world, the tone and the story of your project in a short reel. Your agent mixes your own footage, stock and generated concept shots, adds a voice-over, music and captions, and labels every generated shot as concept art. Use invideo for this when you have more vision than footage: the agent makes the missing shots, finds stock, and cuts it all on one timeline, and the reel stays editable for each investor meeting. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Make a short sizzle reel for my series "Salt Road". My test footage is in ./tests, the pitch deck is ./deck.pdf. Write the plan as a brief first. Fill the gaps with stock and generated concept shots, and label each generated shot "Concept". Add a voice-over from the logline, music and captions. Price everything before you spend. ``` In a chat app, you drag the footage and the deck into the project. In a terminal, you name the files and the agent uploads them. #### What you need Investors want to see the tone and know what is real. Give the agent both. - **Your footage.** Test shoots, a scene, a teaser, location scouts. - **The pitch.** The logline, the world, the characters, the comparable titles. - **The voice-over script.** Or ask the agent to write one from the logline. - **The look.** Mood images or a deck. - **Music.** A track you have the rights to, or a mood for stock or generated music. - **The length.** A sizzle is usually a few minutes. #### Steps The agent writes a plan first, then cuts on a branch. The agent makes a brief with `new_brief`, then writes the beats into it with `write`: the hook, the world, the characters, the stakes, the ask. Each beat says which shots are yours, which are stock, and which it will generate. Expected result: a brief URL. You change the plan before anything is spent. The agent brings in three kinds of media. 1. It adds your files with `add_media`, or `start_upload` for large files. 2. It turns the deck into images with `media` `document.pages`, so slides can become cards. The dry run shows its price before anything starts. 3. It searches `search_library` in `stock_video`, shows you the previews, and places the ones you pick with `add_media` and `stock`. The dry run shows the stock's price. Expected result: a sequence URL per file, an image per deck page, and the stock you picked. The agent follows the generation pattern for each shot that does not exist. 1. It runs `find_models` with the shot in words, picks one, and reads its inputs with `get_model`. A good pick is `seedance_2_5.r2v`. Your agent can search for others with `find_models`. 2. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, and reads the sequence URL with `read` when the result lands. It names each shot for its beat with `rename`. Expected result: a sequence URL per concept shot. The agent follows the same pattern for the voice. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. Your agent can search for others with `find_models`. It reads the inputs with `get_model`, finds a voice with `search_library` in `elevenlabs_text_to_speech_voices`, and gives you the previews. It calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a voice-over sequence URL you can play. The agent makes a timeline with `new_timeline` and a branch with `timeline_history`. It places the voice-over on `A1`, the shots in brief order on `V1` with `insert_media` and `place_media`, and the music on `A2` with `ducker` from `add_audio_effect`. A new timeline ducks under `A1`, so the ducker reacts to the voice-over. Expected result: a first cut, and a new `state_token`. On every generated shot, the agent adds a small "Concept" label with `add_text` for the length of the shot. It ends with a card that says which shots are concept art and names the models used. For captions, the agent prices `audio.transcript` with `dry_run` on the voice-over's sequence URL and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a label on every generated shot, and captions. The agent runs `capture` on every generated shot to check its label, and at each card. It runs `check_timeline`, then `export`. Expected result: an export card with status `completed`. You share it from an export page with `share_export_page`, private or with a link. The same job from a terminal: ```bash invideo context new-brief --name "Salt Road sizzle" \ --description "Short pitch reel for investors" invideo asset upload ./tests/* ./deck.pdf invideo media document.pages invideo library search --library stock_video \ --query "desert highway at dusk" invideo gen models --query "cinematic concept shot" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ -i prompt="A salt flat at dawn, a lone truck, wide, 35mm" invideo gen run --model seedance_2_5.r2v \ --max-credits --idempotency-key salt-flat-01 \ -i prompt="A salt flat at dawn, a lone truck, wide, 35mm" invideo status --wait invideo notebook show invideo library search \ --library elevenlabs_text_to_speech_voices --query "warm, low" invideo edit new --name "Salt Road sizzle" --fps 24 invideo branch new --name sizzle-v1 --token invideo edit show invideo edit change --timeline T1 --token \ --operations @labels.json invideo edit capture --at 8,31,57,96 --out ./frames invideo edit export --format video --target-lufs -14 ``` Where the values come from: `` from `invideo project new`. `` is the `url` that `invideo asset upload` returns for the deck; uploads land in a dated folder, so never guess the path. `` comes from `invideo notebook show `. `` is the price the dry run returns, its `estimated_credits`, and `` is the `url` the paid run returns. `` comes from `invideo edit new`. `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read fresh, because the main token is stale on the branch. `` is the `branch_url` that `branch new` returns. The file in `--operations @labels.json` is a bare list of ops, like the `operations` list below. The voice-over runs the same `gen model`, dry run and capped run on `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a `voice_id` from that search. The key MCP call labels a generated shot and adds the end card. This fence is the full MCP `edit_timeline` call. `start_f` and `end_f` are frames at the timeline's frame rate. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "add_text", "track": "V3", "start_f": 744, "end_f": 864, "text": "Concept", "style": { "font_size": 28, "color": "#ffffffcc" } }, { "op": "add_text", "track": "V3", "start_f": 2760, "end_f": 2880, "text": "Concept shots: Seedance 2.5.\nAll else is real footage." } ] } ``` #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** each generated shot, the voice-over, generated music, the captions' transcript, and each stock clip you place. - **Free:** the brief, searching stock, the cut, the labels, `capture`, export pages and the export. `document.pages` shows its price in the dry run before anything starts. A first cut takes the agent under an hour. The concept shots take a few minutes each. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a reel that blurs what is real and what is concept. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | A generated shot has no label | `capture` each generated shot and add the missing label with `add_text`. | | The label covers a face | Move it to a corner with `set_position`, then `capture` again. | | The voice sounds wrong | Pick another voice from `search_library` and generate again. Keep the old take. | | The music drowns the voice | Add `ducker` to the music track `A2`. A new timeline ducks under `A1` by default. If the voice is on another track, point the ducker at it with `set_sidechain_source`. | | `document.pages` returns "Nothing at that URL" | The path was guessed. Pass the URL that `invideo asset upload` returned for the deck. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | CLI exit 5 | A limit on credits or quota. Check the balance. | | Avoid: passing off a generated shot as footage | Instead: label it. Investors check, and a missing label costs trust. | | Avoid: calling `generate` again to check on a shot | Instead: `read` the thread URL or call `status`. | Investors and their lawyers expect generated material to be labeled. A clear "Concept" label and an end card that names the tools keep the reel honest and keep the meeting on your story. #### Prompts to try Each prompt is a real variation of the job. ```text Make a short version of the sizzle on its own branch for a cold email: the hook, the world, the ask. Keep every concept label. ``` ```text Swap the stock desert shots for generated ones in the same style as my test footage. Label them, and show me frames side by side. ``` ```text Make a version for a streamer with the comparable titles on cards after the hook, and a version without them. ``` #### When to use something else invideo does not make the pitch deck itself. Write the deck in a slide tool like Keynote or Google Slides, then bring it in with `add_media` and `document.pages`. For investor rooms that need a secure screening link with view tracking, host the export on a review platform like Frame.io or Vimeo. #### Related - [Cut a trailer or teaser from your film](/how-to/film/trailer-or-teaser) - [Make storyboards and previs before the shoot](/how-to/film/storyboards-and-previs) - [Make an AI short film with a character that stays the same](/how-to/film/short-film-consistent-character) - [Label AI content so the ad runs](/how-to/marketing/ai-disclosure-for-ads) - [Licensing and commercial use](/account/commercial-use) ### Turn dailies into string-outs and selects Source: https://docs.invideo.io/how-to/film/dailies-to-string-outs.md Your day's footage synced to the sound, laid out in slate order, circled takes marked, a string-out per scene and a selects reel, ready for your editing app. You get your dailies organized for the edit: picture synced to the sound recorder, every take laid out in slate order, the circled takes marked, a string-out per scene, and a selects reel. This work is also called syncing dailies, an assistant editor's prep, or a string-out. Your agent does it on invideo timelines and hands it to your editing app as a project. Use invideo for this when you want the prep done by your agent while you sleep: it reads the slates and the sound, builds a timeline per scene, and exports a project that Premiere Pro, DaVinci Resolve or Final Cut Pro opens. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt. ```text Day 4 dailies are in ./day-04: camera files in ./day-04/A-cam and ./day-04/B-cam, sound in ./day-04/sound. Sync picture to sound, lay the takes in slate order, mark the circled takes from ./day-04/notes.txt, and make a string-out per scene and a selects reel. Price the transcripts first. Then export a DaVinci Resolve project. ``` In a terminal, the agent uploads the folders itself, large files included. In a chat app, you drag the files into the project. #### What you need Clear slates make this fast. The agent reads them from the picture and the sound. - **The camera files.** Every card from the day. - **The sound files.** The recorder's files, one per take. - **The camera and sound reports.** Or a text file with scene, take, and which takes are circled. - **The frame rate.** The project's frame rate, as a whole number like 24, 25 or 30. `new_timeline` and `invideo edit new --fps` take whole numbers, so a 23.976 project runs at 24 here and conforms in the NLE. - **Your editing app.** Premiere Pro, DaVinci Resolve or Final Cut Pro. #### Steps The agent works on one timeline for the day, then copies it per scene. The agent uploads in three calls. 1. It makes the timeline with `new_timeline` at the project's frame rate. 2. For each large file, it calls `start_upload` and PUTs the bytes to the `upload_url`. 3. It calls `add_media` with the `upload_id` and the timeline URL. Expected result: a sequence URL and a media bin id for every camera and sound file. The agent runs `media` with `video.frames` on the first seconds of each camera file to read the slate board. Where the board is not in frame, it reads the spoken slate from the transcript. Expected result: scene and take for every file. The agent finds the offset in two calls. 1. The agent prices `audio.transcript` with `dry_run` on the camera's own sound and on the recorder file, each by its sequence URL from `add_media`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. The same words in both give the offset. 2. It confirms the offset on the slate clap with `audio.waveform`, where the clap is the sharp peak in both files. Expected result: an offset in seconds for every take. The agent places each take's picture with `insert_media` in scene and take order, and its recorder sound on an audio track at the offset. It links them with `link_clips` and names each clip with `set_name`, like "12A-3". It sends a scene in one `edit_timeline` call. Expected result: synced takes in slate order, and a new `state_token`. The agent adds a marker on each circled take with `add_marker`, a color and a note from the camera report. It approves the circled takes in the notebook with `mark_sequence`, with the reason "circled". Expected result: markers on the timeline and approved takes in the notebook. The agent copies the day's timeline per scene with `duplicate_timeline`, and on each copy removes the other scenes' takes with `delete_clip` mode `close_gap`. For the selects reel, it makes one more copy and keeps only the circled takes. Expected result: a timeline per scene, and a selects timeline, each with its own `timeline_id`. The agent runs `capture` on a few takes per scene and listens for sync with `audio.waveform`. It runs `check_timeline`. Then it runs `export` with `format` set to `davinci`, `premiere` or `final_cut`, and `media_packaging` folder or zip. Expected result: an export card with status `completed` that lists the media zip. The same job from a terminal: ```bash invideo edit new --name "Day 04 dailies" --fps 25 invideo asset upload ./day-04/A-cam/* ./day-04/B-cam/* invideo asset upload ./day-04/sound/* invideo media video.frames --asset m3 --at 0,1,2 --out ./slates invideo media audio.transcript --dry-run invideo media audio.transcript --max-credits invideo media audio.waveform --asset m3 --limit 160 invideo edit change --timeline T1 --token \ --operations @scene-12.json invideo notebook mark --status accepted --reason "circled" invideo edit capture --timeline --at 2,40 invideo edit export --format davinci --media-packaging zip \ --idempotency-key day-04 --json invideo status --wait invideo notebook show --out ./day-04-resolve ``` Where the values come from: `` from `invideo project new`, and `` from `invideo edit new`. `` is the `url` that `invideo asset upload` returns for each file; `m3` is its bin id, which the reads that return at once, such as `video.frames` and `audio.waveform`, take with `--asset`. `` is the price the dry run returns, its `estimated_credits`. `` comes from `invideo edit show `, read again after each change. `` is the take's sequence URL. `` is the `timeline_id` that `duplicate_timeline` gives each scene copy. `` is `.sequences[0]` of the export answer. `invideo status` waits but does not download; `notebook show` with `--out` saves the files. When `status` says `completed`, the media zip can still be packing, so run `notebook show` again until the zip is in the folder. The file in `--operations @scene-12.json` is a bare list of ops, like the `operations` list below. The key MCP call lays one synced take and marks it. This fence is the full MCP `edit_timeline` call. The `at_f` values are frames at the timeline's frame rate, so the sound starts the offset earlier than the picture. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "insert_media", "asset": "m3", "track": "V1", "at_f": 4500, "ripple": true }, { "op": "insert_media", "asset": "m41", "track": "A1", "at_f": 4470, "ripple": true }, { "op": "add_marker", "at_f": 4500, "color": "#e53935", "name": "12A-3 circled", "note": "Best performance, soft focus end" } ] } ``` The agent reads the new clip ids with `get_timeline`, then sends `link_clips` and `set_name` in the next call. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** a transcript per file with `audio.transcript`. Skip it for takes with a clear slate clap, and the agent syncs them from `audio.waveform` alone. - **Free:** uploads, the timelines, markers, approvals, string-outs and the project export. `video.frames` and `audio.waveform` show their price in the dry run before anything starts. Uploading a day's cards takes the longest. The sync and the string-outs take the agent under an hour. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from takes with no clap, or files the agent could not name. | Symptom | Fix | | --- | --- | | A take is out of sync by a frame | Move the sound clip one frame with `move_clip`, then check the clap with `audio.waveform` again. | | A take has no slate clap | The agent syncs it on the transcript words alone. Check it by eye with `capture`. | | A file has no readable slate | The agent lists it for you. Tell it the scene and take. | | Takes are out of order | Give the agent the camera report. It reorders with `move_clip`. | | The project opens without media | It was exported with `none`. Export again with `folder` or `zip`. | | An upload by URL fails on a large file | Use `start_upload`, then `add_media` with the `upload_id`. | | The folder has the project file but no media | The zip was still packing. Run `invideo notebook show --out` again until the zip lands. | | `audio.transcript` is refused as `not_found` | It got a bin id like `m3`. Pass the file's sequence URL instead. | | CLI exit 7 | Nothing ran. Run the same command again. | | Avoid: approving takes the report does not circle | Instead: mark only what the report or the director says. | | Avoid: syncing by file time alone | Instead: confirm every take on the clap or the words. | #### Prompts to try Each prompt is a real variation of the job. ```text Sync the day's B-cam to the A-cam and the sound, stack them as separate video tracks per take, and make a string-out for scene 14 only. ``` ```text Make a selects reel of every circled take from days 1 to 4, in script order, with the slate name burned on each take. ``` ```text Find every take where the actor says "I never left". List them with scene, take and timecode, and mark them on the timeline. ``` #### When to use something else invideo syncs by sound and by the slate, not by timecode. For a shoot with jam-synced timecode on every camera and recorder, a sync by timecode in DaVinci Resolve or Premiere Pro is faster. For on-set color and dailies for everyone on set, use an on-set dailies tool such as DaVinci Resolve or Pomfort Silverstack. #### Related - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) - [Edit a documentary or interview from the transcript, with b-roll and lower thirds](/how-to/film/documentary-and-interview-edit) - [Color grade log footage and match shots](/how-to/film/color-grade-log-footage) - [Create a first cut from raw footage](/guides/how-to-create-a-first-cut-from-raw-footage-in-invideo-editor) - [Run invideo in CI and on servers](/how-to/ci-and-servers) ### Clean up the dialogue and keep the original Source: https://docs.invideo.io/how-to/film/dialogue-cleanup.md Noisy dialogue cleaned into a new file, placed beside the original so you can compare, then de-essed, EQ'd, compressed and checked for loudness. You get clean dialogue from noisy location sound, also called dialogue cleanup, noise reduction or audio repair. Your agent makes a cleaned copy of each voice file, places it beside the original on the timeline with the original muted, then evens out the voice with de-essing, EQ, compression and a limiter. The original file never changes, so you can switch back at any moment. Use invideo for this when you want to hear the clean and the original side by side in your edit: the clean is a new file, the original stays on its own muted track, and every audio effect is a setting you can change. #### Quickest path Set up your agent first with [invideo for AI agents](/agents). Then give it the timeline URL and this prompt. ```text The dialogue in scene 5 has traffic noise and hiss. Clean each voice file, keep the originals muted under the clean ones, then de-ess, EQ and compress the dialogue. Do not cut any words or pauses. Price the cleaning first and work on a branch. ``` In a chat app, you paste the timeline URL into the chat. In a terminal, you paste it into the prompt. #### What you need Clean sound starts with the best source. Give the agent the recorder files if you have them. - **The dialogue.** The timeline URL, or the sound files: the boom, the lavs, or the camera's sound. - **The problem.** Hiss, hum, traffic, wind, room echo, mouth clicks, harsh "s" sounds. - **What to keep.** Music or effects recorded under the voice, if any. - **The delivery.** The loudness target your platform or broadcaster publishes. Streaming services and broadcasters each state their own figure; the agent sets it with `target_lufs` on `export`. #### Steps The agent listens first, cleans into new files, and works on a branch. The agent creates a branch with `timeline_history`. On that branch it runs `media` with `audio.content` on each voice file to find the speech, `audio.loudness` for the level, and `audio.waveform` for the shape. Expected result: the files with the most noise, and where the speech is. The agent runs `media` with `audio.clean` on the voice file's sequence URL, from `add_media` or `invideo asset upload`. It runs `dry_run: true` first and tells you the price. For a price of 1 credit or more it waits for your yes. Then it runs it again with `max_credits` set to that price and an `idempotency_key`. On a sound file it uses the model `clean_voice.clean_audio`, and on a video file `clean_voice.clean_video`. It turns on noise removal, and leaves off the options that cut fillers or silences, so the timing stays the same. Both models take `keep_music`, so music under the voice can stay in the clean file. Expected result: a new sequence URL per file. The original file stays as it was. Where music or effects sit under the voice, the agent runs `media` with `audio.separate` on the file's sequence URL to split the sound into stems. It runs `dry_run: true` first and tells you the price. For a price of 1 credit or more it waits for your yes. Then it runs the paid call with `max_credits` set to that price and an `idempotency_key`. Expected result: a stem per part, with the voice on its own. The agent adds an audio track with `add_track`, reads its id with `get_timeline`, places each clean file at the same frame as its original with `insert_media`, and mutes the original clip with `set_audio_muted`. Expected result: the clean voice plays, and the original sits muted under it. The agent adds `click_remover`, `de_esser`, `eq` and `compressor` to the clean dialogue track with `add_audio_effect`. When several dialogue tracks share one chain, it creates a dialogue bus with `create_audio_bus`, routes the tracks to it with `set_audio_routing`, and puts the chain on the bus instead. In a second call, it sets each with `set_audio_effect_parameter`, by the effect ids `get_timeline` gives. It adds `limiter` to the timeline. Expected result: the effects in `get_timeline`, in that order. The agent runs `audio.loudness` on the clean files and compares them with the target. It checks each scene with `capture` and `check_timeline`. Expected result: voices at an even level. The agent runs `export` with `format` video and `target_lufs` set to the platform's target. For the dialogue alone, it exports with `mode` audio and `audio_format` wav. Expected result: an export card with status `completed`. The same job from a terminal: ```bash invideo branch new --name dialogue-clean --token invideo edit show invideo media audio.content --asset m2 invideo media audio.loudness --asset m2 invideo media audio.clean --dry-run \ --model clean_voice.clean_audio --inputs '{"remove_noise":true}' invideo media audio.clean --max-credits \ --model clean_voice.clean_audio --inputs '{"remove_noise":true}' \ --idempotency-key clean-m2 invideo status --wait invideo edit change --timeline T1 --token \ --operations @dialogue.json invideo media audio.loudness invideo edit export --format video --target-lufs -14 invideo edit export --format video --mode audio \ --audio-format wav ``` Where the values come from: `` from `invideo edit new`. `` comes from `invideo edit show` on the URL the next command runs on: `` for `branch new`, then ``, read fresh, because the main token is stale on the branch. `` is the `branch_url` that `branch new` returns. `` is the `url` that `invideo asset upload` returns for the voice file, and `m2` is its bin id, which the reads that return at once take with `--asset`. `` is the price the dry run returns, its `credits`. `` is the URL the paid `audio.clean` returns. The file in `--operations @dialogue.json` is a bare list of ops, like the `operations` list below. The key MCP calls place the clean voice, mute the original, and shape the voice. This is the MCP `edit_timeline` path, on the branch. The original dialogue sits on `A1`. The first call adds a track for the clean files. This fence is the bare list of ops, the same list `--operations @ops.json` takes. ```json [ { "op": "add_track", "name": "Clean voice", "kind": "audio" } ] ``` The agent reads the new track's id with `get_timeline`, `A4` here, then sends the next call. `c12` is the original dialogue clip on `A1`. This fence is the full MCP `edit_timeline` call. ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "insert_media", "asset": "", "track": "A4", "at_f": 1200, "ripple": false }, { "op": "set_audio_muted", "target": "c12", "muted": true }, { "op": "add_audio_effect", "target": "A4", "target_kind": "track", "effect": "de_esser" }, { "op": "add_audio_effect", "target": "A4", "target_kind": "track", "effect": "eq" }, { "op": "add_audio_effect", "target": "A4", "target_kind": "track", "effect": "compressor" } ] } ``` The audio effects get ids when this call lands. In a third call, the agent sets each one with `set_audio_effect_parameter` and the id from `get_timeline`. For the EQ, `band1` set to a high-pass at 80 Hz, `{"hp": 80}`, takes out rumble. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - **Costs credits:** each cleaned file from `audio.clean`, and each split from `audio.separate`. - **Free:** placing and muting, every audio effect, buses, and the exports. `audio.content`, `audio.loudness` and `audio.waveform` show their price in the dry run before anything starts. Cleaning a scene's files takes a few minutes. Setting the effects takes the agent a few minutes more. See [Credits and what they cost](/account/credits) for prices. #### If something goes wrong Most problems come from a clean file that no longer lines up, or effects pushed too hard. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | The clean file is shorter than the original | Fillers or long silences were removed. Clean again with those options off, so the timing matches. | | The clean voice sounds thin or watery | The cleaning went too far. Compare with the original, and keep the original where it sounds better. | | The voice is out of sync after placing | Place the clean file at the original clip's start frame, read with `get_timeline`. | | A voice is still loud and quiet by turns | Lower the compressor's `threshold` with `set_audio_effect_parameter`. | | The music must come out as its own stem | Run `media` with `audio.separate` on the file's sequence URL, with `dry_run: true` first, then `max_credits` and an `idempotency_key`. | | The "s" sounds are still harsh | Lower the `de_esser` `threshold`, or raise its `range`. | | Breathing and room noise got louder | The compressor is too strong. Raise its `threshold` or lower its `ratio`. | | The export peaks too high | Add `limiter` to the timeline and set its `ceiling`. | | `audio.clean` is refused as `not_found` | It got a bin id. Pass the voice file's sequence URL instead. | | CLI exit 2 on `-i` | `media` takes model inputs as `--inputs` with a JSON object, not `-i`. | | CLI exit 5 | A limit on credits or quota. Check the balance. | | Avoid: deleting the original sound | Instead: mute it with `set_audio_muted`. The clean is a new file, and you may want the original back. | | Avoid: cleaning with fillers or silences removed | Instead: keep the timing. Cut words on the timeline, where you can undo them. | #### Prompts to try Each prompt is a real variation of the job. ```text The lav on the actor in scene 9 has clothing rustle. Clean only that file, compare it with the boom, and use whichever sounds better per line. ``` ```text There is music on set under the dialogue at the party. Split the stems, keep the voice, and lay a clean music track from stock under it. ``` ```text Make a dialogue stem export at the broadcaster's loudness target in WAV for the sound mixer, with every audio effect on, and keep the originals muted in the project. ``` #### When to use something else invideo exports a stereo mix. For a 5.1 or Dolby Atmos mix, export the dialogue as WAV with `export` mode `audio`, or the project with `format` `premiere` or `davinci`, and mix in a DAW such as Pro Tools or the Fairlight page in DaVinci Resolve. For heavy repair, like a voice under a loud generator, use a repair tool such as iZotope RX, then bring the result back in with `add_media`. #### Related - [How can I make uneven dialogue levels more consistent?](/guides/how-can-i-make-uneven-dialogue-levels-more-consistent) - [How can I use EQ to reduce muddy or harsh dialogue?](/guides/how-can-i-use-eq-to-reduce-muddy-or-harsh-dialogue) - [How do I reduce harsh s sounds in dialogue?](/guides/how-do-i-reduce-harsh-s-sounds-in-dialogue) - [When to use a limiter rather than a compressor](/guides/when-should-i-use-a-limiter-rather-than-a-compressor) - [Use Claude Code as your film editor on an invideo timeline](/how-to/film/claude-code-as-film-editor) - [Check your video before you say it is done](/how-to/check-your-video) ## Developers ### Turn a CSV into many videos with a script Source: https://docs.invideo.io/how-to/developers/csv-to-videos.md Turn every row of a CSV into its own video with a bash loop over the invideo CLI: change the text from the row, export, and download, safe to rerun. Turn a spreadsheet into videos: one video per CSV row, personalized videos at volume, a batch render from a template. A bash loop reads each row, changes the template's text with the CLI, exports the video, and saves the file. The loop is safe to stop and rerun. It skips rows that are done, and a retried export never renders twice. Use invideo for this when a person designs the template in the editor and a script fills it in, and every video can still be opened and fixed by hand. #### Quickest path Set up the CLI first with [invideo for AI agents](/agents). Then give your coding agent this prompt. ```text Write a bash script that makes one invideo video per row of rows.csv from the template edit . Find the text clip ids with invideo edit show. Set the text from each row, export at 1080p, download to ./out, and skip rows that are done. Dry-run the first row. Run a few rows, show me, and wait for my yes. ``` This page is for a terminal. In a chat app, your agent can do a few rows with `duplicate_timeline`, `set_text` and `export`, but a script is the way for many rows. #### What you need The template is the work. The script is small. - A template edit in invideo, designed by a person: footage, music, logo, and text clips with placeholder words. - A CSV with a header row and one row per video. The script below expects no commas inside fields. - The CLI, signed in. See [Run invideo in CI and on servers](/how-to/ci-and-servers) for a machine with no browser. - `jq`, to build the operations and read the state token. #### Steps The agent sets up once, tests one row, then runs the loop. The agent runs `invideo agent register --name csv-batch` and sets `INVIDEO_AS=csv-batch` for the script. It sees the name in the project. The agent reads the template's `state_token` with `invideo edit show --json`, then runs `invideo branch new --name csv-batch --token `. It sees the branch's URL in `.branch_url`. The `url` key still names main, so the script uses `.branch_url`. The agent runs `invideo edit show --json` and notes the text clip ids, like `t1` and `t2`. It sees the ids and the branch's own `state_token`. The agent builds the `set_text` ops for row 1 and runs `invideo edit change` with `--dry-run`. Nothing is applied. It sees the ops checked. The agent runs the script on a small part of the CSV. Each row changes the text, saves a checkpoint, exports and saves the MP4. It sees one file and one `.done` file per row in `./out`, like `out/r1.mp4`. The agent runs `invideo edit capture` on the branch after a row, and you watch the first files. It sees the frames a viewer sees. The agent runs the rest of the CSV in parts, and you check each part before the next. It sees a `.done` file per finished row, so a rerun skips it. The script: ```bash #!/usr/bin/env bash # rows.csv: id,name,offer with a header row and no commas in fields set -u export INVIDEO_JSON=1 export INVIDEO_AS=csv-batch # the name from: invideo agent register EDIT="" # branch_url from: invideo branch new NAME=t1 # text clip ids from: invideo edit show "$EDIT" OFFER=t2 BATCH=$(date +%Y%m%d) mkdir -p out token() { invideo edit show "$EDIT" | jq -r .state_token; } change() { invideo edit change "$EDIT" --timeline T1 --token "$(token)" \ --operations @ops.json --wait } tail -n +2 rows.csv | while IFS=, read -r id name offer; do [ -f "out/$id.done" ] && continue jq -n --arg n "$name" --arg o "$offer" --arg a "$NAME" --arg b "$OFFER" \ '[{op:"set_text",clip:$a,text:$n},{op:"set_text",clip:$b,text:$o}]' \ > ops.json change; code=$? [ "$code" -eq 3 ] && { change; code=$?; } # stale token: read again case "$code" in 0) ;; 4|5|8|9) echo "stop at row $id, exit $code" >&2; exit "$code" ;; *) echo "skip row $id, exit $code" >&2; continue ;; esac invideo branch checkpoint "$EDIT" --title "row $id" --token "$(token)" ans=$(invideo edit export "$EDIT" --format video --quality 1080 \ --idempotency-key "csv-$BATCH-$id") || continue card=$(jq -r '.sequences[0]' <<<"$ans") invideo status "$card" --wait >/dev/null || continue invideo notebook show "$card" --out "out/$id" >/dev/null || continue [ -f "out/$id/export.mp4" ] || { echo "no file for row $id" >&2; continue; } mv "out/$id/export.mp4" "out/$id.mp4" && touch "out/$id.done" done ``` `` is the `branch_url` that `invideo branch new` returns. The clip ids `t1` and `t2` come from `invideo edit show `. In the steps, `` and `` are the template's project and timeline URLs, which the person gives you, and `` comes from `invideo edit show`. The ops for one row, as `jq` writes them. This is the bare list of ops that `--operations @ops.json` takes: ```json [ { "op": "set_text", "clip": "t1", "text": "Hi Maya" }, { "op": "set_text", "clip": "t2", "text": "Two for one in Pune this week" } ] ``` ##### What the script relies on Each line uses a flag from the command's `--help`. - `INVIDEO_JSON=1` makes every command return one JSON object, so `jq -r .state_token` reads the token. - `--wait` on any command retries when nothing ran, exit 7. It does not make `edit export` wait for the render. - The export answer's `.sequences[0]` is the card's URL. `invideo status --wait` waits for the render and saves nothing. - `invideo notebook show --out ` saves the file as `/export.mp4`. `--file-name` does not change that name, so the script renames it. - The script writes `.done` only when the MP4 is on disk, so a rerun redoes a row whose file is missing. - `--idempotency-key` makes a retried export find the first export instead of rendering again. ##### A timeline per row The script reuses one timeline, so each row's video lives in its export and its checkpoint. To keep an editable timeline per row, add a `duplicate_timeline` op per row, then read the copy's clip ids with `invideo edit show --timeline ` before `set_text`. Export it with `--timeline`. ##### Paid steps per row If each row needs its own voice or image, add an `invideo gen run` per row. The agent finds a model with `invideo gen models --query ""`, the CLI's `find_models`. A good pick for a voice is `seed_tts_2_0`. Your agent can search for others with `find_models`. It reads the inputs once with `invideo gen model`, and runs row 1 with `--dry-run`, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it passes `--max-credits` set to that price and an `--idempotency-key` on every row, so a rerun never pays twice. The paid line goes inside the loop, before `change`. ```bash invideo gen models --query "voice for a short greeting" invideo gen model --model seed_tts_2_0 invideo gen run --model seed_tts_2_0 --dry-run \ -i prompt="Hi Maya, this week only." -i voice_id= # inside the loop, per row: invideo gen run --model seed_tts_2_0 \ --max-credits --idempotency-key "voice-$BATCH-$id" \ -i prompt="Hi $name, this week only." -i voice_id= ``` `` is the template's project: its URL up to the project name, before `/tree/`. `` comes from `invideo library search` in `seed_tts_2_0_voices`; a voice id works only with its own model. `` is a notebook page in the project; `invideo notebook show ` lists them. `` is the price row 1's dry run gave. Each paid run returns a thread URL. The agent waits with `invideo status --wait`, then reads the voice's sequence URL with `invideo notebook show` before it places the voice. It never runs `gen run` again to check. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: every `edit change`, checkpoint and export in the script. - Costs credits: only what you add per row, like a voice with `invideo gen run`. Each row takes the time of one export. Run large CSVs in parts, and check each part. See [Credits](/account/credits) for prices. #### If something goes wrong The script reads the exit code of each command. These are the codes from `invideo help exit-codes`. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Exit 2 | The request cannot be done as asked. Check the ops with `--dry-run`. The refusal names the field to fix. | | Exit 3 | The edit changed since the read. The script reads the token again and retries once. | | Exit 4 | Not signed in. Run `invideo auth login`, or the device code login on a server. | | Exit 5 | Credits or quota ran out. The script stops. Rerun later; done rows are skipped. | | Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | Exit 7 | Nothing ran. `--wait` retries it. | | Exit 8 | The person must confirm in invideo. The script stops. | | Exit 9 | Run `invideo update`, then rerun. | | A row has no MP4 and no `.done` file | The export or the save failed. Rerun the script. It redoes only that row. | | Text overflows its box in the files | Fix the template in the editor, delete the `.done` files, then rerun the script. | | A name with a comma breaks the row | Parse the CSV with a CSV tool such as Miller (`mlr`) instead of `read`. | | Avoid: run the loop on main | Instead: branch the template first. | #### Prompts to try Each prompt is a real variation of this job. ```text Change the script to read rows.json instead of a CSV, one object per line, and add a city field to a third text clip. ``` ```text Add a voice per row with seed_tts_2_0 saying the name. Dry-run the first row and tell me the price per row before you run the rest. ``` ```text Make a 9:16 and a 16:9 file per row from two template timelines, T1 and T2, in the same edit. ``` #### When to use something else For a pure render API with no editor and no person in the loop, a JSON-to-video service such as Creatomate or Shotstack fits. invideo fits when a person designs and fixes the template in a real editor. #### Related - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [Run several agents and a person in one project](/how-to/developers/several-agents-one-project) - [CLI commands and flags](/reference/cli) - [Exit codes](/reference/exit-codes) - [Environment variables](/reference/environment) - [When to use Creatomate or Shotstack vs invideo](/compare/creatomate-shotstack) ### Run several agents and a person in one project Source: https://docs.invideo.io/how-to/developers/several-agents-one-project.md Run several AI agents and a person in one invideo project: each agent with its own name and branch, messages between them, and one shared brief. Run several agents in one video project: a multi-agent workflow, a team of agents, Claude Code and Codex side by side, with a person who reviews. Each agent registers its own name, works on its own branch, and talks to the others through messages. A shared brief holds the plan. The person watches every cursor in the editor and decides which branch wins. Use invideo for this when you want agents and people in the same project at the same time, with names on every change and branches that keep one agent's work from breaking another's. #### Quickest path Set up your agents first with [invideo for AI agents](/agents). Then give each one its part. This prompt is for the first agent. ```text In the invideo project , register as "cutter". Read the brief "Launch teaser". Make a branch called cutter and cut the teaser there. When the cut is ready, message the agent "sound" with the branch URL, and point at anything you want me to look at. ``` Each agent picks MCP or the CLI for its own session. Two agents can use different ones, but one agent never mixes them. #### What you need Plan the roles before the agents start. - One project URL that every agent and the person share. - A name per agent: short, lowercase, like `cutter`, `sound`, `captions`. - A brief with the plan, the roles and the rules. - The person who approves the final branch. #### Steps Every agent follows the same steps with its own name. Each agent calls `register` with the project URL and its name, and `model` if it knows it. It passes the name as `as` on every call after that. On the CLI it runs `invideo agent register` and sets `INVIDEO_AS`. It sees the agents already in the project. The first agent, or the person, makes the plan with `new_brief`. Every agent reads it with `read` before it starts, and changes one part with `edit`, which is safer than `write`. It sees the brief's markdown and its `revision`. Each agent calls `timeline_history` with `action: "create_branch"` and its name, and edits only that branch's URL. It sees its branch URL and a `state_token`. The agent sends each `edit_timeline` call with the latest `expected_state_token` from `get_timeline` on its branch. It sees a new `state_token` when its edit lands. An agent finds the others' URLs with `read` on the project's `…/agents`, or `invideo agent list`. It sends a message with `message`, using the other agent's URL. It reads answers with `inbox`, and replies to the `from.url` of a message. It sees its unread messages, oldest first. An agent calls `point_at` with clip ids or a time and a few words, like "new intro here". The person sees the cursor under the agent's name. When it is done, the agent calls `leave_timeline`. It sees its cursor go. The person compares the branches in the editor. The agent sets the chosen branch with `timeline_history` action `set_default` or `declare_final`, only when the person says so. It sees the branch list with the new default. The terminal version for one agent: ```bash export INVIDEO_AS=cutter invideo agent register --name cutter --model opus invideo project show invideo agent list invideo edit show invideo branch new --name cutter --token invideo edit show invideo edit change --timeline T1 --token \ --operations @cut.json invideo edit point --at 4 --text "new intro here" invideo agent message --text "Cut ready: " invideo agent inbox invideo edit leave ``` Where each value comes from: - `` comes from `invideo project new`, or the person gives it. `` comes from `invideo edit new`. - `` comes from `invideo edit show` on the URL the next command runs on. For `branch new` that is ``. For `edit change` it is ``, read fresh, because the main token is stale on the branch. - `` is the `branch_url` that `branch new` returns. - `@cut.json` names a file that holds a bare list of operations. `` is another agent's URL from `invideo agent list`. The MCP calls that differ from a single-agent job, as a list of tool calls, each with its tool name and its arguments. `` is the `sound` agent's URL from `read` on the project's `…/agents`. `` is the branch URL that `timeline_history` returns. `` comes from `list_projects`, or the person gives it. ```json [ { "tool": "register", "arguments": { "url": "", "name": "cutter", "model": "opus" } }, { "tool": "message", "arguments": { "url": "", "as": "cutter", "text": "Cut is ready on branch cutter: " } }, { "tool": "inbox", "arguments": { "url": "", "as": "cutter" } }, { "tool": "point_at", "arguments": { "url": "", "as": "cutter", "ids": ["c7"], "text": "new intro here" } } ] ``` ##### Branches do not merge `timeline_history` has no merge action. Plan the work so each agent owns a branch, or a timeline of its own. When one agent needs another's change, it reads that branch and repeats the change on its own branch with `edit_timeline`. Or the agents work one after another on one branch, and hand over with a message. ##### An agent that generates An agent can make media for its part, like a `sound` agent that makes a music bed. It follows the generation pattern on its own branch. 1. The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_music_v2_5_instrumental`. Your agent can search for others with `find_models`. 2. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. 3. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It gets a thread URL and, when the result lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. ```bash invideo gen models --query "calm instrumental music bed" invideo gen model --model elevenlabs_music_v2_5_instrumental invideo gen run --model elevenlabs_music_v2_5_instrumental \ --dry-run -i prompt="calm piano bed for a product teaser" invideo gen run --model elevenlabs_music_v2_5_instrumental \ -i prompt="calm piano bed for a product teaser" \ --max-credits --idempotency-key sound-bed-1 ``` `` is the shared project URL. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. ##### Messages to invideo agents cost credits A project can hold invideo's own agents, such as Agent Two, beside remote agents like Claude Code. A message to a remote agent is free. A message to an invideo agent runs it on the person's credits, so send one only when the person asks, or to answer a message from it. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. - Free: `register`, messages between remote agents, `inbox`, `point_at`, branches, edits and exports. - Costs credits: a message to an invideo agent, and any generation, transcript or stock an agent uses. Setup takes a few minutes per agent. See [Credits](/account/credits) for prices. #### If something goes wrong Most problems come from shared names and stale tokens. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | `register` refuses the name | The name is in use in this project. Pick another. | | A notice says you acted as a shared name | The call had no `as`. Pass your name on every call, or set `INVIDEO_AS`. | | An edit is refused as a conflict | Another edit landed first. Read with `get_timeline` and reconsider. Do not resend blindly. | | CLI exit 3 | The same conflict on the CLI. Run `invideo edit show` and rebuild. | | `timeout` or `completion_unknown` | Retry the identical request with the same token. A conflict then means it landed. | | No answer in the inbox | The other agent reads its inbox only when it runs. Check `inbox` again later. | | `write` on the brief is refused | It changed since your read. Read again, or change one part with `edit`. | | Avoid: two agents on one branch at once | Instead: one branch per agent, or take turns. | | Avoid: one agent mixes MCP and the CLI | Instead: pick one per session. | #### Prompts to try Each prompt is a real variation of this job. ```text Register as "captions". Wait for a message from "cutter" with a branch URL, then add captions on a branch called captions off that one. ``` ```text Register as "reviewer". Read every branch, capture frames at each scene, and message each agent a list of fixes with timecodes. Do not edit. ``` ```text Set up a brief for a three-agent ad edit: cutter, sound and captions, with each one's job and the order they work in. ``` #### When to use something else invideo does not run or schedule the agents. Start them in their own clients, or with an orchestrator such as your CI system or an agent framework. For one agent doing everything, the plain work loop on [invideo for AI agents](/agents) is simpler. #### Related - [invideo for AI agents](/agents) - [Turn a CSV into many videos with a script](/how-to/developers/csv-to-videos) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [MCP tools](/reference/mcp-tools) - [Environment variables](/reference/environment) ### Bring a Remotion Source: https://docs.invideo.io/how-to/developers/composition-to-timeline.md Your agent reads a Remotion, HyperFrames or Tesseract composition and rebuilds it as clips, text, shapes and keyframes you can move, trim and restyle. Turn a code composition into an editable timeline: convert a Remotion, HyperFrames or Tesseract project into tracks, clips and keyframes instead of one flat render. Your agent reads the source, a React component, an HTML page or a `.tsrct` project, and rebuilds each element with edit operations. You end up with a title you can retype, a logo you can move and a push-in you can retime by hand. Use invideo for this when the person who asks for changes does not write code, and you want them to drag a clip in the editor instead of asking for a new render. #### Quickest path Set up your agent with [invideo for AI agents](/agents) first. Then give it this prompt. ```text Read the composition in ./video and rebuild it on a new invideo timeline, one element per clip: text as text, images and video as clips, motion as keyframes. Match the size and fps. List any layer you cannot rebuild, and render only those as clips. Work on a branch and show me the timeline URL. ``` In a terminal, the agent reads the source folder and uploads the files itself. In a chat app, you drag the images, videos, fonts and source files into the chat, and the agent works from them there. #### What you need The source is the input, not the render. - The composition source: the Remotion project, the HyperFrames HTML, CSS and JavaScript, or the Tesseract project with its media. - Every file the composition uses: images, videos, audio and font files. - The size and frame rate of the composition. - A list of the layers that must stay editable, if not all of them. #### How each element maps The agent rebuilds each element with the op that matches it. Look up each op's fields with `timeline_catalog` before its first use. | In the composition | On the timeline | | --- | --- | | Size and frame rate | `set_timeline_settings` with `width`, `height` and `fps` | | Start and length | `start_f` and `end_f`, or `at_f` and `duration_f`, in frames at the timeline's rate | | Text | `add_text`, then `set_text_style` and `style_text_range` | | Fonts | `add_media` with the font file; its id goes in `font` | | Images and video | `add_media`, then `insert_media` or `place_media`, with `set_position` and `set_zoom` | | Rectangles, circles, SVG paths | `add_shape` with `preset` `rectangle`, `ellipse`, `star` or `path` | | Gradients and strokes | `set_shape_paint`, `add_shape_paint`, `set_shape_path_points` | | Position and scale over time | `add_keyframe_lane` on `position_x`, `position_y`, `zoom_x`, `zoom_y`, then `add_keyframes` | | Opacity and rotation over time | `set_keyframes` with `property` `opacity` or `rotation` | | Easing | `ease` on `set_keyframes`, or `set_keyframe_interpolation` on a lane's keyframe | | Path morphs | `animate_shape_path`, then `set_shape_path_points` at each time | | Layer order and blend | track order, `set_blend_mode`, `set_opacity` | | Transitions | `add_transition`, `add_edge_transition`, or `add_custom_transition` in GLSL | | A filter or shader | an effect from the catalog with `add_effect`, or `add_custom_effect` in GLSL | | Audio | `add_media`, then `place_media` on `A1`, `A2` or `A3` | | Canvas, WebGL, DOM tricks, third-party components | Render that layer alone and place it as a clip | Times convert one way. Set the timeline's `fps` to the composition's frame rate, and Remotion frame numbers copy over as they are. HyperFrames times are in seconds, in `data-start` and `data-duration`, so the agent multiplies them by the frame rate. In HyperFrames, CSS `z-index` sets which layer is on top, not `data-track-index`. #### Steps The agent works on a branch and checks the result before it says done. The agent reads the source and writes a list of elements, each with its start, length, position, style and motion. It sees which elements map to an op and which do not. The agent creates a branch with `timeline_history` and `action: "create_branch"`, then sends `set_timeline_settings` with the composition's size and frame rate. It sees a `branch_url` and a new `state_token`. The agent uploads each image, video, audio and font file with `start_upload` and `add_media` on the branch URL. It sees a media bin id for each, like `m1` and `m2`. The agent sends one `edit_timeline` call with the clips, text and shapes, in track order, plus a keyframe lane for each animated position or zoom. It sees the new clip ids and lane ids in `created`. The agent sends a second call with `add_keyframes` on each lane id, and `set_keyframe_interpolation` for the easing. It sees a new `state_token`. For each layer that does not map, the agent renders that layer alone in the source tool, uploads it, and places it on its track. It sees one clip per rendered layer. The agent calls `capture` at the same times as frames from the source tool's own render, compares them, and fixes what differs. It sees frames that match. The first call places a background video, a title that fades in, a logo, and two lanes for a push-in. This is the full MCP call: ```json { "url": "", "timeline_id": "T1", "expected_state_token": "", "operations": [ { "op": "set_timeline_settings", "timeline": "T1", "width": 1920, "height": 1080, "fps": 30 }, { "op": "insert_media", "asset": "m1", "track": "V1", "at_f": 0, "ripple": false }, { "op": "add_text", "track": "V3", "start_f": 15, "end_f": 90, "text": "Spring launch", "style": { "font_size": 96, "font_weight": 700, "color": "#ffffff" } }, { "op": "set_keyframes", "clip": "t1", "property": "opacity", "points": [ { "at_f": 15, "value": 0, "ease": "ease_out" }, { "at_f": 30, "value": 1 } ] }, { "op": "insert_media", "asset": "m2", "track": "V2", "at_f": 60, "ripple": false }, { "op": "set_position", "clip": "c2", "x": 0, "y": 300 }, { "op": "set_zoom", "clip": "c2", "x": 0.25, "y": 0.25 }, { "op": "add_keyframe_lane", "parent": "c1", "parent_kind": "video_clip", "property": "zoom_x", "default_value": 1 }, { "op": "add_keyframe_lane", "parent": "c1", "parent_kind": "video_clip", "property": "zoom_y", "default_value": 1 } ] } ``` `` is the `branch_url` that `timeline_history` returns. `` comes from `get_timeline` on that URL. `m1` and `m2` are the media bin ids that `add_media` returns for the background video and the logo. On a new timeline the clips are `c1`, `t1` and `c2`; on a timeline that already has clips, the agent reads the ids from `created`. The second call is the push-in. A lane id exists only after the first call lands, so the keyframes go in their own call. This is the bare list of ops that `--operations @ops.json` takes: ```json [ { "op": "add_keyframes", "lane": "", "points": [ { "time_seconds": 0, "value": 1 }, { "time_seconds": 4, "value": 1.15 } ] }, { "op": "add_keyframes", "lane": "", "points": [ { "time_seconds": 0, "value": 1 }, { "time_seconds": 4, "value": 1.15 } ] } ] ``` `` and `` are the `keyframe_lane` ids in `created` from the first call. The same zoom on both lanes keeps the picture's shape. The same job from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo branch new --name rebuild --token invideo asset upload ./video/public/bg.mp4 invideo asset upload ./video/public/logo.png invideo edit change --timeline T1 --token \ --operations @place.json --dry-run invideo edit change --timeline T1 --token \ --operations @place.json invideo edit change --timeline T1 --token \ --operations @motion.json invideo edit capture --at 1 --at 3 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is the timeline's URL. `` is the `branch_url` that `invideo branch new` returns. `` comes from `invideo edit show `, read again before each change. `place.json` holds the `operations` list of the first call, and `motion.json` the second list. #### Cost and time Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. A rebuild uses edit operations and uploads, so it spends no credits. A short title card takes a few minutes. A long composition with many layers takes longer, so the agent rebuilds it in parts. See [Credits](/account/credits). #### If something goes wrong Each refusal carries a `code` and a `message`. Read the `message`: it names the operation by its place in the list. | Symptom | Fix | | --- | --- | | `revision_conflict` | Someone's edit landed since the read. Read the timeline again, then send the call with the new `state_token`. | | `target_not_found` on `add_keyframes` | The lane id is wrong or from a dry run. Use the `keyframe_lane` id from `created` of the call that landed. | | `target_not_found` on `set_text_style` with `font` | The font is not in the media bin. Upload the font file with `add_media` on the timeline's URL, then use the id it returns. | | `target_not_found` on a clip id like `t1` | The project has clips already, so the new ids differ. Read them from `created`. | | `invalid_edit` on `add_edge_transition` | The clip is not first or last on its track. Use `add_transition` on the cut between two clips. | | `add_custom_effect` is refused with compiler errors | Fix the GLSL at the line and column the refusal lists. Read `timeline_catalog` with `guides` `custom_shader` first. | | A rendered layer shows a black or white box | Render that layer again with a transparent background, where the tool supports it, and check it with `capture`. | | The motion feels different from the source | Easing differs, such as a Remotion `spring`. Add more keyframes along the curve, or tune `set_keyframe_interpolation`. | | Avoid: render the whole composition to one MP4 | Instead: rebuild what maps, and render only the layers that do not. | | Avoid: edit main | Instead: rebuild on a branch from `timeline_history`, and give the person the branch URL. | #### Prompts to try Each prompt is a real variation of this job. ```text Rebuild the Remotion composition "Promo" from src/Root.tsx as an invideo timeline. Keep the headline and the price as editable text clips. ``` ```text Turn this HyperFrames index.html into an invideo timeline. Convert the GSAP tweens on position and scale into keyframe lanes. Render the canvas chart alone and place it as a clip. ``` ```text Read my Tesseract project and rebuild the title card and lower third on the invideo timeline, so my editor can change the names by hand. ``` #### When to use something else Keep rendering to MP4 when nobody will edit the elements, or when most of the composition is canvas, WebGL, physics or a third-party React component. Bring that render in as footage, as [Use Remotion with invideo](/integrations/remotion) shows. invideo does not run React, CSS or JavaScript, so arbitrary CSS layout, DOM behavior and live code do not translate. For a video made from data at volume, stay in the source tool and render there. #### Related - [Use Remotion with invideo](/integrations/remotion) - [Use HyperFrames with invideo](/integrations/hyperframes) - [Use Tesseract with invideo](/integrations/tesseract) - [Timeline edit operations](/reference/edit-operations) - [Make an intro, outro or logo animation](/how-to/creators/intro-outro-logo-animation) - [Check your video before you say it is done](/how-to/check-your-video) No. Your agent reads the source and sends edit operations. The timeline then holds real clips, text and keyframes that you edit like any other. Close, not exact. Position, zoom, opacity, rotation and timing match. Custom easing, filters and fonts that render differently can look slightly off, so the agent compares frames with `capture`. ## Reference ### CLI commands and flags Source: https://docs.invideo.io/reference/cli.md Every invideo CLI command, its flags and an example, from the live help, plus the help topics on arguments, URLs, output and waiting. The invideo CLI is one binary that drives invideo from a shell: it generates video, images, voice and music with `invideo gen`, edits timelines with `invideo edit`, and exports. Install it, sign in, and check who you are: ```bash curl -fsSL https://agents.invideo.io | sh invideo auth login invideo auth status ``` Every command has the same shape: `invideo [] [flags]`. The URL names what the command acts on, and every answer gives the URLs to use next. Run `invideo --help` for one command's flags, and `invideo help ` for a help topic. #### Rules for every command These rules hold on every command. Your agent keeps them and gets clean, repeatable runs. - **The URL is the handle.** Pass the URL of what you act on: a workspace, a project, a page, a sequence or an edit. Give the URLs you make to the person. Each one opens what it names in invideo. - **Ask for JSON.** Add `--json` to get the whole answer as one JSON object, `next` included. Set `INVIDEO_JSON=1` to do this on every command. - **Follow jobs with `--wait`.** A command that starts a generation, an export or an upload returns a URL at once. Run `invideo status --wait` to follow it until it is over. `status` does not download. - **Save files with `notebook show`.** Run `invideo notebook show --out ` on a sequence or an export card to save its file. - **Name yourself in a project.** Run `invideo agent register` once, then pass `--as ` on every command in that project, or set `INVIDEO_AS`. Every project command takes `--as`, so the tables below leave it out. - **Price before you pay.** Run a paid command with `--dry-run` first, then run it with `--max-credits`. These flags work on every command: | Flag | What it does | | --- | --- | | `--help` | Help for any command. | | `--json` | The answer as one JSON object on stdout, with `next`. | | `--tsv` | An answer's list as tab-separated rows under a header line. | | `--out ` | Saves files into the folder on the commands that save them: `invideo notebook show` (a sequence or an export card), and `invideo edit capture` and `invideo media video.frames` (frames). `invideo status` saves nothing, even with `--out`. | | `--wait` | Waits for a generation, an export or an upload to finish. | | `--timeout ` | Stops waiting after this many seconds. | The commands come in the order `invideo --help` lists them. #### auth The `auth` commands: sign in and out. ##### auth login Sign in, in the browser. It takes no flags of its own. ```bash invideo auth login ``` ##### auth logout Forget this machine's sign-in. It takes no flags of its own. ```bash invideo auth logout ``` ##### auth status Who you are signed in as. It takes no flags of its own. ```bash invideo auth status ``` #### workspace The `workspace` commands: your workspaces. ##### workspace list Your workspaces. It takes no flags of its own. ```bash invideo workspace list ``` #### project The `project` commands: list, create, show and rename projects. ##### project list Your projects, newest first. | Flag | Value | What it does | | --- | --- | --- | | `--offset` | integer | Where the page starts: the next_offset of the page before. | | `--query` | string | Only projects whose title contains this. | ```bash invideo project list [] --query teaser ``` ##### project new Start a project. | Flag | Value | What it does | | --- | --- | --- | | `--title` | string | Required. The project's name, as the person will see it, like "Product teaser". | ```bash invideo project new [] --title "Product teaser" ``` ##### project show A project: its notebook, context, briefs and newest files. It takes no flags of its own. ```bash invideo project show https://invideo.io/@acme/launch-reel ``` ##### project rename Rename what a URL names. | Flag | Value | What it does | | --- | --- | --- | | `--name` | string | Required. The new name, like "Take 3 · slower, warmer". | ```bash invideo project rename --name "Launch" ``` #### notebook The `notebook` commands: pages, threads and sequences. ##### notebook show A page, a thread or a sequence. It takes no flags of its own. ```bash invideo notebook show invideo notebook show --out ./out ``` On a sequence or an export card, `--out ` saves the file into the folder. An exported video saves as `export.mp4`, whatever `--file-name` the export had; rename it after. `` is `.sequences[0]` in the answer of `invideo edit export --json`. ##### notebook new-page A new notebook page. | Flag | Value | What it does | | --- | --- | --- | | `--title` | string | Required. The page's title, as the person will see it. | ```bash invideo notebook new-page --title "Ideas" ``` ##### notebook mark Approve or reject a sequence. | Flag | Value | What it does | | --- | --- | --- | | `--status` | string | Required. accepted approves it, rejected rejects it. One of `accepted`, `rejected`. | | `--reason` | string | Why, in a sentence the person sees beside the mark. | ```bash invideo notebook mark --status accepted --reason "best take" ``` #### context The `context` commands: the project's entries and briefs. ##### context show A context entry or a brief. It takes no flags of its own. ```bash invideo context show /context ``` ##### context write Replace a context entry or a brief. | Flag | Value | What it does | | --- | --- | --- | | `--markdown` | string | Required. All of it, as `invideo context show` shows it (`--markdown @entry.md`). | | `--description` | string | A context entry's line in the context's index; kept when left out. | | `--revision` | integer | The revision your latest read gave. | ```bash invideo context write --markdown @acme.md ``` ##### context edit Change part of a context entry or a brief. | Flag | Value | What it does | | --- | --- | --- | | `--new` | string | Required. What takes its place. | | `--old` | string | Required. The exact text to change, as `invideo context show` shows it. | | `--all` | | Changes every place it is. | ```bash invideo context edit --old "loud" --new "plain" ``` ##### context new-brief Start a brief. | Flag | Value | What it does | | --- | --- | --- | | `--description` | string | Required. What it is for, in a sentence or two. | | `--name` | string | Required. Its name, like "Launch teaser". | ```bash invideo context new-brief --name "Launch" \ --description "The launch teaser" ``` #### edit The `edit` commands: read, change, capture and export an edit. ##### edit new A new edit in a project. | Flag | Value | What it does | | --- | --- | --- | | `--fps` | integer | Frames per second (default 30). | | `--height` | integer | Height in pixels (default 1080). | | `--name` | string | The edit's name, from what it is for, like "Product teaser" (default "Timeline"). | | `--width` | integer | Width in pixels (default 1920). | ```bash invideo edit new --name "Teaser v1" ``` ##### edit change Change an edit: a list of operations, all or none. | Flag | Value | What it does | | --- | --- | --- | | `--operations` | list | Required. Operations, each an op and its fields, as a JSON list (`--operations @ops.json`). The file holds a bare list, `[ {...} ]`, with no `operations` wrapper. | | `--timeline` | string | Required. Which timeline to change, from `invideo edit show`. | | `--token` | string | Required. The state token from your latest read or change of this edit. | | `--dry-run` | | Checks the operations without applying them. | ```bash invideo edit change --timeline T1 --token … --operations @ops.json ``` `` comes from `invideo edit new`. The `--token` value is the `state_token` from `invideo edit show`, and each change returns a fresh one. ##### edit catalog The operations, effects and transitions an edit takes. | Flag | Value | What it does | | --- | --- | --- | | `--audio-effects` | list | Audio effect names whose settings to give. | | `--effects` | list | Effect names whose parameters to give. | | `--guides` | list | Guide names whose text to give, like custom_shader. | | `--ops` | list | Op names whose fields to give. | | `--transitions` | list | Transition names whose parameters to give. | ```bash invideo edit catalog --ops trim_clip,add_text ``` ##### edit export Render an edit to a file. | Flag | Value | What it does | | --- | --- | --- | | `--format` | string | Required. video renders a file; premiere, final_cut and davinci make a project file that Premiere Pro, Final Cut Pro or DaVinci Resolve opens; invideo makes an invideo project. One of `video`, `premiere`, `final_cut`, `davinci`, `invideo`. | | `--audio-format` | string | For video: the sound's format. One of `aac`, `opus`, `wav`. | | `--encode-quality` | string | For video: how hard the encoder works; best is slowest. One of `draft`, `good`, `best`. | | `--end` | number | For video: where it ends, in seconds. | | `--file-name` | string | For video: the file's name. | | `--fps` | number | For video: frames per second; the edit's own when left out. | | `--idempotency-key` | string | Any text unique to this export, like a UUID. | | `--media-packaging` | string | For premiere, final_cut and davinci: how the media comes with the project. One of `folder`, `zip`, `none`. | | `--mode` | string | For video: a video, its sound alone, or one still image. One of `video`, `audio`, `image`. | | `--quality` | string | For video: its height in pixels. One of `240`, `480`, `720`, `1080`. | | `--start` | number | For video: where it starts, in seconds (default 0). | | `--still-at` | number | With --mode image: the time of the still, in seconds. | | `--target-lufs` | number | For video: the loudness to normalize the sound to, in LUFS. | | `--timeline` | string | Which timeline in the edit to export, from `invideo edit show`. | ```bash invideo edit export --format video --quality 1080 --json invideo status --wait invideo notebook show --out ./out ``` The export returns an export card. `` is `.sequences[0]` in the JSON answer. `invideo status --wait` follows the card until it is over and saves nothing. `invideo notebook show` with `--out` saves the video as `export.mp4`; `--file-name` does not name the saved file. For `premiere`, `final_cut` and `davinci`, `completed` can arrive before the media package is ready: run `invideo notebook show` again until the files list is there. ##### edit leave Leave an edit (your cursor goes). It takes no flags of its own. ```bash invideo edit leave ``` ##### edit show An edit's tracks and clips, and its state token. | Flag | Value | What it does | | --- | --- | --- | | `--collection` | string | With --mode collection, the kind of object to list: timeline, track, clip, transition, gap, audio_track, audio_clip, audio_gap, asset, folder, font, lut, audio_bus, audio_effect, audio_send, marker, keyframe_lane, keyframe, motion_path_handle, guide, effect, shape_path, shape_paint, caption_slide, caption_sticker, color_mask, values. One of `timeline`, `track`, `clip`, `transition`, `gap`, `audio_track`, `audio_clip`, `audio_gap`, `asset`, `folder`, `font`, `lut`, `audio_bus`, `audio_effect`, `audio_send`, `marker`, `keyframe_lane`, `keyframe`, `motion_path_handle`, `guide`, `effect`, `shape_path`, `shape_paint`, `caption_slide`, `caption_sticker`, `color_mask`, `values`. | | `--end-seconds` | number | With --mode window: where the window ends. | | `--ids` | list | With --mode inspect: the ids to read. | | `--limit` | integer | The most objects on one page. | | `--mode` | string | overview lists the timelines; window reads tracks and the clips between --start-seconds and --end-seconds; collection lists one kind of object; inspect reads the objects named in --ids. One of `overview`, `inspect`, `window`, `collection`. | | `--offset` | integer | Where the page starts: the next_offset of the page before. | | `--parent-id` | string | With --mode collection: only objects that belong to this clip, track, timeline or keyframe lane. | | `--property-path` | string | With --collection values: where the list sits in the object, like /vertices. | | `--snapshot` | string | The snapshot the first page gave, for the pages after it. | | `--start-seconds` | number | With --mode window: where the window starts (default 0). | | `--timeline` | string | Which timeline in the edit, from `invideo edit show`. | ```bash invideo edit show ``` ##### edit inspect Objects of an edit by id, with every property you can change; a custom shader's source. | Flag | Value | What it does | | --- | --- | --- | | `--ids` | list | Required. The objects' ids, from `invideo edit show`. | | `--limit` | integer | The most objects on one page. | | `--offset` | integer | Where the page starts: the next_offset of the page before. | | `--snapshot` | string | The snapshot the first page gave, for the pages after it. | ```bash invideo edit inspect --ids c5,c7 ``` ##### edit check Check an edit for problems. It takes no flags of its own. ```bash invideo edit check ``` ##### edit capture Render frames of an edit as it looks now. | Flag | Value | What it does | | --- | --- | --- | | `--at` | list | Required. Times in the edit, in seconds, up to 12. | | `--timeline` | string | Which timeline in the edit, from `invideo edit show`. | ```bash invideo edit capture --at 1,3.5 --out ./frames ``` `--out ` saves the frames into the folder. ##### edit point Point at a time or clips, for people watching. | Flag | Value | What it does | | --- | --- | --- | | `--text` | string | Required. What to say beside your cursor, in about four words. | | `--at` | number | One time in the edit, in seconds. | | `--ids` | list | Up to 10 clip ids from `invideo edit show`. | | `--timeline` | string | Which timeline in the edit, from `invideo edit show`. | ```bash invideo edit point --at 4 --text "this cut" ``` #### branch The `branch` commands: an edit's checkpoints and branches. ##### branch list Branches and checkpoints, each branch with its URL. | Flag | Value | What it does | | --- | --- | --- | | `--limit` | integer | The most checkpoints on one page. | | `--offset` | integer | Where the page of checkpoints starts. | | `--snapshot` | string | The snapshot the first page gave. | ```bash invideo branch list ``` ##### branch checkpoint Save a checkpoint on a branch; returns the edits it saved. | Flag | Value | What it does | | --- | --- | --- | | `--title` | string | Required. A short title for the checkpoint. | | `--token` | string | Required. The state token from your latest read or change of this edit. | | `--message` | string | A longer note on what changed. | ```bash invideo branch checkpoint --title "rough cut" --token … ``` ##### branch restore Restore a branch to a checkpoint; returns the edits it changed and the backup. | Flag | Value | What it does | | --- | --- | --- | | `--checkpoint` | string | Required. A checkpoint, as `invideo branch list` names it. | | `--token` | string | Required. The state token from your latest read or change of this edit. | ```bash invideo branch restore --checkpoint … --token … ``` ##### branch new Branch off now, or off a checkpoint with --checkpoint. | Flag | Value | What it does | | --- | --- | --- | | `--name` | string | Required. The new branch's name. | | `--token` | string | Required. The state token from your latest read or change of this edit. | | `--checkpoint` | string | A checkpoint, as `invideo branch list` names it. | ```bash invideo branch new --name tighter-intro --token … ``` The answer gives `branch_url`. Run every later `edit change`, `edit check`, `edit capture` and `edit export` on that ``, with a fresh token from `invideo edit show `. The main timeline's token is stale on the branch. ##### branch edit-from-here Open a checkpoint for editing on a branch of its own. | Flag | Value | What it does | | --- | --- | --- | | `--checkpoint` | string | Required. A checkpoint, as `invideo branch list` names it. | | `--token` | string | Required. The state token from your latest read or change of this edit. | ```bash invideo branch edit-from-here --checkpoint … --token … ``` ##### branch tag Tag a checkpoint. | Flag | Value | What it does | | --- | --- | --- | | `--checkpoint` | string | Required. A checkpoint, as `invideo branch list` names it. | | `--name` | string | Required. The tag's name. | | `--token` | string | Required. The state token from your latest read or change of this edit. | ```bash invideo branch tag --checkpoint … --name v1 --token … ``` ##### branch rename Rename a branch. | Flag | Value | What it does | | --- | --- | --- | | `--name` | string | Required. The branch's new name. | | `--token` | string | Required. The state token from your latest read or change of this edit. | ```bash invideo branch rename --name final --token … ``` ##### branch archive Close a branch to edits; it keeps its history. | Flag | Value | What it does | | --- | --- | --- | | `--token` | string | Required. The state token from your latest read or change of this edit. | ```bash invideo branch archive --token … ``` ##### branch unarchive Open an archived branch again. It takes no flags of its own. ```bash invideo branch unarchive ``` ##### branch default Make a branch the default. | Flag | Value | What it does | | --- | --- | --- | | `--token` | string | Required. The state token from your latest read or change of this edit. | ```bash invideo branch default --token … ``` ##### branch final Declare a branch final. | Flag | Value | What it does | | --- | --- | --- | | `--token` | string | Required. The state token from your latest read or change of this edit. | ```bash invideo branch final --token … ``` #### asset The `asset` commands: the project's files: upload and add. ##### asset upload Upload local files into a project. | Flag | Value | What it does | | --- | --- | --- | | `--timeline` | string | With an edit's URL: which timeline's media bin, from `invideo edit show`. | ```bash invideo asset upload ./shots/*.mp4 ``` ##### asset add Bring in media from a link or the stock library. | Flag | Value | What it does | | --- | --- | --- | | `--file-name` | string | The file's name with its extension, to name it by. | | `--media-url` | string | A public http(s) link to the file; a file's URL from the project's …/assets; or a sequence's or font's URL (with an edit's URL). | | `--mime-type` | string | The file's media type, like video/mp4. | | `--stock` | string | A stock result's id from `invideo library search`, with the project's URL. | | `--timeline` | string | With an edit's URL: which timeline's media bin, from `invideo edit show`. | ```bash invideo asset add --media-url https://…/clip.mp4 ``` ##### asset show A project's files, a folder or a file. It takes no flags of its own. ```bash invideo asset show /assets ``` #### media Each `media` subcommand works on one file: a sequence URL, a file under the project's `…/assets`, or, for reads, a bin asset with `--asset`. Reads are free and return at once. `audio.transcript` and the model ops cost credits, so run them with `--dry-run` first. The tool ops, such as `video.trim` and `image.crop`, make a new file without a model. The dry run shows its price before anything starts. `--asset` works on the reads only: `metadata`, `video.frames`, `audio.waveform`, `audio.loudness`, `audio.content`, `audio.onsets`, `audio.markers`, `audio.key`, `audio.sections` and `audio.beats`. Every op that costs credits or makes a file refuses `--asset` with `not_found`. Pass the file's sequence URL (`…/notebook/seq-N.M`) instead. `invideo asset upload` and `invideo asset add` return that URL. In the examples, `` is the `estimated_credits` from the same command run with `--dry-run`. The examples below come from each command's help. Where a table marks a flag as required, add it to the example before you run it. Most `media` subcommands also take some of these shared flags. Each subcommand below names the ones it takes. | Flag | What it does | | --- | --- | | `--asset` | A file in the edit's media bin, by its id from `invideo edit show`. Reads only. | | `--stock` | A stock result's id from `invideo library search`, with the project's URL. | | `--dry-run` | Prices it; nothing starts. | | `--idempotency-key` | Any text unique to this one, like a UUID. | | `--max-credits` | The most it may cost, in the person's credits: nothing starts when it is higher. | ##### media metadata What a file is: streams, duration, size. Shared flags: `--asset`, `--stock`. ```bash invideo media metadata ``` ##### media video.frames Frames of a file at times in it. | Flag | Value | What it does | | --- | --- | --- | | `--at` | list | Required. Times in the file, in seconds, up to 12. | Shared flags: `--asset`, `--stock`. ```bash invideo media video.frames --at 0,2,4 --out ./frames ``` ##### media audio.waveform A file's audio levels. | Flag | Value | What it does | | --- | --- | --- | | `--limit` | integer | The most points, 16 a second (default 256). | | `--offset` | integer | The first point, counted in points (16 a second) from the start. | Shared flags: `--asset`, `--stock`. ```bash invideo media audio.waveform ``` ##### media audio.loudness A file's loudness: integrated, true peak, range. Shared flags: `--asset`, `--stock`. ```bash invideo media audio.loudness ``` ##### media audio.content Where a file's sound is speech, music, effects or silence. | Flag | Value | What it does | | --- | --- | --- | | `--limit` | integer | The most spans (default 256). | | `--offset` | integer | The first span, counted from the start. | Shared flags: `--asset`, `--stock`. ```bash invideo media audio.content ``` ##### media audio.onsets Where each hit or transient in a file starts and peaks. | Flag | Value | What it does | | --- | --- | --- | | `--limit` | integer | The most onsets (default 256). | | `--offset` | integer | The first onset, counted from the start. | Shared flags: `--asset`, `--stock`. ```bash invideo media audio.onsets ``` ##### media audio.markers A file's tempo and musical markers. | Flag | Value | What it does | | --- | --- | --- | | `--limit` | integer | The most markers (default 256). | | `--offset` | integer | The first marker, counted from the start. | Shared flags: `--asset`, `--stock`. ```bash invideo media audio.markers ``` ##### media audio.key A file's musical key. Shared flags: `--asset`, `--stock`. ```bash invideo media audio.key ``` ##### media audio.sections A file's musical structure, coarse to fine. Shared flags: `--asset`, `--stock`. ```bash invideo media audio.sections ``` ##### media audio.beats Where a file's strong and weak beats fall. | Flag | Value | What it does | | --- | --- | --- | | `--end-seconds` | number | Only beats by this time in the file, in seconds. | | `--limit` | integer | The most beats (default 256). | | `--offset` | integer | The first beat, counted from the start of the file or of the window --start-seconds and --end-seconds make. | | `--start-seconds` | number | Only beats at or after this time in the file, in seconds. | Shared flags: `--asset`, `--stock`. ```bash invideo media audio.beats ``` ##### media audio.transcript Every word said in a file, with its time and speaker. | Flag | Value | What it does | | --- | --- | --- | | `--end-seconds` | number | Only words that end by this time in the file, in seconds. | | `--limit` | integer | The most words (default 256). | | `--max-credits` | number | The most starting it may cost, in the person's credits: nothing starts when it is higher. | | `--offset` | integer | The first word, counted from the start of the file or of the window --start-seconds and --end-seconds make. | | `--start-seconds` | number | Only words that start at or after this time in the file, in seconds. | Shared flags: `--asset`, `--dry-run`, `--stock`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media audio.transcript --max-credits ``` ##### media document.pages An image sequence of each page of a PDF or deck. | Flag | Value | What it does | | --- | --- | --- | | `--to` | string | A page's or thread's URL to put the pages on. | ```bash invideo media document.pages ``` `` is the URL that `invideo asset upload` returns for the PDF or deck. ##### media audio.separate Split a file's sound into its stems. | Flag | Value | What it does | | --- | --- | --- | | `--inputs` | object | The model's own extras, as `invideo gen model` lists them: -i key=value, or --input inputs.json. | | `--model` | string | Which model runs it, one of: audio_separation. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media audio.separate --max-credits ``` ##### media audio.clean Clean the voice in a file. | Flag | Value | What it does | | --- | --- | --- | | `--inputs` | object | The model's own extras, as `invideo gen model` lists them: -i key=value, or --input inputs.json. | | `--model` | string | Which model runs it, one of: clean_voice.clean_audio, clean_voice.clean_video. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media audio.clean --max-credits ``` ##### media video.upscale Upscale a video. | Flag | Value | What it does | | --- | --- | --- | | `--inputs` | object | The model's own extras, as `invideo gen model` lists them: -i key=value, or --input inputs.json. | | `--model` | string | Which model runs it, one of: topaz_proteus_natural, pixverse_upscale, topaz_video_upscale, seedvr_video_upscale, flashvsr_video_upscale, bytedance_video_upscale, byteplus_vod_upscale, flux_3_video_upscale, topaz_astra_2, topaz_starlight_precise_26, topaz_gaia_2_animation. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.upscale --max-credits ``` ##### media image.upscale Upscale an image. | Flag | Value | What it does | | --- | --- | --- | | `--inputs` | object | The model's own extras, as `invideo gen model` lists them: -i key=value, or --input inputs.json. | | `--model` | string | Which model runs it, one of: clarity_upscaler, crystal_upscaler, topaz_bloom_2, magnific_upscaler_creative, magnific_upscaler_precision_v2, pruna_p_image_upscale, byteplus_ultra_hd. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media image.upscale --max-credits ``` ##### media video.removeBackground Remove a video's background. | Flag | Value | What it does | | --- | --- | --- | | `--inputs` | object | The model's own extras, as `invideo gen model` lists them: -i key=value, or --input inputs.json. | | `--model` | string | Which model runs it, one of: bria_video_bg_remove, veed_video_bg_remove.veed_bg_standard, veed_video_bg_remove.veed_bg_fast, pixelcut_video_bg_remove, ben_v2_video_bg_remove. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.removeBackground --max-credits ``` ##### media image.removeBackground Remove an image's background. | Flag | Value | What it does | | --- | --- | --- | | `--inputs` | object | The model's own extras, as `invideo gen model` lists them: -i key=value, or --input inputs.json. | | `--model` | string | Which model runs it, one of: bria_bg_remove, birefnet_bg_remove. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media image.removeBackground --max-credits ``` ##### media video.trim Trim a video to a time range. | Flag | Value | What it does | | --- | --- | --- | | `--end-time` | number | Required. End Time (s). | | `--start-time` | number | Required. Start Time (s). | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.trim ``` ##### media video.reverse Play a video backwards. Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.reverse ``` ##### media video.changeSpeed Speed up or slow down a video, or ramp its speed. | Flag | Value | What it does | | --- | --- | --- | | `--start-speed` | number | Required. Start Speed. | | `--end-speed` | number | End Speed. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.changeSpeed ``` ##### media video.stitch Join videos of the same aspect ratio into one. | Flag | Value | What it does | | --- | --- | --- | | `--video-array` | list | Required. Videos. | | `--aspect-ratio` | string | Aspect Ratio. | Shared flags: `--dry-run`, `--idempotency-key`, `--max-credits`. ```bash invideo media video.stitch ``` ##### media video.sceneSplit Split a video into its scenes. | Flag | Value | What it does | | --- | --- | --- | | `--threshold` | number | Threshold. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.sceneSplit ``` ##### media video.loop Loop a video to a target length. | Flag | Value | What it does | | --- | --- | --- | | `--target-duration` | number | Required. Target Duration (s). | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.loop ``` ##### media video.extractFrameFirst A video's first frame, as an image. Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.extractFrameFirst ``` ##### media video.extractFrameLast A video's last frame, as an image. Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.extractFrameLast ``` ##### media video.extractFrameByNumber One frame of a video by its number, as an image. | Flag | Value | What it does | | --- | --- | --- | | `--frame-number` | number | Required. Frame Number. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.extractFrameByNumber ``` ##### media video.extractFrameAtTime The frame of a video at a time, as an image. | Flag | Value | What it does | | --- | --- | --- | | `--time-seconds` | number | Required. Time (seconds). | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.extractFrameAtTime ``` ##### media video.extractFrameInterval Every Nth frame of a video, as images. | Flag | Value | What it does | | --- | --- | --- | | `--frame-interval` | number | Required. Frame Interval. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.extractFrameInterval ``` ##### media video.extractMsInterval A frame of a video every N milliseconds, as images. | Flag | Value | What it does | | --- | --- | --- | | `--interval-ms` | number | Required. Interval (ms). | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.extractMsInterval ``` ##### media video.replaceAudio Replace a video's sound with an audio file. | Flag | Value | What it does | | --- | --- | --- | | `--audio-input` | string | Required. Audio Input. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.replaceAudio ``` ##### media video.addAudioTrack Mix an audio file into a video's sound. | Flag | Value | What it does | | --- | --- | --- | | `--audio-input` | string | Required. Audio Input. | | `--volume` | number | Volume. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.addAudioTrack ``` ##### media video.resize A video as MP4 at a target height. | Flag | Value | What it does | | --- | --- | --- | | `--resolution` | string | Required. Resolution (height). | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.resize ``` ##### media audio.toVideo An audio file as a video with a blank picture. | Flag | Value | What it does | | --- | --- | --- | | `--aspect-ratio` | string | Aspect Ratio. | | `--fps` | number | FPS. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media audio.toVideo ``` ##### media video.contactSheet One image of frames across a video, in a grid. | Flag | Value | What it does | | --- | --- | --- | | `--columns` | integer | Required. Columns. | | `--resolution` | string | Required. Resolution (height). | | `--rows` | integer | Required. Rows. | | `--style` | string | Required. Style. | | `--start-offset-ms` | integer | Start offset (ms). | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media video.contactSheet ``` ##### media audio.trim Trim an audio file to a time range. | Flag | Value | What it does | | --- | --- | --- | | `--end-time` | number | Required. End Time (s). | | `--start-time` | number | Required. Start Time (s). | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media audio.trim ``` ##### media audio.extract A video's sound, as an audio file. | Flag | Value | What it does | | --- | --- | --- | | `--format` | string | Format. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media audio.extract ``` ##### media audio.concat Join audio files into one. | Flag | Value | What it does | | --- | --- | --- | | `--audio-array` | list | Required. Audio Files. | | `--gap-duration` | number | Gap Duration (s). | Shared flags: `--dry-run`, `--idempotency-key`, `--max-credits`. ```bash invideo media audio.concat ``` ##### media audio.addAudioTrack Mix an audio file over another. | Flag | Value | What it does | | --- | --- | --- | | `--overlay-audio-input` | string | Required. Overlay Audio. | | `--start-time` | number | Start Time (s). | | `--volume` | number | Volume. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media audio.addAudioTrack ``` ##### media image.collage Combine images into one collage. | Flag | Value | What it does | | --- | --- | --- | | `--image-array` | list | Required. Images. | | `--aspect-ratio` | string | Aspect Ratio. | Shared flags: `--dry-run`, `--idempotency-key`, `--max-credits`. ```bash invideo media image.collage ``` ##### media image.crop Crop an image. | Flag | Value | What it does | | --- | --- | --- | | `--h` | number | Required. Height. | | `--w` | number | Required. Width. | | `--x` | number | Required. X Position. | | `--y` | number | Required. Y Position. | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media image.crop ``` ##### media image.resizeAspectRatio Resize an image to an aspect ratio. | Flag | Value | What it does | | --- | --- | --- | | `--aspect-ratio` | string | Aspect Ratio. | | `--max-height` | number | Max Height (px). | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media image.resizeAspectRatio ``` ##### media image.resizeFit Resize an image to fit a width and height. | Flag | Value | What it does | | --- | --- | --- | | `--max-height` | number | Required. Max Height (px). | | `--max-width` | number | Required. Max Width (px). | Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media image.resizeFit ``` ##### media image.rotate Rotate an image. Shared flags: `--asset`, `--dry-run`, `--idempotency-key`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media image.rotate ``` ##### media describe What a video holds, from invideo's media understanding: a summary, chapters and captions. It spends credits, so price it with `--dry-run` first. | Flag | Value | What it does | | --- | --- | --- | | `--start-seconds` | number | Only captions that start at or after this time in the file, in seconds. | | `--end-seconds` | number | Only captions that end by this time in the file, in seconds. | | `--limit` | integer | The most captions (default 256). | | `--offset` | integer | The first caption, counted from the start of the file or of the window the two time flags make. | Shared flags: `--asset`, `--dry-run`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media describe --max-credits ``` ##### media ask A question about a stretch of a video, answered by invideo's media understanding. The stretch is at most a minute long. It spends credits, so price it with `--dry-run` first. | Flag | Value | What it does | | --- | --- | --- | | `--question` | string | Required. What to answer about the stretch. | | `--start-seconds` | number | Required. Where the stretch starts in the file, in seconds. | | `--end-seconds` | number | Required. Where the stretch ends, at most 60 seconds after the start. | Shared flags: `--asset`, `--dry-run`, `--max-credits`. Here `--asset` is refused: pass the file's sequence URL. ```bash invideo media ask --start-seconds 120 --end-seconds 150 \ --question "When is the goal scored?" --max-credits ``` #### gen The `gen` commands: generate with a model. ##### gen models Models you can generate with. | Flag | Value | What it does | | --- | --- | --- | | `--output` | string | Only models that make this. One of `video`, `image`, `audio`, `three_d`. | | `--query` | string | What to generate or a model's name, like "lip sync" or "seedance". | ```bash invideo gen models --query "video" ``` ##### gen model One model and its inputs. | Flag | Value | What it does | | --- | --- | --- | | `--model` | string | Required. A model id from `invideo gen models`, as `invideo gen run` takes it. | ```bash invideo gen model --model seedance_2_5.r2v ``` ##### gen run Generate with a model; its inputs go as -i key=value. | Flag | Value | What it does | | --- | --- | --- | | `--model` | string | Required. A model id from `invideo gen models`. | | `--dry-run` | | Prices it and checks the inputs; nothing starts. | | `--idempotency-key` | string | Any text unique to this generation, like a UUID. | | `--inputs` | object | The model's inputs, as `invideo gen model` lists them: each as -i key=value (`-i prompt=@prompt.txt` reads a file), or all of them as JSON with --input inputs.json. | | `--max-credits` | number | The most the estimate may be, in the person's credits: nothing starts when it is higher. | ```bash invideo gen run --model seedance_2_5.r2v --dry-run \ -i prompt="slow push on the bottle" invideo gen run --model seedance_2_5.r2v \ --max-credits --idempotency-key shot-1 \ -i prompt="slow push on the bottle" ``` `` is the `estimated_credits` in the dry run's answer. Pass the same inputs, the same way, on both runs. The paid run returns a thread URL; follow it with `invideo status --wait`, then save the result with `invideo notebook show --out `. `` comes from `invideo notebook new-page`. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. #### export The `export` commands: export pages. ##### export add Add sequences to an export page. | Flag | Value | What it does | | --- | --- | --- | | `--urls` | list | Required. Sequence and edit URLs of the project. | | `--kind` | string | A new page's layout (default playlist). One of `playlist`, `canvas`, `doc`. | | `--page` | string | An export page's URL, to add to it; leave it out for a new page. | | `--title` | string | A new page's title. | ```bash invideo export add --urls , ``` ##### export edit Reorder, retitle or trim an export page. | Flag | Value | What it does | | --- | --- | --- | | `--order` | list | A playlist page's object ids in the order to show them. | | `--remove` | list | Object ids to take off the page. | | `--title` | string | The page's new title. | ```bash invideo export edit --title "Final cuts" ``` ##### export share Share an export page. | Flag | Value | What it does | | --- | --- | --- | | `--permissions` | object | For each visibility, whether people may comment and download, all three together, as one JSON object with `public`, `shared` and `private` keys, each holding `comment` and `download` booleans. | | `--team-access` | string | What the workspace may do with the page. One of `view`, `comment`, `edit`. | | `--visibility` | string | public: anyone with its URL; shared: the workspace; private: only you. One of `public`, `shared`, `private`. | ```bash invideo export share --visibility public ``` #### agent The `agent` commands: agents in a project and their messages. ##### agent list Every agent in a project. It takes no flags of its own. ```bash invideo agent list ``` ##### agent register Take a name in a project; pass it as `--as ` after. | Flag | Value | What it does | | --- | --- | --- | | `--name` | string | Required. Your name: up to 24 lowercase letters, digits, - and _, like scout. | | `--model` | string | The model you run on, if you know it, like opus. | ```bash invideo agent register --name scout ``` ##### agent message Message an agent; its answer comes to your inbox. | Flag | Value | What it does | | --- | --- | --- | | `--text` | string | Required. The message, in plain words. | ```bash invideo agent message --text "trim the intro?" --as scout ``` ##### agent inbox Your unread messages. | Flag | Value | What it does | | --- | --- | --- | | `--before` | integer | A message id from an earlier inbox: the messages before it. | ```bash invideo agent inbox --as scout ``` #### library The `library` commands: search stock video, images, music and voices. ##### library search Search a stock library. | Flag | Value | What it does | | --- | --- | --- | | `--library` | string | Required. `_voices`, stock_video, stock_image or stock_music. | | `--cursor` | string | Voices only: the cursor the last answer gave, for its next page. | | `--query` | string | What to find, like "aerial city at night". | ```bash invideo library search --library stock_video \ --query "city at night" ``` #### status Where generations, exports and uploads stand; --wait follows them until over. It takes several URLs at once, from any of your projects. It has no flags of its own: add `--wait` to follow the jobs until they are over. ```bash invideo status --wait ``` #### feedback The `feedback` commands: report a bug or ask for a feature. ##### feedback bug Tell invideo something broke. | Flag | Value | What it does | | --- | --- | --- | | `--summary` | string | Required. One line: what went wrong. | | `--what-happened` | string | Required. The command you ran, its arguments, and the full answer. | | `--expected` | string | What you expected instead. | | `--kind` | string | broken, confusing or wrong_result. One of `broken`, `confusing`, `wrong_result`. | | `--tool` | string | The command it happened with. | ```bash invideo feedback bug --summary "…" --what-happened "…" ``` ##### feedback feature Ask invideo for something. | Flag | Value | What it does | | --- | --- | --- | | `--summary` | string | Required. One line: what is needed. | | `--details` | string | What you were trying to make, and why this was needed. | | `--workaround` | string | What you did instead, if anything. | ```bash invideo feedback feature --summary "…" ``` #### update Update invideo to its latest release. It updates an install from the script. With Homebrew, it says what to run instead (`brew upgrade invideo`). It takes no flags. ```bash invideo update ``` #### Help topics The CLI has five help topics. `invideo help exit-codes` has its own page, [Exit codes](/reference/exit-codes). The other four follow, in plain words. ##### arguments A command's arguments are flags. Write a flag as `--name value` or `--name=value`. - A true-or-false flag, like `--dry-run`, takes no value. `--dry-run=false` turns it off. - A list repeats its flag (`--at 1 --at 3.5`), or takes commas (`--at 1,3.5`), or takes JSON. - An object, like `--permissions`, takes JSON. - `@path` reads a value from a file, like `--operations @ops.json`. A `-` reads it from stdin. - `--input payload.json` gives the whole payload as one JSON object. Flags you add go on top of it. On `invideo gen run`, the file holds the bare inputs that `invideo gen model` lists, with no `inputs` wrapper. A model's own inputs go with `-i`, one each, so they never clash with the command's flags. Run `invideo gen model --model ` to list a model's inputs. ```bash invideo gen run --model seedance_2_5.r2v \ -i prompt="slow push" -i duration=5 ``` ##### urls A URL is the handle. Every command takes the URL of what it acts on, and every answer gives the URLs to use next. A project's URL names its notebook. Under it sit the notebook pages (`…/notebook/`), threads and sequences, the edits, the context and its entries (`…/context`), the files (`…/assets`), and the agents (`…/agents`). Give the person the URLs you make. Each one opens what it names. ##### output An answer is indented `key: value` text. What to do next comes after it. The text is the same on a terminal and in a pipe, so an agent reads it as a person does. - `--json` prints the whole answer as one JSON object, `next` included, for `jq`. `INVIDEO_JSON=1` does this on every command. - `--tsv` prints an answer's list as tab-separated rows under a header line. Its other fields and what to do next go to stderr, so `grep`, `cut` and `awk` read the rows. - Errors and notices always go to stderr. ```bash invideo branch list --tsv | cut -f2 ``` ##### waiting A command that starts something (a generation, an export or an upload) returns the URL to follow at once. Run `invideo status --wait` to check back until the job is over. It follows jobs in any of your projects. `--timeout ` stops the wait after that many seconds. With `--wait`, any command also tries again when nothing ran (exit code 7). A retry is the same request, so it never starts anything twice. ```bash invideo status --wait ``` #### Related - [Exit codes](/reference/exit-codes) - [Environment variables](/reference/environment) - [MCP tools](/reference/mcp-tools) - [Timeline edit operations](/reference/edit-operations) - [Models](/reference/models) ### Timeline edit operations Source: https://docs.invideo.io/reference/edit-operations.md Every edit_timeline operation by job, with its required fields, the time unit rules, and runnable operations lists. Your agent edits a timeline with one tool, `edit_timeline`. It sends a list of operations, and each operation is an `op` and its fields. The CLI sends the same list with `invideo edit change`. This is the full MCP `edit_timeline` call: ```json { "url": "https://invideo.io/@acme/launch-reel/tree/main/seq-9.1", "timeline_id": "T1", "expected_state_token": "", "dry_run": true, "operations": [ { "op": "split_clip", "clip": "c7", "at_f": 90 } ] } ``` #### How an edit works An edit is a read, then a list of operations, then a check. These rules hold for every op on this page. - **Read first.** `get_timeline` returns the ids (`T1` a timeline, `V2` a track, `c7` a clip, `m3` media in the bin) and a `state_token`. Pass ids as they are. An object without a short id, like a keyframe, has a UUID. - **Send the latest token.** Every edit needs `expected_state_token` from your latest read or edit. A newer edit by anyone makes it stale, and the edit is refused as a conflict. Read again and rebuild the change. - **All or none.** The operations in one call land together or not at all. Put a whole change in one call: a cut and its gap close, or every marker for a song. - **Check with `dry_run`.** `dry_run: true` checks the operations without applying them. - **Look up the fields.** Call `timeline_catalog` with `ops` naming the ops you are about to use, for their exact fields. Call it with `effects`, `audio_effects` or `transitions` for their settings. Unknown ops and fields are refused, and a renamed op says its new name. - **Retry the same request.** After a timeout or `completion_unknown`, send the identical request with the same token. If the first one landed, the retry is refused as a conflict and a read shows the change. Never re-read and resend because a call timed out. - **Use a new object in a second call.** An op cannot always use an object made earlier in the same call. `set_keyframes` on a text clip made in that call is refused, and so is the whole call. Ops that change an effect, a transition or an audio effect take its id from `get_timeline`. Make the object, read the timeline, then send the second call. - **Explicit values only.** Your agent decides the edits and sends exact values. There is no natural-language editing. ##### Time units Fields ending in `_f` are frames at the timeline's rate, and may be fractional. Fields ending in `_seconds`, and `at_seconds`, are seconds. Ranges include their start and exclude their end, so a clip from frame 0 to frame 90 ends before frame 90. Reads give rational times as `{value, rate}`, which is `value / rate` seconds. At 30 frames a second, two seconds is `60` frames. Convert seconds from a transcript or a beat list with the timeline's own rate from `get_timeline`. ##### From the CLI The CLI takes the same operations list from a file. Read the edit for its token, check with `--dry-run`, then apply. `ops.json` holds a bare JSON list, `[ {...} ]`, with no `operations` wrapper and none of the other MCP fields. ```bash invideo edit show invideo edit catalog --ops split_clip,delete_clip invideo edit change --timeline T1 --token … \ --operations @ops.json --dry-run invideo edit change --timeline T1 --token … \ --operations @ops.json ``` `` comes from `invideo edit new`. The `--token` value is the `state_token` that `invideo edit show` prints; each change returns a fresh one. On a branch, use the `branch_url` that `invideo branch new` returns, and a token from `invideo edit show `. #### Operations by job Each table gives the op, what it does, and the fields it needs. Most ops take more optional fields; `timeline_catalog` lists them all. ##### Placement and media These ops put media on the timeline, move and transform clips, and keep the media bin in order. An `asset` is a bin id like `m3`, or a sequence URL from `read`, which goes into the bin first. | Op | What it does | Required fields | | --- | --- | --- | | `insert_media` | Places a whole media file on one track. On a video track it places the picture alone. | `asset`, `track`, `at_f`, `ripple` | | `place_media` | Places part of a file, from one source time to another, with or without its sound. | `asset`, `track`, `at_f`, `source_start_seconds`, `source_end_seconds`, `mode`, `linked_audio` | | `move_clip` | Moves one clip to a track and frame. Linked clips stay unless you move them too. | `clip`, `track`, `at_f`, `mode` | | `reorder_clip` | Puts a clip right after another clip in a track's order. | `clip`, `track` | | `duplicate_clip` | Copies a clip and puts the copy right after it. | `clip` | | `link_clips` | Links clips into one group that moves, trims, splits and deletes together. | `clips` | | `unlink_clips` | Takes clips out of their link groups. | `clips` | | `set_position` | Moves a visual clip, in canvas pixels from the center. | `clip`, `x`, `y` | | `set_zoom` | Zooms a visual clip. `1` fits the canvas. Give `x` and `y` the same value. | `clip`, `x`, `y` | | `set_rotation` | Sets a visual clip's rotation in degrees. | `clip`, `degrees` | | `set_anchor` | Sets the point a clip rotates and zooms around. | `clip`, `x`, `y` | | `set_opacity` | Sets the opacity of a visual clip or a video track. | `target`, `opacity` | | `set_blend_mode` | Sets how a clip or a video track blends with what is below it. | `target`, `mode` | | `fit_frame` | Zooms a clip so the whole picture fits the canvas, with bars. | `clip` | | `fill_frame` | Zooms a clip so the picture covers the canvas, cropping the overflow. | `clip` | | `paste_attributes` | Copies transform, composite, crop, playback or effects from one clip onto others. | `from`, `to`, `attributes` | | `set_clip_enabled` | Turns a clip off or on. A clip that is off is skipped in playback and exports. | `clip`, `enabled` | | `set_name` | Renames a media clip, track, marker, folder or other named object. | `target`, `name` | | `create_folder` | Makes a folder in the media bin. | `name` | | `move_bin_items` | Moves bin folders and assets into a folder. | `folders`, `assets` | | `delete_bin_items` | Deletes bin folders and assets. | `folders`, `assets` | ##### Cutting and trimming These ops cut clips, move their edges, and open or close time. `from_f` on a trim or a roll must match the edge as you last read it. | Op | What it does | Required fields | | --- | --- | --- | | `split_clip` | Cuts a clip in two at a frame. The right half is a new clip; the left half keeps the id. | `clip`, `at_f` | | `trim_clip` | Moves the head or tail of a clip. | `clip`, `edge`, `from_f`, `to_f`, `mode`, `linked` | | `slip_clip` | Changes which part of its media a clip plays, without moving it. | `clip`, `from_src_f`, `to_src_f` | | `roll` | Moves the cut between two touching clips. One gets longer, the other shorter. | `left_clip`, `right_clip`, `from_f`, `to_f` | | `delete_clip` | Removes a clip, and leaves a gap (`leave_gap`) or closes it (`close_gap`). | `clip`, `mode`, `linked` | | `clear_track` | Empties a track, or one span of it, and keeps the track. | `track` | | `edit_gap` | Closes, resizes or opens a gap on a track. | `kind` | | `edit_time_range` | Inserts time, or removes a span, on every unlocked track at once. | `timeline`, `start_f`, `end_f`, `mode` | | `retime` | Changes speed inside one video clip: ramp, freeze, reverse, section, points or reset. | `clip`, `kind` | ##### Tracks These ops add, order, hide and lock tracks. | Op | What it does | Required fields | | --- | --- | --- | | `add_track` | Adds an empty video or audio track. | `name`, `kind` | | `delete_track` | Deletes a track and everything on it. | `track` | | `move_track` | Moves a track above another track of the same kind. | `track` | | `set_track_hidden` | Hides or shows a video track. | `track`, `hidden` | | `set_track_locked` | Locks or unlocks a track. Edits on a locked track are refused. | `track`, `locked` | | `add_adjustment` | Adds an adjustment clip. Its effects and grades apply to everything below it. | `track`, `start_f`, `end_f` | ##### Text and captions Text clips hold one block of words. Caption clips hold slides, each a line of text with a start and an end, and optional timed words that light up as they are spoken. | Op | What it does | Required fields | | --- | --- | --- | | `add_text` | Adds a text clip. It never covers or pushes other clips. | `track`, `start_f`, `end_f`, `text` | | `set_text` | Replaces the words of a text clip, or of a caption clip with one slide. | `clip`, `text` | | `set_text_style` | Restyles a whole text or caption clip. Only the keys you send change. | `clip`, `style` | | `style_text_range` | Styles some characters of a text clip. | `target`, `range`, `style` | | `add_captions` | Adds a caption clip from a list of slides, with optional words. | `track`, `slides` | | `set_caption_slide_text` | Replaces the text of one caption slide. | `clip`, `slide_index`, `text` | | `append_caption_slide` | Adds a slide at the end of a caption clip. | `clip`, `text`, `duration_seconds` | | `delete_caption_slide` | Removes one slide, as a blank gap or with the rest moving up. | `clip`, `slide`, `ripple` | | `move_caption_slide` | Moves one slide later or earlier inside its caption clip. | `clip`, `slide`, `delta_seconds` | | `trim_caption_slide` | Moves the left or right edge of one slide. | `clip`, `slide`, `delta_seconds`, `edge`, `ripple` | | `split_caption_fragment` | Splits one timed word of a slide in two. | `clip`, `slide`, `fragment_index`, `character_offset` | | `merge_caption_fragment` | Joins one timed word with the next. | `clip`, `slide`, `fragment_index` | ##### Shapes A shape clip holds paths: rectangles, ellipses, stars or drawn outlines. Each path has fills and strokes, called paint. | Op | What it does | Required fields | | --- | --- | --- | | `add_shape` | Adds a shape clip from a preset, with its box and center in canvas pixels. | `track`, `at_f`, `duration_f`, `preset`, `width`, `height`, `x`, `y` | | `add_shape_path` | Adds a rectangle, ellipse or star to a shape clip. | `clip`, `preset`, `size` | | `remove_shape_path` | Removes one path. | `clip`, `path` | | `reorder_shape_path` | Moves a path in the drawing order. | `clip`, `path`, `index` | | `rename_shape_path` | Renames a path. | `clip`, `path`, `name` | | `set_shape_path_visible` | Shows or hides a path. | `clip`, `path`, `visible` | | `set_shape_path_geometry` | Makes a path a rectangle, ellipse or star with a size and position. | `clip`, `path`, `geometry` | | `convert_shape_path_to_points` | Turns a preset path into points you can move one by one. | `clip`, `path`, `at_seconds` | | `set_shape_path_points` | Sets every point of a drawn path at one time. | `clip`, `path`, `at_seconds`, `closed`, `vertices` | | `transform_shape_path` | Moves, scales, rotates or fades one path at one time. | `clip`, `path`, `at_seconds`, `values` | | `trim_shape_path` | Draws only part of a path's outline, for a line that draws itself on. | `clip`, `path`, `at_seconds`, `enabled` | | `add_shape_paint` | Adds a fill or a stroke to a path. | `clip`, `path`, `kind` | | `remove_shape_paint` | Removes a fill or a stroke. | `clip`, `path`, `layer` | | `reorder_shape_paint` | Moves a fill or a stroke in the paint order. | `clip`, `path`, `layer`, `index` | | `set_shape_paint` | Changes a fill's or a stroke's settings at one time. | `clip`, `path`, `layer`, `at_seconds`, `values` | | `animate_shape_path` | Starts animating a drawn path's outline. | `clip`, `path`, `at_seconds` | | `stop_animating_shape_path` | Stops the outline animation and keeps the outline at one time. | `clip`, `path`, `at_seconds` | | `delete_shape_path_keyframe` | Removes the outline keyframe at one time. | `clip`, `path`, `at_seconds` | | `move_shape_path_keyframe` | Moves an outline keyframe to another time. | `clip`, `path`, `from_seconds`, `to_seconds` | | `set_shape_path_keyframe_easing` | Sets the easing from one outline keyframe to the next. | `clip`, `path`, `at_seconds`, `in_handle`, `out_handle` | | `create_shape_keyframe_lane` | Starts animating one setting of a path, like `transform.rotation`. | `clip`, `parameter`, `path` | ##### Effects Effects go on a video or image clip, or on a whole video track. Call `timeline_catalog` with `effects` for each effect's settings and ranges. | Op | What it does | Required fields | | --- | --- | --- | | `add_effect` | Adds an effect to the end of a clip's effects. | `clip`, `effect` | | `remove_effect` | Removes one effect or grade from a clip. | `clip`, `effect` | | `set_effect_parameter` | Sets one setting of an effect on a clip. | `clip`, `effect`, `parameter`, `value` | | `set_visual_effect_enabled` | Turns one effect off or on without removing it. | `target`, `effect`, `enabled` | | `move_visual_effect` | Reorders one effect in its stack. | `target`, `effect` | | `add_track_effect` | Adds an effect to a video track, for everything on it. | `track`, `effect` | | `remove_track_effect` | Removes one effect from a video track. | `track`, `effect` | | `set_track_effect_parameter` | Sets one setting of an effect on a video track. | `track`, `effect`, `parameter`, `value` | | `set_matte_source` | Sets the track a `track_matte_key` takes its shape from. | `target`, `effect` | | `apply_effect_asset` | Adds an effect asset from the media bin to a clip. | `clip`, `asset` | ##### Transitions Transitions sit on the cut between two touching clips, or at a clip's head or tail, from or to black. `in_f` is how far a transition reaches into the left clip and `out_f` into the right clip. | Op | What it does | Required fields | | --- | --- | --- | | `add_transition` | Adds a transition at the cut between two touching clips. | `left_clip`, `right_clip`, `type`, `in_f`, `out_f` | | `add_edge_transition` | Adds a transition at a clip's head or tail, from or to black. | `clip`, `edge`, `type`, `in_f`, `out_f` | | `remove_transition` | Removes a transition by its id. | `transition` | | `set_transition_parameter` | Sets one setting of a transition. | `transition`, `parameter`, `value` | | `resize_transition` | Changes how far a transition reaches into each clip. | `transition`, `in_f`, `out_f` | | `apply_transition_asset` | Places a custom transition from the media bin on a cut. | `left_clip`, `right_clip`, `asset`, `in_f`, `out_f` | ##### Color A grade is a stack of color controls on a clip. Masks limit a grade to part of the picture. | Op | What it does | Required fields | | --- | --- | --- | | `edit_grade` | Adds, removes or reorders a grade on a clip. | `clip`, `kind` | | `set_grade_parameter` | Sets one control of a grade, like `exposure` or `saturation`. | `clip`, `grade`, `parameter`, `value` | | `set_grade_curve` | Replaces one whole curve of a grade. | `clip`, `grade`, `which`, `points` | | `edit_grade_mask` | Adds or removes a mask on a grade. | `clip`, `grade`, `kind` | | `set_grade_mask_parameter` | Sets one setting of a grade mask, like its center or feather. | `clip`, `grade`, `mask`, `parameter`, `value` | | `apply_lut` | Applies a LUT from the media bin to a clip's grade. Bring the `.cube` or PNG LUT file in with `add_media` on the timeline URL first. | `clip`, `lut` | | `set_media_color_profile` | Says which color profile a bin file was shot in, such as a log profile. | `asset`, `profile` | | `set_timeline_working_space` | Sets the color space a timeline is mixed in. | `timeline`, `working_space` | ##### Audio and buses A video's sound is a separate audio clip linked to it, so target that clip. Call `timeline_catalog` with `audio_effects` for each audio effect's settings. | Op | What it does | Required fields | | --- | --- | --- | | `set_audio_gain` | Sets the volume of an audio clip or track, in dB. | `target`, `gain_db` | | `set_audio_muted` | Mutes or unmutes an audio clip or track. | `target`, `muted` | | `set_audio_solo` | Solos or unsolos an audio track. | `track`, `solo` | | `set_audio_pan` | Sets the stereo pan of an audio track. | `track`, `pan` | | `set_audio_fades` | Sets both fades of an audio clip, in frames. | `clip`, `fade_in_f`, `fade_out_f` | | `set_audio_fade` | Sets one fade of an audio clip, in seconds, and its curve. | `clip`, `direction`, `curve` | | `set_audio_speed` | Sets an audio clip's playback speed. | `clip`, `speed` | | `set_audio_pitch_preserved` | Chooses whether an audio clip keeps its pitch when its speed changes. | `clip`, `maintain_pitch` | | `apply_audio_crossfade` | Crossfades two touching audio clips. | `outgoing`, `incoming`, `curve`, `duration_seconds`, `alignment`, `trim_to_fit` | | `remove_audio_crossfade` | Removes a crossfade between two audio clips. | `outgoing`, `incoming` | | `add_audio_effect` | Adds an audio effect to a clip, a track, a bus or the timeline's chain. | `target`, `target_kind`, `effect` | | `remove_audio_effect` | Removes one audio effect. | `effect` | | `set_audio_effect_enabled` | Turns one audio effect off or on. | `effect`, `enabled` | | `move_audio_effect` | Reorders one audio effect in its chain. | `effect` | | `set_audio_effect_parameter` | Sets one setting of an audio effect. | `effect`, `parameter`, `value` | | `create_audio_bus` | Makes a submix bus that feeds the main output. | `timeline`, `name` | | `set_audio_routing` | Sends a track's or a bus's output to a bus. | `target` | | `create_audio_send` | Sends a copy of a track's or a bus's sound to another bus. | `target`, `bus`, `level`, `pre_fader` | | `set_audio_send_level` | Changes a send's level. | `send`, `level` | | `delete_audio_send` | Removes one send. | `send` | | `set_audio_bus_controls` | Changes a bus's volume, pan, mute, solo, name or effect switch. | `bus`, `values` | | `set_main_output` | Changes the main audio output, the last stage before export. | `values` | | `set_timeline_audio` | Sets the volume of a timeline's whole mix, or mutes it. | `timeline` | | `set_sidechain_source` | Picks the track, usually the voice, that `ducker` effects react to. A new timeline already uses `A1`; set it only when the voice is on another track. | `timeline` | ##### Keyframes A keyframe lane animates one property of a clip or a track. Keyframe times are in seconds: from the clip's start for a clip lane, and from the timeline's start for a track lane. | Op | What it does | Required fields | | --- | --- | --- | | `set_keyframes` | Replaces a clip's whole opacity or rotation animation, in frames. | `clip`, `property`, `points` | | `add_keyframe_lane` | Starts animating one property of a clip or track. | `parent`, `parent_kind`, `property`, `default_value` | | `create_effect_keyframe_lane` | Starts animating one number setting of an effect. | `clip`, `parameter`, `effect` | | `add_keyframe` | Adds a point to a lane. | `lane`, `time_seconds`, `value` | | `add_keyframes` | Adds many points to one lane at once. | `lane`, `points` | | `move_keyframe` | Moves a keyframe and gives it a new value. | `keyframe`, `time_seconds`, `value` | | `delete_keyframe` | Deletes one keyframe. | `keyframe` | | `remove_keyframe_lane` | Removes a lane and stops that animation. | `lane` | | `set_keyframe_interpolation` | Sets the easing from one keyframe to the next. | `keyframe`, `bezier_in`, `bezier_out`, `hold` | ##### Markers and guides Markers sit on the timeline at a frame. Guides are lines on the canvas, placed as a fraction of its width or height. | Op | What it does | Required fields | | --- | --- | --- | | `add_marker` | Adds a marker at a frame, or over a range with `duration_f`. | `at_f` | | `set_marker` | Changes a marker's frame, length, name, note or color. | `marker` | | `delete_marker` | Removes a marker. | `marker` | | `create_guide` | Adds a guide line to the canvas. | `timeline`, `orientation`, `position`, `locked` | | `set_guide` | Sets a guide's position and lock. | `guide`, `position`, `locked` | | `update_guide` | Changes any of a guide's position, orientation, lock or color. | `guide` | | `delete_guide` | Deletes one guide. | `guide` | | `set_timeline_guides_locked` | Locks or unlocks all guides at once. | `timeline`, `locked` | | `clear_timeline_guides` | Removes all guides, or only the horizontal or vertical ones. | `timeline` | ##### Nesting A nested clip shows another timeline inside this one. | Op | What it does | Required fields | | --- | --- | --- | | `nest_timeline` | Places another timeline as a nested clip. | `timeline`, `track`, `start_f`, `end_f` | | `nest_clips` | Copies chosen clips into a new timeline, and can replace them with one nested clip. | `video_clips`, `audio_clips`, `name`, `mode` | | `unnest_clip` | Replaces a nested clip with copies of the clips it shows. | `clip` | | `make_nested_clip_unique` | Gives one nested clip its own copy of its timeline. | `clip` | ##### Timelines and settings These ops make timelines and change their size, rate and work area. Branches and checkpoints are not ops: the `timeline_history` tool keeps them, and the CLI `branch` commands do the same. | Op | What it does | Required fields | | --- | --- | --- | | `create_timeline` | Makes a new timeline with empty video and audio tracks. Edit it in a later call. | `width`, `height`, `fps` | | `duplicate_timeline` | Copies a whole timeline into a new one that shares nothing with it. | `timeline`, `name` | | `set_timeline_settings` | Sets a timeline's canvas size and frame rate together. | `timeline`, `width`, `height`, `fps` | | `set_timeline_work_area` | Marks the part of a timeline to work on. | `timeline`, `start_seconds`, `end_seconds` | | `clear_timeline_work_area` | Clears the work area, so the whole timeline is used. | `timeline` | ##### Custom shaders When no effect or transition in the catalog fits, write a GLSL shader. Read `timeline_catalog` with `guides: ["custom_shader"]` once first. The shader is compiled and checked before it lands; a refusal lists the compiler's errors. | Op | What it does | Required fields | | --- | --- | --- | | `add_custom_effect` | Puts a GLSL effect you write on a video or image clip, with its parameters as controls. | `clip`, `name`, `source`, `params` | | `update_custom_effect` | Replaces a custom effect's shader. It needs the hash from `inspect_objects`. | `clip`, `effect_id`, `expected_effect_hash`, `source`, `params` | | `add_custom_transition` | Puts a GLSL transition you write on a cut, or at a clip's head or tail. | `name`, `source`, `params`, `in_f`, `out_f` | | `update_custom_transition` | Replaces a custom transition's shader. It needs the hash from `inspect_objects`. | `transition_id`, `expected_transition_hash`, `source`, `params` | #### Effect, audio effect and transition names These are the names that `add_effect`, `add_track_effect`, `add_audio_effect`, `add_transition` and `add_edge_transition` take. Call `timeline_catalog` with the name for its settings and ranges. ##### Effects Effects go on a video or image clip with `add_effect`, or on a video track with `add_track_effect`. | Name | What it does | | --- | --- | | `aurora` | Adds moving bands of rainbow aurora light over the picture. | | `beat_rock` | Splits the picture's color channels apart in short, regular bursts, like a beat hitting. | | `drop_shadow` | Puts a soft shadow of the clip's shape behind it. | | `tint` | Recolors the picture with two colors: one for the darks and one for the lights. | | `dynamic_zoom` | Zooms and pans smoothly over the clip's length, from a start framing to an end framing. | | `dynamic_anchor_zoom` | Zooms smoothly around the clip's anchor point over its length, from a start framing to an end framing. | | `edge_roundness` | Rounds the clip's corners. | | `8bit` | Turns the picture into blocky pixel art with a small retro game palette. | | `fast_chroma_key` | Removes a solid background color, like a green screen, so the tracks below show through. | | `fit_with_blur` | Fits the whole clip in the frame and fills the empty bars with a blurred, enlarged copy of it. | | `flashback` | Flickers the picture with bright, tinted overexposure in bursts, like a memory. | | `focus_blur` | Keeps the center sharp and blurs toward the edges, with slight color fringing. | | `gaussian_blur` | Blurs the picture evenly. | | `invert` | Inverts the colors, like a film negative. | | `kaleidoscope` | Folds the picture into a moving kaleidoscope pattern. | | `lens_flare` | Adds a lens flare glow over the picture. | | `multi_mirror` | Mirrors one part of the picture onto the rest. | | `pixel_glitch` | Flashes shifted blocks of the picture with noisy grain, like a digital glitch. | | `16bit` | Turns the picture into blocky pixel art with fewer color levels, keeping its own colors. | | `tritone` | Recolors the picture with three colors: one each for the darks, midtones and lights. | | `wiggle` | Shakes the picture randomly, zoomed in slightly so the edges stay hidden. | | `zoom_out` | Shrinks the picture and repeats it in tiles to fill the frame. | | `crop` | Cuts the clip down to a rectangle, with optional soft edges and rounded corners. | | `track_matte_key` | Shows the clip only where another video track has picture, using that track as a mask. | ##### Audio effects Audio effects go on an audio clip, an audio track, a bus or the timeline's own chain with `add_audio_effect`. | Name | What it does | | --- | --- | | `compressor` | Evens out a performance: loud parts quieter, quiet parts louder. | | `de_esser` | Softens harsh s and sh sounds in a voice. | | `click_remover` | Removes lip smacks and mouth clicks from a voice. | | `ducker` | Pulls music down under a voice, and back up after it. | | `eq` | An 8-band equalizer. | | `limiter` | Holds the level under a ceiling, for delivery. | | `pitch_shift` | Moves a voice up or down without changing its timing. | | `plate_reverb` | A classic plate reverb. | | `voice_eq` | Cleans up a recorded voice: less rumble, more clarity. | | `voice_reverb` | A one-knob plate reverb for voice. | ##### Transitions Transitions go on a cut with `add_transition`, or at a clip's head or tail with `add_edge_transition`. | Name | What it does | | --- | --- | | `back_flip` | The next clip flips over in 3D from one side and lands on top of the current one. | | `barrel` | The picture bulges or pinches like a fisheye lens while it crossfades to the next clip. | | `big_reveal` | The current clip shrinks and slides away while the next one slides in, zooming down from close up. | | `blink` | The picture flickers between the two clips and settles on the next one. | | `block_displacement` | The picture breaks into rectangular blocks that slide away to show the next clip. | | `blur` | Both clips blur to a peak in the middle while they crossfade. | | `bold_and_powerful` | The next clip slides in enlarged over the current one, then settles back to its normal size. | | `bounce_back` | The next clip slides in with a springy bounce. | | `cross_zoom` | A zoom blur sweeps across the frame while the clips crossfade. | | `cross_zoom_blur` | The current clip zooms in and blurs as the next one zooms down into place. | | `cube_3d_rotation` | The two clips turn like neighboring faces of a cube. | | `curl_in` | The next clip pushes the current one out in stop-start steps. | | `curtain_call` | The current clip shrinks as it is pushed out and the next one grows into place. | | `cut` | The frame splits in half and the halves slide apart to show the next clip. | | `dot_glitch` | A digital glitch of noise blocks and dots that switches to the next clip at its peak. | | `dots` | The current clip dissolves into a grid of halftone dots that resolves into the next one. | | `fade` | A plain crossfade; at the start or end of a clip, a fade from or to black. | | `film_roll_in` | The frame scrolls quickly through a strip of frames, like a film reel, and lands on the next clip. | | `flash` | A flash of color hides the change to the next clip. | | `flippin` | The whole frame flips over like a card, with the next clip on the back. | | `light_leak` | A glow of colored light with dust and soft light spots washes over a crossfade. | | `light_leak_bokeh` | Drifting, out-of-focus spots of light pass over a crossfade. | | `light_leak_flicker` | A flickering burst of colored light covers the middle of a crossfade. | | `light_leak_flow` | Both clips smear along one direction as a band of light flows across. | | `glitch` | The color channels wave apart while the clips crossfade. | | `glitch_displace` | The picture breaks into noisy, washed-out fragments that resolve into the next clip. | | `glitch_slide` | Strips of the picture slide out of place with a color split while the clips crossfade. | | `granularity` | Both clips break into large pixel blocks at the middle while they crossfade. | | `hinge` | The next clip swings into place around a corner, like a door on a hinge. | | `hole` | A round opening grows from the center as one clip zooms through it into the other. | | `impact` | The next clip snaps in close up, then punches back out to its normal size in steps. | | `lens_distortion` | The picture bulges like a lens with color fringing, then settles into the next clip. | | `lens_flare` | A lens flare sweeps over a soft crossfade. | | `mirror_zoom` | The current clip shrinks into mirrored tiles while the next one grows out of them. | | `pixelate_zoom` | The current clip zooms in while it pixelates, and the next one sharpens into place. | | `radial_blur` | A zoom blur toward the center while the clips crossfade. | | `rewind` | Frames scroll past quickly, snap back and land on the next clip, like a rewind. | | `roll` | The frame rolls past repeated copies of itself and lands on the next clip. | | `roll_3d` | Like roll, with the frame bulging like a cylinder and, if set, turning as it rolls. | | `rotation` | The current clip spins away with motion blur as the next one spins in. | | `rotation_zoom` | The current clip spins and zooms away while the next one spins in from small. | | `showtime` | A hard-edged wipe shows the next clip in stop-start steps. | | `shake_flash` | A camera shake around the change, hidden by a flash of color. | | `shake_slide` | The next clip pushes in with a camera shake and a color split. | | `shake_zoom` | A zoom between the clips with a camera shake and a color split. | | `slide` | The next clip pushes the current one out of the frame. | | `slide_blur` | The clips slide with motion blur along a straight or curved path. | | `slide_cube` | The current clip squeezes toward one edge as the next one expands from the other. | | `slide_fade` | The clips slide past each other while they crossfade. | | `slide_stretch` | The clips slide with a heavy stretch and blur along the motion. | | `slide_warp` | The clips slide with motion blur, the leading edge bending as it moves. | | `slit_scan` | The edge of the picture smears across the frame, then unsmears into the next clip. | | `stack` | The next clip slides in over the current one, which stays still. | | `threshold` | The picture gives way by brightness, through a solid color, to the next clip. | | `twirl` | The picture swirls around the center while the clips crossfade. | | `wave` | Sideways ripples run through the picture while the clips crossfade. | | `wipe` | A hard edge wipes across the frame to show the next clip. | | `wiper` | The frame zooms in and spins with blur, changes to the next clip and unwinds. | | `wobble_slide` | Strips of the picture wobble out of place with blur and color blocks while the clips crossfade. | | `zoom` | One clip zooms in or out of the other, with a fade. | | `zoom_twirl_rgb` | The current clip zooms away with a twirl and a color split as the next one grows into place. | #### Examples Each example is the `operations` list of one `edit_timeline` call, or the contents of `ops.json` for `invideo edit change`. The ids are examples: take the real ones from `get_timeline`. The timeline runs at 30 frames a second. ##### Place a file on the timeline This places bin asset `m3` at the start of track `V1`, then places seconds 4 to 10 of `m4`, with its sound, right after it. ```json [ { "op": "insert_media", "asset": "m3", "track": "V1", "at_f": 0, "ripple": false }, { "op": "place_media", "asset": "m4", "track": "V1", "at_f": 150, "source_start_seconds": 4, "source_end_seconds": 10, "mode": "overwrite", "linked_audio": true } ] ``` ##### Cut the first three seconds This splits clip `c7` at frame 90. The left half keeps the id `c7`, so the delete removes it and closes the gap. Its linked sound goes with it. ```json [ { "op": "split_clip", "clip": "c7", "at_f": 90 }, { "op": "delete_clip", "clip": "c7", "mode": "close_gap", "linked": true } ] ``` ##### Add a title and match an existing one This adds a white, bold title for the first three seconds, then restyles text clip `c12` to match. ```json [ { "op": "add_text", "track": "V2", "start_f": 0, "end_f": 90, "text": "Summer in Lisbon", "style": { "font_size": 96, "font_weight": 700, "color": "#ffffff", "align": "center", "shadow": true } }, { "op": "set_text_style", "clip": "c12", "style": { "font_weight": 700, "color": "#ffffff", "shadow": true } } ] ``` ##### Add a crossfade and a fade to black This crossfades the cut between `c7` and `c8` over 24 frames, then fades the tail of `c8` to black over one second. ```json [ { "op": "add_transition", "left_clip": "c7", "right_clip": "c8", "type": "fade", "in_f": 12, "out_f": 12 }, { "op": "add_edge_transition", "clip": "c8", "edge": "tail", "type": "fade", "in_f": 0, "out_f": 30 } ] ``` ##### Add word-by-word captions This adds two caption slides with timed words. The words build up as they are spoken. The times come from a transcript (`media` with `audio.transcript`), turned into frames. ```json [ { "op": "add_captions", "track": "V3", "slides": [ { "text": "Welcome back", "start_f": 0, "end_f": 30, "words": [ { "text": "Welcome", "start_f": 0, "end_f": 15 }, { "text": "back", "start_f": 15, "end_f": 30 } ] }, { "text": "to the channel", "start_f": 30, "end_f": 66, "words": [ { "text": "to", "start_f": 30, "end_f": 38 }, { "text": "the", "start_f": 38, "end_f": 46 }, { "text": "channel", "start_f": 46, "end_f": 66 } ] } ], "style": { "font_size": 64, "color": "#ffffff", "stroke": true, "stroke_color": "#000000", "stroke_width": 4 } } ] ``` #### After an edit Check the result before you call it done. `capture` renders frames of the timeline at the seconds you name. `check_timeline` reports structural problems, like a clip that points at something deleted. It does not judge the edit. On the CLI, the same checks are `invideo edit capture` and `invideo edit check`. #### Related - [MCP tools](/reference/mcp-tools) - [CLI commands and flags](/reference/cli) - [Check your video before you say it is done](/how-to/check-your-video) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Cut ums, pauses and retakes](/how-to/creators/cut-ums-and-retakes) ### MCP tools Source: https://docs.invideo.io/reference/mcp-tools.md Every invideo MCP tool with what it takes and what it returns, the media ops, the job statuses and the refusal codes. The invideo MCP server is a remote server that your agent connects to once. Through it the agent generates video, images, voice and music with the models in `find_models`, edits timelines, and exports. It is the route for clients without a shell: Claude on the web, ChatGPT, the Gemini app, VS Code, Gemini CLI and any other MCP client. Terminal agents such as Claude Code, Codex, Cursor and Antigravity use the CLI instead; see [invideo for AI agents](/agents). A generic client config looks like this: ```json { "mcpServers": { "invideo": { "url": "https://mcp.invideo.io/mcp" } } } ``` | Setting | Value | | --- | --- | | Server URL | `https://mcp.invideo.io/mcp` | | Transport | Streamable HTTP (JSON-RPC 2.0 over POST) | | Sign-in | OAuth in the browser when you connect, or a device code with no browser | There are no API keys. Every call runs as the signed-in person, in the workspaces they chose. For other clients, see [invideo for AI agents](/agents). #### Rules for every tool Four rules hold across the tools. Read them before the tool list. - **A URL is the handle.** Every tool takes a URL as `url`, and every result gives the URLs to use next. Give each URL to the person: it opens exactly that in invideo. Nothing is remembered between calls. - **Register a name, then pass `as`.** In a project, call `register` once with a `name`, like `scout`. Then pass that name as `as` on every call there. Without it, you act as the agent that every unnamed call from your client shares. - **Follow `next`.** Every result carries `next`: what to do from here, with the tools and URLs. It is advice, not orders. - **Read `structuredContent`.** Results come as structured content, with JSON text too. Check `isError` and the status before you treat a request as done. These are the URL shapes the tools take: | What | URL | | --- | --- | | A workspace | `https://invideo.io/@` | | A project | `https://invideo.io/@/` | | A notebook page | `…/notebook/page-2` | | A thread on a page | `…/notebook/page-2#thread-9` | | A sequence (one generation, upload or stock result) | `…/notebook/seq-9.1` | | A timeline on a branch | `…/tree/main/seq-9.1` | | The project's context, and one entry | `…/context`, `…/context/world/kai.md` | | A brief | `…/briefs/3` | | The project's files, a folder, one file | `…/assets`, `…/assets/downloads`, `…/assets/downloads/poster.jpg` | | Export pages, and one of them | `…/exports`, `…/exports/` | #### Tools at a glance The tools come in the same groups as the server's own guide, which `get_help` returns. Each tool lists what it takes and what it returns. ##### Projects Projects live in a workspace. Pass the workspace's URL from `list_workspaces`. | Tool | Takes | Returns | | --- | --- | --- | | `list_projects` | A workspace `url`, an optional `query` on the title, and `offset` for the next page. | The workspace's projects, newest first, each with its URL. | | `new_project` | A workspace `url` and a `title`. | The new project's URL. | ##### Read anything One tool reads any URL. | Tool | Takes | Returns | | --- | --- | --- | | `read` | Any `url`: a project, page, thread, sequence, timeline, context entry, brief, file or folder. | What is there. A project gives its pages, threads, sequences, context, briefs and newest files. A sequence gives its status, a fresh download URL, and a `picture` once completed. Every item has its URL, status, maker and `judgement`. | ##### Mark and rename These tools change what the person sees in the notebook. | Tool | Takes | Returns | | --- | --- | --- | | `mark_sequence` | A sequence `url`, `status` (`accepted` or `rejected`) and an optional `reason`. | The mark, which `read` shows as `judgement`. Mark only when the person asks or agrees. | | `rename` | A page, thread or sequence `url`, and a `name`. With your own agent URL, it renames you. | A `read` of what it renamed. | ##### Briefs and context Context entries and briefs are markdown documents that the project's agents work from. | Tool | Takes | Returns | | --- | --- | --- | | `new_brief` | A project `url`, a `name` and a `description`. | The brief's URL. | | `edit` | An entry or brief `url`, `old_text` quoted exactly as `read` shows it, `new_text`, and optional `replace_all`. | The changed document. | | `write` | An entry or brief `url`, the whole `markdown`, the `revision` from your read, and an optional `description`. | The written document. A write at a new entry URL makes the entry. Empty markdown deletes an entry or archives a brief. | ##### Pages, timelines and media in These tools add pages, timelines and files to a project. | Tool | Takes | Returns | | --- | --- | --- | | `new_page` | A project `url` and a `title`. | The new page's URL. | | `new_timeline` | A page or project `url`, and optional `name`, `width`, `height` and `fps`. | The timeline's URL, in a thread of its own. | | `add_media` | A `url` (page, thread or timeline) and one source: `media_url`, `file`, `upload_id` or `stock`. Optional `file_name`, `mime_type` and `timeline_id`. | The file's sequence URL. On a timeline, also its media bin entry with the asset id. A font or a document goes to the project's files. On a timeline URL, a font also goes into the bin, and its id is the font that `add_text` takes. A `.cube` LUT on a timeline URL goes into the bin, and its id is the `lut` that `apply_lut` takes. | | `start_upload` | A `file_name`. | An `upload_id` and an `upload_url`. PUT the raw bytes to the URL, then call `add_media` with the `upload_id`. | ##### Libraries One tool searches the voice and stock libraries. | Tool | Takes | Returns | | --- | --- | --- | | `search_library` | A `url`, a `library` (`_voices`, `stock_video`, `stock_image` or `stock_music`), a `query`, and `cursor` for voices. | Items with an `id` and a low-resolution `preview`; exports use the clean file. | ##### Generate These tools find a model, show its inputs and run it. See [Models](/reference/models). | Tool | Takes | Returns | | --- | --- | --- | | `find_models` | A `url`, and optional `output` (`video`, `image`, `audio`, `three_d`) and `query`. | Models with an id, a name and a price. | | `get_model` | A `url` and a `model` id. | The model's description, capabilities, price by its inputs, and its inputs as a JSON Schema. | | `generate` | A `url`, a `model`, `inputs`, `max_credits`, `dry_run` and `idempotency_key`. | With `dry_run`, the price and nothing started. Otherwise the thread's URL at once, and the sequences' URLs once they appear. | ##### Read and check a timeline These tools read a timeline without changing it. | Tool | Takes | Returns | | --- | --- | --- | | `get_timeline` | A timeline `url`, `mode` (`overview`, `window`, `collection`, `inspect`), and the fields for that mode. | Tracks, clips and media with short ids, the revision, and the `state_token` that edits need. | | `inspect_objects` | A timeline `url` and `ids`. | Each object with every property `edit_timeline` can change. | | `timeline_catalog` | A `url`, and optional `ops`, `effects`, `audio_effects`, `transitions` or `guides` by name. | With no names, every op, effect and transition with one line each. With names, their exact fields and settings. | | `check_timeline` | A timeline `url`. | Structural findings, each with what is wrong and how to fix it. It does not judge the edit. | ##### Edit and keep history These tools change a timeline and keep its branches and checkpoints. | Tool | Takes | Returns | | --- | --- | --- | | `edit_timeline` | A timeline `url`, `timeline_id`, `expected_state_token`, `operations`, and optional `dry_run`. | The new state. The operations land all or none. See [Timeline edit operations](/reference/edit-operations). | | `timeline_history` | A timeline `url` and an `action`: `list`, `checkpoint`, `restore`, `create_branch`, `edit_from_here`, `create_tag`, `rename`, `archive`, `unarchive`, `set_default` or `declare_final`. | Branches and checkpoints with their URLs, or the timelines an action saved or changed. Every action but `list` and `unarchive` needs `expected_state_token`. | ##### Look and make new files These tools render frames of a timeline and work on single files. | Tool | Takes | Returns | | --- | --- | --- | | `capture` | A timeline `url`, `at_seconds`, and an optional `timeline_id`. | Rendered frames of the timeline as it looks now, with every layer, effect and text. | | `media` | A `url` and an `op`, with that op's fields. | A read of the file, a transcript, or a new sequence. See the `media` ops below. | ##### Your cursor People watching the timeline see your cursor under your client's name. | Tool | Takes | Returns | | --- | --- | --- | | `point_at` | A timeline `url`, a short `text`, and `at_seconds` or clip `ids`. | Your cursor at that place, with the text beside it. | | `leave_timeline` | A timeline `url`. | Your cursor off the timeline. | ##### Export Exports are free and need the person's export permission on the project. | Tool | Takes | Returns | | --- | --- | --- | | `export` | A timeline `url`, a `format` (`video`, `premiere`, `final_cut`, `davinci` or `invideo`), `options`, and an `idempotency_key`. | The export's thread URL at once, and its card's URL once it appears. `read` the card for its status, then its files or its export page. | For `video`, `options` takes `mode` (`video`, `audio`, `image`), `quality` (`240`, `480`, `720`, `1080`), `file_name`, `start`, `end`, `fps`, `encode_quality` (`draft`, `good`, `best`), `target_lufs`, `audio_format` (`aac`, `opus`, `wav`), `still_at` and `timeline_id`. For `premiere`, `final_cut` and `davinci`, it takes `media_packaging` (`folder`, `zip`, `none`). `export` with `format` set to `premiere`, `davinci` or `final_cut` makes a project file that Premiere Pro, DaVinci Resolve or Final Cut Pro opens. ##### Export pages Export pages are where people watch, comment on and download what was made. | Tool | Takes | Returns | | --- | --- | --- | | `add_to_export_page` | A project `url`, sequence or timeline `urls`, and `page` for an existing page, or `title` and `kind` (`playlist`, `canvas`, `doc`) for a new one. | The page, with its URL and object ids. A new page is private. | | `edit_export_page` | An export page `url`, and `remove`, `order` or `title`. | The changed page. | | `share_export_page` | An export page `url`, `visibility` (`public`, `shared`, `private`), `permissions` and `team_access`. | The page's new sharing. Ask the person before you make a page public. | ##### Account These tools say who is signed in and where they can work. | Tool | Takes | Returns | | --- | --- | --- | | `current_user` | Nothing. | The person's name and email, and `credits_remaining` in the default workspace. | | `list_workspaces` | Nothing. | The workspaces this connection can use, each with its URL. | ##### Feedback These tools send a report to the invideo team. | Tool | Takes | Returns | | --- | --- | --- | | `report_bug` | A `url`, a `summary`, `what_happened`, and optional `tool`, `kind` and `expected`. | The filed report. Use it when a call fails for a reason you cannot see, or a description left you guessing. | | `request_feature` | A `url`, a `summary`, and optional `details` and `workaround`. | The filed request. Use it for something the person needs that the tools cannot do. | ##### Other tools The server has six more tools. The guide's table does not list them, but its text and the tool schemas do. | Tool | Takes | Returns | | --- | --- | --- | | `get_help` | An optional `topic`. | The server's guide to working with invideo, or one section of it. | | `status` | A project `url` and a list of job `urls` from that project. | Each job's status and `retry_after_s`, in one call. | | `register` | A project `url`, a `name`, and an optional `model`. | Your name in the project, and the agents already there. | | `message` | An agent's `url` and `text`. | The sent message. Its answer comes to your inbox. Messaging Agent Two starts its work, and Agent Two's work and the media it makes use credits. | | `inbox` | A project `url`, and an optional `before`. | The messages sent to your `as` name, oldest first. | | `import-claude-motion-from-url` | A video `url`, a `download_token`, and optional `title` and `claude_design_project_id`. | An MP4 video imported into invideo. | #### The media tool `media` works on one file without a timeline. The file is a sequence URL, a file under the project's `…/assets`, or, for reads, a bin asset (the timeline's URL and `asset_id`) or a stock result (the project's URL and `stock`). Pick the job with `op`. Which ops take which file: - **Reads take `asset_id`.** `metadata`, `video.frames`, `audio.waveform`, `audio.loudness`, `audio.content`, `audio.onsets`, `audio.markers`, `audio.key`, `audio.sections` and `audio.beats` accept a bin asset. - **Paid and file-making ops take a sequence URL.** `audio.transcript`, the model ops and every tool op below refuse `asset_id` with `not_found`. Pass the file's sequence URL (`…/notebook/seq-N.M`) as `url`. `add_media` returns that URL, and so does `invideo asset upload` on the CLI. ```json { "url": "https://invideo.io/@acme/launch-reel/notebook/seq-9.1", "op": "audio.transcript", "dry_run": true } ``` ##### Reads, free Reads answer at once and cost nothing. | Op | What it gives | | --- | --- | | `metadata` | What a file is: streams, duration, size. | | `video.frames` | Frames of a file at the times in `at_seconds`. | | `audio.waveform` | A file's audio levels, as peaks. | | `audio.loudness` | A file's loudness: integrated, true peak, range. | | `audio.content` | Where the sound is speech, music, effects or silence. | | `audio.onsets` | Where each hit or transient starts and peaks. | | `audio.markers` | Tempo, beats, phrases and drops. | | `audio.key` | The musical key. | | `audio.sections` | The musical structure, coarse to fine. | | `audio.beats` | Where the strong and weak beats fall. | ##### Transcript and media understanding The transcript is kept on the file. The first call starts it and returns its status with `retry_after_s`. Call again with the same file for the words. Only the first call spends credits, so run it with `dry_run` first and pass `max_credits`. | Op | What it gives | | --- | --- | | `audio.transcript` | Every word said, with its time and speaker. `start_seconds`, `end_seconds`, `offset` and `limit` page through the words. | | `describe` | What is seen and heard across the whole file: a summary, chapters and captions. Costs credits; `dry_run` prices it, `max_credits` caps it. | | `ask` | Answers one `question` about the stretch from `start_seconds` to `end_seconds`, inside the call. Costs credits; `dry_run` prices it, `max_credits` caps it. | ##### Document pages This op turns a document in the project's files into images. The dry run shows its price before anything starts. | Op | What it gives | | --- | --- | | `document.pages` | An image sequence of each page of a PDF or office document, on the page or thread `to` names, or the project's first page. | ##### Model ops A model op makes a new sequence beside the file, followed like a generation. It runs the op's default model, or the one you name in `model`, with `inputs` for that model's extras. It costs credits: pass `dry_run` first, then `max_credits` and an `idempotency_key`. A model named in this table is a good pick, not a promise. Models retire. If one is refused as not found, leave `model` out for the op's default, or run `find_models` with the job in words, and tell the person. | Op | What it makes | Models it takes | | --- | --- | --- | | `audio.separate` | The sound split into stems. | `audio_separation` | | `audio.clean` | A cleaned voice. | `clean_voice.clean_audio`, `clean_voice.clean_video` | | `video.upscale` | An upscaled video. | `topaz_proteus_natural`, `pixverse_upscale`, `topaz_video_upscale`, `seedvr_video_upscale`, `flashvsr_video_upscale`, `bytedance_video_upscale`, `byteplus_vod_upscale`, `flux_3_video_upscale`, `topaz_astra_2`, `topaz_starlight_precise_26`, `topaz_gaia_2_animation` | | `image.upscale` | An upscaled image. | `clarity_upscaler`, `crystal_upscaler`, `topaz_bloom_2`, `magnific_upscaler_creative`, `magnific_upscaler_precision_v2`, `pruna_p_image_upscale`, `byteplus_ultra_hd` | | `video.removeBackground` | A video without its background. | `bria_video_bg_remove`, `veed_video_bg_remove.veed_bg_standard`, `veed_video_bg_remove.veed_bg_fast`, `pixelcut_video_bg_remove`, `ben_v2_video_bg_remove` | | `image.removeBackground` | An image without its background. | `bria_bg_remove`, `birefnet_bg_remove` | ##### Tool ops A tool op makes a new file without a model. The dry run shows its price before anything starts. Its options are fields under their own names. `video.stitch`, `audio.concat` and `image.collage` take their files as a list of sequence URLs. A project file or a stock result has no thread, so `add_media` it first. | Op | What it makes | Its fields | | --- | --- | --- | | `video.trim` | A video cut to a time range. | `start_time`, `end_time` | | `video.reverse` | The video played backwards. | none | | `video.changeSpeed` | The video sped up, slowed down or ramped. | `start_speed`, `end_speed` | | `video.stitch` | Videos of the same aspect ratio joined into one. | `video_array`, `aspect_ratio` | | `video.sceneSplit` | The video split into its scenes. | `threshold` | | `video.loop` | The video looped to a target length. | `target_duration` | | `video.extractFrameFirst` | The first frame, as an image. | none | | `video.extractFrameLast` | The last frame, as an image. | none | | `video.extractFrameByNumber` | One frame by its number, as an image. | `frame_number` | | `video.extractFrameAtTime` | The frame at a time, as an image. | `time_seconds` | | `video.extractFrameInterval` | Every Nth frame, as images. | `frame_interval` | | `video.extractMsInterval` | A frame every N milliseconds, as images. | `interval_ms` | | `video.replaceAudio` | The video with its sound replaced. | `audio_input` | | `video.addAudioTrack` | The video with an audio file mixed into its sound. | `audio_input`, `volume` | | `video.resize` | The video as MP4 at a target height. | `resolution` | | `video.contactSheet` | One image of frames across the video, in a grid. | `rows`, `columns`, `resolution`, `style`, `start_offset_ms` | | `audio.toVideo` | An audio file as a video with a blank picture. | `aspect_ratio`, `fps` | | `audio.trim` | An audio file cut to a time range. | `start_time`, `end_time` | | `audio.extract` | A video's sound, as an audio file. | `format` | | `audio.concat` | Audio files joined into one. | `audio_array`, `gap_duration` | | `audio.addAudioTrack` | One audio file mixed over another. | `overlay_audio_input`, `start_time`, `volume` | | `image.collage` | Images combined into one collage. | `image_array`, `aspect_ratio` | | `image.crop` | A cropped image. | `x`, `y`, `w`, `h` | | `image.resizeAspectRatio` | An image resized to an aspect ratio. | `aspect_ratio`, `max_height` | | `image.resizeFit` | An image resized to fit a width and height. | `max_width`, `max_height` | | `image.rotate` | A rotated image. | none | #### Statuses Generations, imports, exports and model ops run in the background. Follow one with `read` on its URL, or with `status` for several URLs at once. Look again after `retry_after_s`. | Status | What it means | What to do | | --- | --- | --- | | `queued` | The job waits to start. | Check again after `retry_after_s`. | | `running` | The job is under way. | Check again after `retry_after_s`. | | `completed` | The job is over and its result is ready. | `read` the URL for the files. For a `premiere`, `final_cut` or `davinci` export, read it again until the files list is there; `completed` can come before the media package. | | `failed` | The job did not finish. | `read` the URL for the reason. | | `held` | A safety review holds the job. It is not over. | Tell the person, and check again later. | | `needs_confirmation` | Only the person can confirm the job, in invideo. | Ask the person to confirm it. | Never call `generate` or `export` again to check on a job. The transcript and beats in `media` are the one exception: calling again with the same file is how you follow them. #### Refusals A refused call returns `status`, `code` and `message`. The `code` is stable, for your logic. The `message` says what to do next. If the same refusal comes back after you fix it once, stop, tell the person, and file `report_bug`. | Answer | What it means | What to do | | --- | --- | --- | | `status: refused` | Nothing took effect. | Read the `message`, fix the request, and send it once more. | | `status: completion_unknown` | The call may have landed. | Retry the identical request with the same `expected_state_token` or `idempotency_key`. | | `code: unavailable` | The timeline is starting. | Retry the same request in a few seconds. | | `code: timeout` | A read, a capture or a media look timed out. Nothing changed. | Read again. | | `code: failed` | The request did not go through. | Try it once more. If it fails again, file `report_bug` with the tool, the URL and what you sent. | | A stale state token | Someone's edit landed first. | Read again with `get_timeline`, and rebuild the change. | | `get_model` or `generate` refuses the model as not found | Models retire. | Run `find_models` with the job in words, use the best match, and tell the person which model you used. | #### Related - [invideo for AI agents](/agents) - [Timeline edit operations](/reference/edit-operations) - [Models](/reference/models) - [CLI commands and flags](/reference/cli) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### Models Source: https://docs.invideo.io/reference/models.md How to find, price and run an invideo generation model, and the model ids to use for each job, from video to voice to 3D. invideo runs the leading generation models for video, images, audio and 3D. Your agent finds one, reads its inputs, prices the run, and then runs it: ```json { "url": "https://invideo.io/@acme/launch-reel/notebook/page-2", "model": "seedance_2_5.r2v", "inputs": { "prompt": "slow push on the bottle" }, "dry_run": true } ``` Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. For prices, see [Credits and what they cost](/account/credits). #### Find, price and run a model Every model goes through the same four steps, on MCP or on the CLI. Call `find_models` with `output` (`video`, `image`, `audio` or `three_d`) and a `query` in plain words, like "lip sync" or "seedance". Each result has a model id, a name and a price. Without a query, it lists every model by name. Call `get_model` with the `model` id. It returns the model's description, its price by its inputs, and its inputs as a JSON Schema. Media inputs take sequence URLs from the project, so bring files in with `add_media` first. A voice input takes an id from `search_library`. Call `generate` with `dry_run: true`. It checks the inputs and returns the price, and it starts nothing. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. Call `generate` again without `dry_run`, with `max_credits` and an `idempotency_key`. Nothing starts when the estimate is above `max_credits`. The key makes a retry after a timeout find the first generation instead of paying twice. The answer is the thread's URL at once, and the sequences' URLs when they appear. Credit prices by model are on the video, image and audio pricing pages. The dry run is the price of one specific call. When a model's `price` has `estimate: true`, the final charge can end above it. Follow the run with `read` or `status` on its URLs. Never call `generate` again to check on it. The URL says where the result goes. A page's URL starts a new thread there. A thread's, a sequence's or a timeline's URL adds to that thread. ##### On the CLI The CLI does the same four steps. A model's own inputs go with `-i key=value`, one each. ```bash invideo gen models --output video --query "lip sync" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ -i prompt="slow push on the bottle" invideo gen run --model seedance_2_5.r2v \ --max-credits --idempotency-key 7f3c9a2e \ -i prompt="slow push on the bottle" invideo status --wait ``` Where each value comes from: - `` comes from `invideo project new` or `invideo project list`. - `` is a notebook page, from `invideo notebook new-page `, or a page listed by `invideo notebook show `. The project URL works too. - `` is `estimated_credits` in the dry run's answer. - `` is in the paid run's answer. `invideo status` waits for it and saves nothing. `-i prompt=@prompt.txt` reads an input from a file. `--input inputs.json` gives all the inputs as one JSON object: the bare inputs that `get_model` lists, with no `inputs` wrapper. The dry run and the paid run pass the same inputs the same way, both with `-i` or both with `--input`. #### When a model retires Models retire. A model id on this page, in a skill or in a saved prompt is a good pick, not a promise. A retired model is refused as not found. | Symptom | Fix | | --- | --- | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | Name the model you used in your summary to the person, so a later run can check it the same way. #### Models by job The tables give the model ids that fit the jobs on this site. They are not every model. Run `find_models` for the full list, and `get_model` for a model's inputs before the first run. The names come from the model list. ##### Text to video These models make a clip from a prompt alone. Most of them also take an optional first or last frame. | Model id | Name | | --- | --- | | `veo_31_lite` | VEO 3.1 Lite | | `kling_v4.kling_v4_frames` | Kling 4.0: Frames | | `kling_v3_turbo` | Kling 3.0 Turbo | | `minimax_h3_max.generate` | MiniMax H3 Max: Generate | | `minimax_h3_max_turbo` | MiniMax H3 Max Turbo | | `wan_30_video.wan_30_frame` | Wan 3.0: Frames | | `gemini_omni_flash_15_preview.start_frame` | Gemini Omni Flash 1.5: Start frame | | `heygen_video_1.generate` | HeyGen Video: Generate | | `flux_3.frames` | FLUX 3: Frames | | `grok_imagine_video.grok_imagine_text_to_video` | Grok Imagine Video: Text to Video | ##### Image to video These models animate a still: a first frame, and for some a last frame too. | Model id | Name | | --- | --- | | `seedance_2_5.frames` | Seedance 2.5: Frames | | `seedance_2_0.frames` | Seedance 2.0: Frames | | `seedance_2_0_fast.frames` | Seedance 2.0 Fast: Frames | | `veo_31.frames` | VEO 3.1: Frames | | `veo_31_fast_preview.frames` | VEO 3.1 Fast: Frames | | `wan_27_alibaba.wan_27_i2v` | Wan 2.7: Image to Video | | `wan_26_alibaba.frames` | Wan 2.6: Image to Video | | `minimax_h3.frames` | MiniMax H3: Frames | | `minimax_h3_lite.frames` | MiniMax H3 Lite: Frames | | `minimax_h3_highspeed.frames` | MiniMax H3 Highspeed: Frames | | `grok_imagine_video.grok_imagine_image_to_video` | Grok Imagine Video: Image to Video | | `camera_moves.image` | Camera control: Image to Video | ##### Reference to video These models take reference images, and for some video and audio, and keep a character or a product the same across shots. Prefer them over a frames model when there is more than one reference. | Model id | Name | | --- | --- | | `seedance_2_5.r2v` | Seedance 2.5: Reference to Video | | `seedance_2_0.r2v` | Seedance 2.0: Reference to Video | | `seedance_2_5_draft.r2v` | Seedance 2.5 Draft: Reference to Video | | `veo_31.ingredients` | VEO 3.1: Ingredients | | `minimax_h3_max.reference` | MiniMax H3 Max: Reference to Video | | `minimax_h3.r2v` | MiniMax H3: Reference to Video | | `minimax_h3_lite.r2v` | MiniMax H3 Lite: Reference to Video | | `minimax_h3_highspeed.r2v` | MiniMax H3 Highspeed: Reference to Video | | `bach_1_0_pro.r2v` | Bach 1.0 Pro: Reference to Video | | `heygen_video_1.reference` | HeyGen Video: Reference to Video | | `kling_video_o1.ingredients` | Kling Video O1: Ingredients | | `happy_horse_11_alibaba.ingredients` | HappyHorse 1.1: Ingredients | | `wan_30_video.wan_30_reference` | Wan 3.0: Reference to Video | | `gemini_omni_flash_15_preview.reference` | Gemini Omni Flash 1.5: Reference to Video | ##### Extend or edit a clip These models continue a clip past its end, or change a clip you already have. | Model id | Name | | --- | --- | | `seedance_2_5.extend` | Seedance 2.5: Extend | | `veo_31.extend` | VEO 3.1: Extend | | `ltx_2_3_pro.extend_video` | LTX 2.3 Pro: Extend Video | | `grok_imagine_video_extend` | Grok Imagine Video Extend | | `seedance_2_5.edit` | Seedance 2.5: Edit | | `kling_v4.kling_v4_edit` | Kling 4.0: Video edit | | `luma_ray_32.edit` | Luma Ray 3.2: Edit | | `ltx_2_3_pro.retake_video` | LTX 2.3 Pro: Retake Video | ##### Reframe These models make a clip in a new aspect ratio by generating the missing picture. They are generative, not a face-tracking crop. | Model id | Name | | --- | --- | | `ltx_2_3_pro.reframe` | LTX 2.3 Pro: Reframe | | `luma_ray_32.reframe` | Luma Ray 3.2: Reframe | ##### Upscale Video upscales charge per source second. The `media` ops `video.upscale` and `image.upscale` run the same kind of model on one file. The two Topaz Hyperion models and LTX turn SDR into HDR. | Model id | Name | | --- | --- | | `topaz_starlight_fast_3` | Topaz Starlight Fast 3 | | `topaz_proteus_4` | Topaz Proteus | | `byteplus_vod_upscale` | BytePlus VOD Video Upscaler | | `topaz_video_upscale` | Topaz Video Upscale | | `seedvr_video_upscale` | SeedVR Video Upscale | | `veo_31_upscale` | Veo 3.1 Video Upscale | | `ltx_video_hdr_upscale` | LTX Video SDR to HDR Upscale | | `topaz_hyperion_2_5_sdr_hdr` | Topaz Hyperion 2.5 (SDR → HDR) | | `topaz_hyperion_2_sdr_hdr` | Topaz Hyperion 2 (SDR → HDR) | | `clarity_upscaler` | Clarity Upscaler | | `magnific_upscaler_precision_v2` | Magnific Upscaler Precision | | `topaz_bloom_2` | Topaz Bloom 2 | ##### Lip sync These models re-time a speaker's lips to a new audio track. | Model id | Name | | --- | --- | | `sync_lipsync_v3.video` | Sync Lipsync v3: Lip-sync video | | `kling_lipsync` | Kling Lipsync | | `heygen_lipsync` | HeyGen Lipsync | | `veed_lipsync_v2` | Veed Lipsync v2 | | `pixverse_lipsync` | Pixverse Lipsync | | `minimax_h3_max.lip_sync` | MiniMax H3 Max: Lip Sync | ##### Dubbing and translation No model dubs a video in one step, so your agent follows a recipe: 1. Get the words and times with `media` `audio.transcript`. 2. Write the translation. 3. Voice it with a text to speech model below. 4. Put the new voice on the video with `media` `video.replaceAudio`. 5. Re-sync the lips with a lip sync model. The voice changer below swaps the voice on a recording and keeps its timing. | Model id | Name | | --- | --- | | `elevenlabs_speech_to_speech.elevenlabs_sts_multilingual_v2` | ElevenLabs Voice Changer: Multilingual STS V2 | ##### Text to speech and voice clone Speaking models take a voice id from `search_library` in the `_voices` library, where `` is the model's id. A voice id works only with its own model: `seed_tts_2_0` takes a voice from `seed_tts_2_0_voices`, and `elevenlabs_text_to_speech.elevenlabs_tts_v4` takes one from `elevenlabs_text_to_speech_voices`. Workspace voice clones show up in the same libraries. `seed_audio_1_0.ta2a` clones a voice from reference clips. Pass them as `reference_audio_1` to `reference_audio_3`, and tag each speaker `@Audio1` to `@Audio3` in the prompt. | Model id | Name | | --- | --- | | `elevenlabs_text_to_speech.elevenlabs_tts_v4` | ElevenLabs Text to Speech: TTS V4 | | `elevenlabs_text_to_speech.elevenlabs_tts_multilingual_v2` | ElevenLabs Text to Speech: Multilingual V2 | | `elevenlabs_text_to_dialogue.generate_v4` | ElevenLabs Text to Dialogue: V4 | | `seed_tts_2_0` | Seed TTS 2.0 | | `minimax_speech_28` | Minimax Speech 2.8 | | `cartesia_sonic_3_6` | Cartesia Sonic 3.6 | | `gemini_3_1_flash_tts` | Gemini 3.1 Flash TTS | | `fish_audio_s2_1_pro` | Fish Audio S2.1 Pro | | `sarvam_bulbul_v3` | Sarvam Bulbul v3 | | `seed_audio_1_0.ta2a` | Seed Audio 1.0: Text + Audio to Audio | ##### Music These models write a song or an instrumental. Stock music is also in `search_library` under `stock_music`. | Model id | Name | | --- | --- | | `elevenlabs_music_v2_5_song` | ElevenLabs Music V2.5 Song | | `elevenlabs_music_v2_5_instrumental` | ElevenLabs Music V2.5 Instrumental | | `minimax_music_3` | Minimax Music 3.0 | | `lyria_3_pro` | Google Lyria 3 Pro | | `mureka_9_song` | Mureka 9 song | | `mureka_9_instrumental` | Mureka 9 Instrumental | | `mureka_9_soundtrack` | Mureka 9 Soundtrack | ##### Sound effects These models make sound effects from a prompt, or a soundtrack for a silent clip. | Model id | Name | | --- | --- | | `elevenlabs_sfx` | ElevenLabs SFX | | `pixverse_sfx` | Pixverse SFX | | `mmaudio_v2.mmaudio_v2_video_to_audio` | MMAudio V2: Video to Audio | | `mmaudio_v2.mmaudio_v2_text_to_audio` | MMAudio V2: Text to Audio | ##### Subtitles These models transcribe a video and burn styled subtitles into it. For captions you can edit on the timeline, use `audio.transcript` and the `add_captions` op instead. | Model id | Name | | --- | --- | | `invideo_subtitles` | invideo Subtitles | | `veed_subtitles` | VEED Subtitles | ##### Text animation and lyric videos These models put animated text on a video, or make a lyric video from a song. | Model id | Name | | --- | --- | | `dynamic_text.styles` | Dynamic Text: Styles | | `dynamic_text.diy` | Dynamic Text: DIY | | `uc_remotion_text` | UC Remotion Text | | `uc_blurred_background_text` | UC Blurred Background Text | | `lyrical_videos.audio` | Lyrical Videos: Lyrics from audio | | `lyrical_videos.video` | Lyrical Videos: Lyrics from video | ##### Background removal These models cut the subject out of a video or an image. The `media` ops `video.removeBackground` and `image.removeBackground` run them on one file. | Model id | Name | | --- | --- | | `bria_video_bg_remove` | Bria Video Background Removal | | `veed_video_bg_remove.veed_bg_standard` | VEED Video Background Removal: Standard | | `pixelcut_video_bg_remove` | Pixelcut Video Background Removal | | `ben_v2_video_bg_remove` | BEN v2 Video Background Removal | | `bria_bg_remove` | Bria BG Remove | | `birefnet_bg_remove` | BiRefNet BG Remove | ##### Segmentation and tracking These models find an object or a person in a video and follow it, for a mask. Use the mask with the `track_matte_key` effect and `set_matte_source`. | Model id | Name | | --- | --- | | `sam_3_1_video` | SAM 3.1 Video Segmentation | | `object_track` | Object Mask | ##### Clean plate These models remove an object or a person and fill in what was behind it. | Model id | Name | | --- | --- | | `ltx_2_3_clean_plate` | LTX 2.3 Clean Plate | | `ideogram_remove_object` | Ideogram Remove Object | | `qwen_image_edit_remove_element` | Qwen Edit Remove Element | ##### Avatars and talking photos These models make a talking head from a photo and an audio clip or a script. | Model id | Name | | --- | --- | | `heygen_photo_avatar` | HeyGen Photo Avatar | | `kling_avatar.pro` | Kling Avatar: Pro | | `kling_avatar.std` | Kling Avatar: Std | | `pruna_p_video_2_pro_avatar` | P-Video 2 Pro Avatar | | `sync_lipsync_v3.image` | Sync Lipsync v3: Animate portrait | | `omni_human_2` | OmniHuman 2.0 | ##### Images These models make or edit stills: thumbnails, product shots, storyboards and first frames for image to video. | Model id | Name | | --- | --- | | `nanobanana_pro` | Nano Banana Pro | | `nano_banana_2_1` | Nano Banana 2.1 | | `gpt_image_2` | GPT Image 2 | | `seedream_5_0_pro` | Seedream 5.0 Pro | | `flux_3_image.generate` | FLUX 3: Generate | | `flux_3_image.edit` | FLUX 3: Edit | | `ideogram_4_5.generate` | Ideogram 4.5: Generate | | `flux_kontext_pro` | Flux Kontext Pro | ##### Vectorize These models make a vector graphic, or turn an image into one. | Model id | Name | | --- | --- | | `ideogram_vector_1.vectorize` | Ideogram Vector 1: Vectorize | | `ideogram_vector_1.generate` | Ideogram Vector 1: Generate | | `recraft_v41.recraft_v41_text_to_vector` | Recraft 4.1: Text to Vector | ##### 3D Find these with `find_models` and `output: "three_d"`. `read` on a 3D sequence gives a preview and model files. Pass that sequence URL to the remesh, retexture and rig models. | Model id | Name | | --- | --- | | `meshy.text_to_3d` | Meshy: Text to 3D | | `meshy.image_to_3d` | Meshy: Image to 3D | | `meshy.multi_image_to_3d` | Meshy: Multi-image to 3D | | `meshy.remesh` | Meshy: Remesh | | `meshy.retexture` | Meshy: Retexture | | `meshy.rig` | Meshy: Rig | | `meshy.rig_and_animate` | Meshy: Rig & animate | #### When to use something else Some jobs need no model, or a different tool. The `media` tool makes many new files without a model: trims, speed changes, loops, frames and resizes. The dry run shows its price before anything starts. Captions you edit on the timeline come from `audio.transcript` and the `add_captions` op. Edits and exports never use a model. #### Related - [MCP tools](/reference/mcp-tools) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Credits and what they cost](/account/credits) - [Generate a missing shot or extend a clip](/how-to/film/generate-a-missing-shot) - [CLI commands and flags](/reference/cli) ### Exit codes Source: https://docs.invideo.io/reference/exit-codes.md What each invideo CLI exit code means, what to do about it, and how --wait and --timeout retry and stop. Every invideo CLI command ends with an exit code. Zero means it worked. Any other code says what went wrong and what to do next. The list comes from the CLI itself: ```bash invideo help exit-codes ``` #### Codes Read the exit code first, then the message. A refused command prints one line to stderr in plain words, even with `--json`; `--json` shapes the answer on stdout, not the error. Scripts branch on the exit code. | Code | Meaning | Fix | | --- | --- | --- | | `0` | It worked. | Nothing to do. | | `1` | It failed, on invideo's side or for an unknown reason. | Read the `message`. If it fails again, file it with `invideo feedback bug`. | | `2` | Usage error, or a request that cannot be done as asked. | Fix the command. Check its flags with `--help`. | | `3` | Conflict: the timeline changed since your read. Read it again. | Run `invideo edit show` again for a new state token, and rebuild the change. | | `4` | Not signed in: run `invideo auth login`. | Run `invideo auth login`. | | `5` | A limit: credits or quota. | Stop, and tell the person. | | `6` | Held by moderation: a safety review, not a refusal. | Wait, then run `invideo status --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `7` | Transient: nothing ran. | Run the same command again. | | `8` | Needs the person's confirmation. | Stop, and ask the person to confirm it in invideo. | | `9` | Update required. | Run `invideo update`, then run the command again. | #### How --wait and --timeout work with the codes A command that starts something (a generation, an export or an upload) returns the URL to follow at once. It does not wait for the job unless you ask. - **`--wait` follows a job.** `invideo status --wait` checks back until the job is over. It follows jobs in any of your projects. - **`--wait` retries code 7.** With `--wait`, any command tries again when nothing ran. A retry is the same request, so it never starts anything twice. - **`--timeout` stops the wait.** `--timeout ` stops waiting after that many seconds. The job goes on in invideo; run `invideo status --wait` later to pick it up. ```bash invideo status --wait --timeout 600 ``` The command that started the job returns `` and ``. `invideo status` follows jobs and saves nothing. To save a file, run `invideo notebook show --out ` after the job is over. #### Mistakes to avoid These are the mistakes agents make with exit codes, and what to do instead. | Avoid | Instead | | --- | --- | | Running a paid command again after a timeout to check on it. | Run `invideo status --wait` on the URL it gave. | | Sending the same `edit change` again after code 3. | Read the edit again with `invideo edit show`, and rebuild the change on the new token. | | Asking the person for a password or a code after code 4. | Run `invideo auth login`. With no browser, run it with `INVIDEO_NO_BROWSER=1`. | | Raising `--max-credits` on your own after code 5. | Stop, and tell the person the price. | #### Related - [CLI commands and flags](/reference/cli) - [Environment variables](/reference/environment) - [MCP tools](/reference/mcp-tools) - [Run invideo in CI and on servers](/how-to/ci-and-servers) ### Environment variables Source: https://docs.invideo.io/reference/environment.md The environment variables the invideo CLI and its install script read, and where the CLI keeps your sign-in. The invideo CLI reads a few environment variables. Set them once in your shell or your CI job, instead of passing a flag on every command: ```bash export INVIDEO_AS=scout export INVIDEO_JSON=1 invideo project list ``` #### Variables Each variable below appears in the CLI's own help or in its install notes. | Variable | What it does | Same as | | --- | --- | --- | | `INVIDEO_AS` | The name you registered in a project with `invideo agent register`. Every project command uses it. | `--as ` | | `INVIDEO_JSON` | Set to `1` to print every answer as one JSON object, `next` included. | `--json` | | `INVIDEO_NO_BROWSER` | Set to `1` to sign in with a device code. `invideo auth login` prints a link and a code, then waits for the approval. | None | | `INVIDEO_INSTALL_DIR` | The folder the install script writes the binary to. | None | | `INVIDEO_VERSION` | The release the install script installs. | None | #### INVIDEO_AS Several agents can work in one project. Each one takes a name with `invideo agent register`, and people watching see who did what. Pass the name with `--as`, or set `INVIDEO_AS` once. Without it, a command acts as `invideo-cli-`, which every unnamed command of yours shares. ```bash invideo agent register --name scout export INVIDEO_AS=scout invideo edit show ``` `` comes from `invideo project new` or `invideo project list`. `` comes from `invideo edit new`. #### INVIDEO_JSON With `INVIDEO_JSON=1`, every command prints its whole answer as one JSON object on stdout, for `jq`. Errors and notices still go to stderr. Without it, an answer is indented `key: value` text. ```bash INVIDEO_JSON=1 invideo project list | jq -r '.projects[].url' ``` #### INVIDEO_NO_BROWSER `invideo auth login` opens a browser on this machine and waits for you to sign in. Where no browser can open, such as over ssh, in a container or on a cloud machine, set `INVIDEO_NO_BROWSER=1`. The command then prints a link and a code at once. Open the link on another device and enter the code. This signs in the CLI only. It does not sign in an MCP connection. ```bash INVIDEO_NO_BROWSER=1 invideo auth login ``` Run it in the background or with a long timeout, since it waits for the approval. Your agent sends you the link and the code in one message. It never asks you for a password or for the code back. #### INVIDEO_INSTALL_DIR and INVIDEO_VERSION The install script writes one file. On macOS and Linux it is `~/.local/bin/invideo`. On Windows it is `%LOCALAPPDATA%\invideo\bin\invideo.exe`. `INVIDEO_INSTALL_DIR` picks another folder, and `INVIDEO_VERSION` picks another release. ```bash curl -fsSL https://agents.invideo.io | INVIDEO_INSTALL_DIR="$HOME/bin" sh ``` If the folder is not on your `PATH`, the script says so. Run the binary by its full path, or add the folder to `PATH`. #### Where the CLI keeps your sign-in The CLI keeps your sign-in on this machine, outside your project folders, and `invideo auth logout` forgets it. There are no API keys and no key variable to set. `invideo auth status` shows who is signed in. `invideo auth logout` forgets this machine's sign-in. #### Related - [CLI commands and flags](/reference/cli) - [Exit codes](/reference/exit-codes) - [Sign in, device codes and sessions](/account/sign-in) - [Run invideo in CI and on servers](/how-to/ci-and-servers) ## Integrations ### Higgsfield Source: https://docs.invideo.io/integrations/higgsfield.md Make clips in Higgsfield, then finish them in invideo with cuts, captions, music and an upscale, on a timeline your agent edits. It depends on the job. Higgsfield is an AI video and image platform that makes short generated clips from prompts, images and references. invideo adds what comes after the clip: a real timeline, captions, music, cuts, an upscale, and an agent that does the edit in your chat. Use Higgsfield to make the shots. Use invideo to turn the shots into a finished video. #### When to use both Use both when the clips are good but the video is not finished. Common cases: - **Several clips, one ad.** You made five shots in Higgsfield and need them cut together, in order, to a beat. - **A clip that needs words.** The shot needs captions, a title, a call to action or a voiceover. - **A clip that needs sound.** The clip is silent, or its sound does not fit, and it needs music that clears rights. - **A sharper file.** The clip needs an upscale before it goes to a client or a big screen. #### Hand-off: from Higgsfield into invideo Download each clip from Higgsfield as a video file, an MP4. Then your agent brings it into an invideo project: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. From there, the agent finishes the video: - **Cuts.** `place_media`, `split_clip`, `trim_clip` and `delete_clip` on the timeline. Beats from `media` `audio.beats` when the cut follows music. - **Captions.** `media` `audio.transcript` on the clip with speech, then `add_captions` with slides and words. - **Music.** `search_library` in `stock_music`, or `generate` with `elevenlabs_music_v2_5_instrumental`. - **Upscale.** `media` `video.upscale` on the clip or on the exported file, with its default model or one from its list, such as `topaz_starlight_precise_26`. The full recipe is in [Finish an AI clip from Higgsfield, Runway or Magnific](/how-to/marketing/finish-an-ai-clip). #### Hand-off: from invideo to Higgsfield When you want a clip back in Higgsfield, your agent runs `export` with `format` `video`. The result is a 1080p MP4. The agent reads the export card for the download, and you upload that file to Higgsfield like any other video. Use this when a finished cut becomes the input for another generation, such as a reference video. #### Steps Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent calls `add_media` for each Higgsfield clip, with `media_url` or an `upload_id` from `start_upload`. Expected result: one sequence URL per clip. The agent calls `new_timeline` in the shape you asked for, then makes a branch with `timeline_history`. Expected result: a timeline URL on a branch, not main. The agent calls `edit_timeline` with `place_media` for each clip, then trims and orders them. Expected result: a new `state_token`. The agent prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a caption clip. The agent runs `find_models` with the music bed in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_music_v2_5_instrumental`. The agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the music lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent runs `check_timeline` and `capture`, then `export` with `format` `video` and an `idempotency_key`. Expected result: an export card with status `completed`. The key MCP call, the full `add_media` call for a clip with a public link: ```json { "url": "", "media_url": "https://example.com/higgsfield-shot-1.mp4", "file_name": "higgsfield-shot-1.mp4" } ``` `` is the timeline's URL, from `new_timeline`. The `media_url` is the clip's public link. The same hand-off from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo asset upload ./higgsfield/*.mp4 invideo edit new --name "Ad v1" --width 1080 --height 1920 invideo edit export --format video --quality 1080 \ --idempotency-key "ad-v1" --json invideo status --wait invideo notebook show --out ./out ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is the `url` that `invideo edit new` returns. `` is `.sequences[0]` of the export answer. A music bed from a terminal: ```bash invideo gen models --query "instrumental music bed" invideo gen model --model elevenlabs_music_v2_5_instrumental invideo gen run --model elevenlabs_music_v2_5_instrumental \ --dry-run -i prompt="warm upbeat bed for a product ad" invideo gen run --model elevenlabs_music_v2_5_instrumental \ -i prompt="warm upbeat bed for a product ad" \ --max-credits --idempotency-key music-1 ``` `` is the same project. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. #### When to stay in Higgsfield Stay in Higgsfield when the job is the shot itself. Higgsfield's own tools are the place to try new prompts, models and camera moves, and to edit one generated clip by swapping an element in it. Also stay there when the clip is the final output, with no cut, no captions and no music. invideo adds value once there is more than one piece to put together. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | `edit_timeline` is refused as a conflict, or CLI exit code 3 | Someone's edit landed first. Read the timeline again with `get_timeline`, then send the change with the new `state_token`. | | `audio.transcript` returns no words | The clip has no speech. Skip the captions, or add a voice-over first. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [Finish an AI clip from Higgsfield, Runway or Magnific](/how-to/marketing/finish-an-ai-clip) - [When to use Higgsfield vs invideo](/compare/higgsfield) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Check your video before you say it is done](/how-to/check-your-video) - [invideo for AI agents](/agents) ### Runway Source: https://docs.invideo.io/integrations/runway.md Make shots in Runway, then cut them into a finished video in invideo with captions, music and an upscale, edited by your agent. It depends on where the work is. Runway is strong at making and changing shots: Gen-4.5 for video generation, Aleph for video transformation, Act-Two for performances, and Workflows for custom pipelines. invideo adds the timeline where those shots become a video, with captions, music, cuts, and an agent that edits in the same project as you. Use Runway to make and transform the shots. Use invideo to cut, caption, score and deliver them. #### When to use both Use both when you have Runway output and need a finished piece. Common cases: - **A short film or ad from many shots.** The shots live in Runway. The cut, the titles and the sound happen on a timeline. - **A team review.** Your agent edits on a branch, and the person reviews the change in invideo before it goes to main. - **Captions and music.** The shots need captions in the brand style and music that clears rights. - **Many versions.** One cut needs a 9:16, a 1:1 and a 16:9 version, one branch each. invideo also runs two Runway models inside a project: `runway_gen45` (Runway Gen-4.5) and `runway_act_two` (Runway Act-Two). Your agent calls them with `generate`, so a missing shot lands in the same project as the rest. #### Hand-off: from Runway into invideo Download each shot from Runway as an MP4. Then your agent brings it in: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. Then the agent finishes the video: - **Cuts.** `place_media`, `split_clip`, `trim_clip` and `move_clip`, with transitions from `add_transition`. - **Captions.** `media` `audio.transcript`, then `add_captions` with slides and words. - **Music and sound.** `search_library` in `stock_music`, or a model such as `elevenlabs_sfx` for a hit. - **Upscale.** `media` `video.upscale` with a model from its list, such as `topaz_astra_2`. #### Hand-off: from invideo to Runway When you want to change a finished cut in Runway, your agent runs `export` with `format` `video`. The result is a 1080p MP4. You upload it to Runway, for example as the input to a video transformation. To send one shot back, the agent exports only that part with `start` and `end` in seconds. #### Steps Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent calls `add_media` for each Runway shot. Expected result: one sequence URL per shot. The agent calls `new_timeline`, then makes a branch with `timeline_history`. Expected result: a timeline URL on a branch. The agent calls `edit_timeline` with `place_media` and `add_transition`. Expected result: a new `state_token`. The agent reads `runway_gen45` with `get_model`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the missing shot lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a caption clip. The agent runs `check_timeline` and `capture`, then `export` with `format` `video`. Expected result: an export card with status `completed`. The key MCP call, the full `generate` call that prices a missing shot before it runs: ```json { "url": "", "model": "runway_gen45", "inputs": { "prompt": "slow push in on the lighthouse at dusk" }, "dry_run": true } ``` `` is a notebook page from `read` on the project URL. The agent reads the model's real inputs with `get_model` before this call. The same shot from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo gen model --model runway_gen45 invideo gen run --model runway_gen45 --dry-run \ -i prompt="slow push in on the lighthouse at dusk" invideo gen run --model runway_gen45 \ -i prompt="slow push in on the lighthouse at dusk" \ --max-credits --idempotency-key shot-1 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. #### When to stay in Runway Stay in Runway when the work is on the shot. Runway's own tools are the place to generate, restyle, extend and transform a clip, and to animate a performance with Act-Two. Its video editor and Workflows suit a pipeline that stays inside Runway from start to end. invideo is the better place once the job is a sequence of shots with words and sound, edited by an agent and reviewed by a person. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | `edit_timeline` is refused as a conflict, or CLI exit code 3 | Someone's edit landed first. Read the timeline again with `get_timeline`, then send the change with the new `state_token`. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [Finish an AI clip from Higgsfield, Runway or Magnific](/how-to/marketing/finish-an-ai-clip) - [When to use Runway vs invideo](/compare/runway) - [Generate a missing shot or extend a clip inside your edit](/how-to/film/generate-a-missing-shot) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Check your video before you say it is done](/how-to/check-your-video) - [invideo for AI agents](/agents) ### Magnific Source: https://docs.invideo.io/integrations/magnific.md Upscale images and video in Magnific, then lay them out, cut and caption them in invideo. Or run Magnific's image upscalers inside invideo. It depends on the step. Magnific is strong at making one image or one video sharper and richer: its Creative Image Upscaler, its relight tools and its video upscaler. invideo adds what comes after the upscale: layout on a timeline, cuts, captions, music, and an agent that does the edit. Where Magnific's work on a single frame ends and the layout of a video starts, hand off to invideo. #### When to use both Use both when an upscaled asset has to become part of a video. Common cases: - **Product stills to a video.** Upscaled product photos become slides in an ad, with motion, text and music. - **AI clips that need detail.** A generated clip goes through Magnific's video upscaler, then into a cut. - **Thumbnails and posters.** One upscaled frame becomes the cover, and the rest of the video is cut in invideo. #### Magnific inside invideo invideo runs two of Magnific's image upscalers as models of `media` `image.upscale`: - **`magnific_upscaler_creative`** (Magnific Upscaler Creative): adds detail, with style, creativity and scale settings. - **`magnific_upscaler_precision_v2`** (Magnific Upscaler Precision): stays close to the source. The agent passes the model as `model` and its settings as `inputs`. The settings come from `get_model`. For `magnific_upscaler_creative` they include `scale_factor` and `optimized_for`. invideo also runs Magnific's skin enhancers as models with `generate`: `magnific_skin_enhancer.skin_enhancer_creative`, `magnific_skin_enhancer.skin_enhancer_faithful` and `magnific_skin_enhancer.skin_enhancer_flexible`. Magnific's video upscaler is not one of the `video.upscale` models in invideo. For video, use Magnific's own app, or `video.upscale` with a model from its list, such as `topaz_starlight_precise_26`. #### Hand-off: from Magnific into invideo Download the result from Magnific. Images come as image files. Magnific's video upscaler gives an MP4 by default. Then your agent brings each file in: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. Then the agent lays the video out. It places stills and clips with `place_media`. It moves a still with `add_keyframe_lane` on `zoom_x` or `position_x`, then `add_keyframes`. It adds text with `add_text` and music from `search_library`. #### Hand-off: from invideo to Magnific To upscale a finished frame or cut in Magnific, your agent exports it from invideo: - **One frame.** `export` with `format` `video`, `mode` `image` and `still_at` in seconds. - **The video.** `export` with `format` `video`. The result is a 1080p MP4. You upload that file to Magnific. For a sharper master of the whole video, upscale the export, not each shot. #### Steps Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent calls `add_media` for each file. Expected result: one sequence URL per file. The agent reads `magnific_upscaler_creative` with `get_model`. It calls `media` with `op` `image.upscale`, `model` `magnific_upscaler_creative` and `dry_run`, and tells you the price. Expected result: a price and no charge. The agent runs the same call with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL for the new image, beside the source. The agent calls `new_timeline`, makes a branch with `timeline_history`, then places the images with `place_media`. Expected result: a new `state_token`. The agent adds a zoom or pan with `add_keyframe_lane` and `add_keyframes`, then `add_text` and a music clip from `stock_music`. Expected result: a timeline that plays from start to end. The agent runs `find_models` with the music bed in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_music_v2_5_instrumental`. The agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the music lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent runs `check_timeline` and `capture`, then `export`. Expected result: an export card with status `completed`. The key MCP call, the full `media` call, priced first: ```json { "url": "", "op": "image.upscale", "model": "magnific_upscaler_creative", "inputs": { "scale_factor": "4x", "optimized_for": "standard" }, "dry_run": true } ``` `` is the `url` that `add_media` returns for the image. The `inputs` names come from `get_model`. #### When to stay in Magnific Stay in Magnific when the job is one image or one clip and its look. Relight, a creative upscale with a prompt, and a video upscale to a ProRes master are Magnific's work. Move to invideo once the asset needs a sequence, text, sound, or a person and an agent editing together. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | `image.upscale` is refused with `code: "not_found"` | The call named a media bin asset. Pass the image's sequence URL from `add_media`. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [Finish an AI clip from Higgsfield, Runway or Magnific](/how-to/marketing/finish-an-ai-clip) - [When to use Magnific vs invideo](/compare/magnific) - [Turn a product photo into a video without redrawing the product](/how-to/marketing/product-photo-to-video) - [Make a thumbnail for the video](/how-to/creators/thumbnail) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [invideo for AI agents](/agents) ### Claude Motion Source: https://docs.invideo.io/integrations/claude-motion.md Bring a Claude Motion animation into invideo as an MP4, then cut it with footage, a voice and music on a timeline your agent edits. It depends on what the video needs. Claude Motion makes short animations inside Claude from text, charts, shapes and images, and each animation is code, so you change one word, number or timing and the rest stays. invideo adds the video around the animation: real footage, a voiceover, music, captions, and a timeline where your agent and you edit together. Make the chart or the animated explainer in Claude Motion. Build the video that holds it in invideo. #### When to use both Use both when the animation is one part of a longer video. Common cases: - **A launch or release video.** An animated chart sits between product footage and a closing card. - **A narrated explainer.** The animation needs a voiceover, music and captions. - **A report for a team.** The numbers animate in Claude Motion, and the video goes to a team with the speaker on camera. - **Many cuts from one animation.** One animation goes into a 16:9 video and a 9:16 short, one branch each. #### Hand-off: from Claude Motion into invideo In Claude, open the animation, click **Export** and choose **MP4**. That file is what crosses into invideo. Your agent brings it in one of two ways. **With `add_media`.** This works for any agent that holds the MP4: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. **With `import-claude-motion-from-url`.** This is the official hand-off that Anthropic built with invideo: when you send a Claude Motion animation to invideo from Claude, Claude calls this tool on the invideo MCP server. It takes these fields: - **`url`**: the MP4's URL. It expires fast, so the server fetches it at once. - **`download_token`**: the access token for the file, given apart from the URL. The caller passes it through as it is. - **`title`**: a suggested title for the imported video. Optional. - **`claude_design_project_id`**: a stable id for the video, the same on every re-send. Send it again with the same id to update an import instead of making a new one. Optional. The tool takes no project URL; Claude fills the fields itself. You do not call it by hand. When your agent has the MP4 file itself, use `add_media`. Then the agent builds the video around the animation: - **Footage.** Your clips through `add_media`, or stock from `search_library` in `stock_video`. - **Voice.** `elevenlabs_text_to_speech.elevenlabs_tts_v4` with `generate`, with a voice from `search_library`. - **Music.** `search_library` in `stock_music`. - **Captions.** `media` `audio.transcript` on the voice, then `add_captions`. #### Hand-off: from invideo to Claude Motion Claude Motion makes animations from what you give Claude: text, charts, shapes and images. To use a frame from your invideo video there, your agent runs `export` with `format` `video`, `mode` `image` and `still_at`. You add that image to Claude. To change the animation itself, change it in Claude Motion, export a new MP4, and bring it in again. The agent swaps it in with `place_media` and `mode` `replace`, so the clip keeps its place and length. #### Steps Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent calls `add_media` with the MP4. Expected result: a sequence URL for the animation. The agent calls `new_timeline`, then makes a branch with `timeline_history`. Expected result: a timeline URL on a branch. The agent calls `edit_timeline` with `place_media` for each clip and the animation. Expected result: a new `state_token`. The agent runs `find_models` with the voice-over in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. The agent can search for others with `find_models`. It picks a `voice_id` with `search_library`, calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the voice lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent places the voice and a music clip from `search_library` with `place_media`. Expected result: a voice clip and a music clip under the picture. The agent runs `check_timeline` and `capture` at the animation's start and end, then `export`. Expected result: an export card with status `completed`. To swap in a new version of the animation, the agent sends this op. The fence is the bare list of ops that `--operations @ops.json` takes: ```json [ { "op": "place_media", "asset": "", "track": "V1", "at_f": 0, "source_start_seconds": 0, "source_end_seconds": 12, "mode": "replace", "replace_clip": "c4", "linked_audio": false } ] ``` `` is the `url` that `add_media` returns for the new MP4. `c4` is the old animation's clip id, from `get_timeline`. The voice from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo gen models --query "voice-over from a script" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo library search \ --library elevenlabs_text_to_speech_voices --query "calm" invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@script.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ -i prompt=@script.txt -i voice_id= \ --max-credits --idempotency-key voice-1 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. `` is an `id` that `invideo library search` returns. #### When to stay in Claude Motion Stay in Claude Motion when the animation is the whole video. A chart, a report or a short walkthrough that needs no footage, voice or music is done when you click **Export**. Move to invideo when the animation is one part of a video with other media, sound and a person reviewing the cut. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | A re-sent animation makes a second video instead of updating the first | Send it with the same `claude_design_project_id` as the first import. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [When to use Claude Motion vs invideo](/compare/claude-motion) - [Turn release notes or a changelog into a video every week](/how-to/training/release-notes-to-video) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Check your video before you say it is done](/how-to/check-your-video) - [invideo for AI agents](/agents) ### CapCut Source: https://docs.invideo.io/integrations/capcut.md Send an MP4 from invideo to CapCut for mobile finishing, or bring a CapCut export into invideo for an agent-driven edit. It depends on who finishes the video and where. CapCut is a video editor on mobile, desktop and the web, strong at quick edits, effects and finishing on a phone. invideo adds an agent that edits for you on a timeline, generation inside the same project, and branches a person reviews. What crosses between the two is a rendered MP4. Nothing editable moves across: CapCut says it does not support importing or exporting project files from third-party editing software. #### When to use both Use both when each tool does one half of the job. Common cases: - **Agent first, phone last.** Your agent makes the cut in invideo. You add a trend effect or a last sticker in CapCut on your phone. - **Phone first, agent next.** You cut the raw clips in CapCut. Your agent adds captions, music, a voiceover or more versions in invideo. - **One master, many posts.** A CapCut edit becomes the master. invideo makes one branch per platform from it. #### Hand-off: from CapCut into invideo In CapCut, click **Export** and choose the resolution. CapCut saves a video file. Then your agent brings it into invideo: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. The CapCut export is one flat clip. The agent cuts it again where it needs to, with `split_clip` and `delete_clip`, or finds the cuts with `media` `video.sceneSplit`. Then the agent finishes it: - **Captions.** `media` `audio.transcript`, then `add_captions` with slides and words. - **Music.** `search_library` in `stock_music`. - **Versions.** One branch per shape with `timeline_history`, then `set_timeline_settings` for the size. #### Hand-off: from invideo to CapCut Your agent runs `export` with `format` `video`. The result is a 1080p MP4. The agent reads the export card for the download URL, and you open the file in CapCut as a new project. For a phone, the agent sets `quality` and `target_lufs` on the export, and you send the file to the phone. In a terminal, `invideo notebook show` with `--out` saves it to a folder. Captions, text and music arrive burned into the picture. To change a caption after the hand-off, change it in invideo and export again. #### Steps Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent calls `add_media` with the MP4. Expected result: a sequence URL. The agent calls `new_timeline` at the size you post, then makes a branch with `timeline_history`. Expected result: a timeline URL on a branch. The agent places the clip with `place_media`, cuts where you asked, and places music from `search_library`. Expected result: a new `state_token` after each `edit_timeline` call. The agent prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a caption clip. The agent runs `find_models` with the voice-over in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. The agent can search for others with `find_models`. It picks a `voice_id` with `search_library`, calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the voice lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent runs `check_timeline` and `capture` at each caption and cut, then calls `export` with `format` `video` and an `idempotency_key`. Expected result: an export card with status `completed`. You open that file in CapCut. The same export from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo edit export --format video --quality 1080 \ --target-lufs -14 --idempotency-key "to-capcut-v1" --json invideo status --wait invideo notebook show --out ./to-capcut ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is the timeline's URL. `` is `.sequences[0]` of the export answer. The voice from a terminal: ```bash invideo gen models --query "voice-over from a script" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo library search \ --library elevenlabs_text_to_speech_voices --query "calm" invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@script.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ -i prompt=@script.txt -i voice_id= \ --max-credits --idempotency-key voice-1 ``` `` is the same project. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. `` is an `id` that `invideo library search` returns. #### When to stay in CapCut Stay in CapCut when you edit by hand on your phone, and the job is a quick post with its templates and effects. A short edit with no agent, no branches and no generation is faster there. Move to invideo when you want an agent to do the edit, a person to review it on a branch, or many versions from one cut. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | A caption is wrong after the hand-off | Captions arrive burned into the picture. Change the caption in invideo and export again. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [When to use CapCut vs invideo](/compare/capcut) - [Make a trend edit like CapCut: slow-mo, meme, freeze frame](/how-to/personal/trend-edit) - [Repurpose one video for every platform, one branch each](/how-to/creators/repurpose-for-every-platform) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [invideo for AI agents](/agents) ### VEED Source: https://docs.invideo.io/integrations/veed.md Add captions and subtitles in VEED or with the veed_subtitles model inside invideo, and move the video between the two as an MP4. It depends on how much editing the video needs. VEED is an online video editor known for its subtitles: Auto Subtitle writes captions from the speech, you style them, and you export the video with the subtitles burned in, or the subtitles as an SRT, VTT or TXT file. invideo adds a timeline your agent edits, generation in the same project, branches for review, and VEED's own subtitle model as a step your agent can run. The video crosses between the two as an MP4. Subtitle files cross as SRT. #### When to use both Use both when the captions and the edit happen in different places. Common cases: - **Edit in invideo, caption in VEED.** Your agent cuts the video. You caption it in VEED with its presets. - **Caption in VEED, finish in invideo.** You have a VEED video with subtitles. Your agent adds music, an intro and more versions. - **A VEED SRT on an invideo video.** You fixed the subtitles in VEED. The agent puts the same words on the invideo timeline. #### VEED inside invideo invideo runs VEED models, so some VEED steps never leave the project: - **`veed_subtitles`** (VEED Subtitles) burns styled, auto-transcribed subtitles into a video. It takes a `video` and a `preset`. It also takes your own subtitles as `srt_file` or `srt_content`, and then skips the transcription. - **`veed_video_bg_remove.veed_bg_standard`** and **`veed_video_bg_remove.veed_bg_fast`** remove a video's background. They are models of `media` `video.removeBackground`. - **`veed_lipsync_v2`** (Veed Lipsync v2) syncs a video to a new audio track. `veed_subtitles` makes a new video with the words in the picture. For captions you can still edit on the timeline, the agent uses `add_captions` instead. #### Hand-off: from VEED into invideo In VEED, export the project, then download it as an MP4. Download the subtitles as an SRT if you want to keep the words. Then your agent brings the video in: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. The agent reads the SRT file and writes its lines into `add_captions`, one slide per line, with times turned into frames at the timeline's rate. Or it passes the SRT to `veed_subtitles` as `srt_content`. #### Hand-off: from invideo to VEED Your agent runs `export` with `format` `video`. The result is a 1080p MP4. You upload it to VEED and run Auto Subtitle there. To send the subtitles as a file, the agent reads the caption slides with `get_timeline` mode `collection` and writes an SRT file. You upload that SRT to VEED with the video. #### Steps Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent calls `add_media` with the MP4 from VEED or your own file. Expected result: a sequence URL. For editable captions, the agent prices `audio.transcript` with `dry_run`, runs it, then sends `add_captions` on a timeline. For burned-in subtitles, it reads the inputs of `veed_subtitles` with `get_model`. Expected result: a plan it tells you, with the price for the paid step. The agent calls `generate` with `veed_subtitles`, the video's sequence URL, a `preset` and `dry_run: true`, and tells you the price. Expected result: a price and no charge. The agent calls `generate` again without `dry_run`, with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the video lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent looks at the result with `media` `video.frames`, checks that the subtitles sit inside the frame, then exports. Expected result: an MP4 you can post or send to VEED. The key MCP call, the full `generate` call, priced first: ```json { "url": "", "model": "veed_subtitles", "inputs": { "video": "", "preset": "simple", "position": "bottom" }, "dry_run": true } ``` `` is the `url` that `add_media` returns for the video. The same run from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo gen model --model veed_subtitles invideo gen run --model veed_subtitles --dry-run \ -i video= -i preset=simple -i position=bottom invideo gen run --model veed_subtitles \ -i video= -i preset=simple -i position=bottom \ --max-credits --idempotency-key subs-1 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. `` is the `url` that `invideo asset upload` returns for the video. #### When to stay in VEED Stay in VEED when you caption a finished clip by hand, with its presets, and want an SRT, VTT or TXT file as the output. A short clip with one round of subtitles is quick there. Move to invideo when an agent does the edit, when the captions must stay editable on a timeline, or when one video becomes many versions. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | `veed_subtitles` refuses an input | Read the inputs again with `get_model` and fix the field the refusal names. | | Subtitles show twice | The VEED download already had subtitles burned in. Download it without them, or skip `veed_subtitles`. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [When to use VEED vs invideo](/compare/veed) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Make an SRT captions file for an LMS](/how-to/training/srt-for-an-lms) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [invideo for AI agents](/agents) ### ElevenLabs Source: https://docs.invideo.io/integrations/elevenlabs.md Bring voice, music and sound from ElevenLabs into invideo as audio files, run ElevenLabs models inside invideo, or seed captions from a Scribe transcript. It depends on where you make the sound. ElevenLabs makes voice and audio: Text to Speech, Speech to Text with Scribe, Music, Sound effects, Dubbing and a Voice changer. invideo adds the picture and the timeline the sound sits on, and it runs several ElevenLabs models inside the project, so your agent makes the voice and places it in one place. Use ElevenLabs when your voices and projects live there. Use the ElevenLabs models in invideo when the agent should make the sound and the cut together. #### When to use both Use both when the sound comes from ElevenLabs and the video comes together in invideo. Common cases: - **A voiceover you made in ElevenLabs.** The agent places it under the footage and cuts the picture to it. - **A song or sound effects.** You made them in ElevenLabs Music or Sound effects. The agent places them on their own tracks. - **A transcript from Scribe.** You have the words with times. The agent turns them into captions. #### ElevenLabs inside invideo invideo runs these ElevenLabs models with `generate`. The agent reads each model's inputs with `get_model` first. | Model | What it makes | | --- | --- | | `elevenlabs_text_to_speech.elevenlabs_tts_v4` | A voiceover from text | | `elevenlabs_text_to_dialogue.generate_v4` | A dialogue between voices | | `elevenlabs_speech_to_speech.elevenlabs_sts_multilingual_v2` | A recording in another voice | | `elevenlabs_sfx` | A sound effect, with an option to loop | | `elevenlabs_music_v2_5_song` | A song with vocals | | `elevenlabs_music_v2_5_instrumental` | Music with no vocals | For a voice, the agent searches the model's voice library with `search_library`. For `elevenlabs_text_to_speech.elevenlabs_tts_v4`, `get_model` names it on the `voice_id` input: `elevenlabs_text_to_speech_voices`. Each voice has a `preview` you can play. Your workspace's cloned voices are in the list too. #### Hand-off: from ElevenLabs into invideo Download the audio from ElevenLabs. MP3 is its default format. Then your agent brings it in: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. The agent places the audio with `place_media` on an audio track and sets its level with `set_audio_gain`. **A Scribe transcript as captions.** Scribe gives each word with its start and end time. The agent turns each time into frames at the timeline's rate, groups the words into lines, and writes them into `add_captions` as slides with words. No `audio.transcript` run is needed, so the captions cost no credits. #### Hand-off: from invideo to ElevenLabs When you want to dub or change a voice in ElevenLabs, your agent exports the sound. `export` with `format` `video` and `mode` `audio` gives the audio alone, with `audio_format` `wav`, `aac` or `opus`. You upload that file to ElevenLabs. For the whole video, for example to dub it in ElevenLabs Dubbing, the agent exports with `mode` `video`. The result is a 1080p MP4. #### Steps Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent calls `add_media` for each ElevenLabs file. To make the voice in invideo, it calls `search_library` for a voice instead. Expected result: a sequence URL per file, or a voice `id`. The agent reads `elevenlabs_text_to_speech.elevenlabs_tts_v4` with `get_model` and sets the `prompt` text and the `voice_id`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the voice lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent makes a branch with `timeline_history`, then places the voice and music with `place_media`. Expected result: a new `state_token`. The agent writes `add_captions` from the Scribe words. With no transcript, it prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Expected result: captions that light up word by word. The agent checks the levels with `media` `audio.loudness`, runs `capture`, then `export` with `target_lufs`. Expected result: an export card with status `completed`. A caption slide written from Scribe words, at 30 frames a second. The fence is the bare list of ops that `--operations @ops.json` takes: ```json [ { "op": "add_captions", "track": "V2", "slides": [ { "text": "Welcome to the launch", "start_f": 0, "end_f": 45, "words": [ { "text": "Welcome", "start_f": 0, "end_f": 12 }, { "text": "to", "start_f": 12, "end_f": 18 }, { "text": "the", "start_f": 18, "end_f": 24 }, { "text": "launch", "start_f": 24, "end_f": 45 } ] } ] } ] ``` Each frame number is a Scribe time in seconds times the timeline's fps, from `get_timeline`. The voice from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo library search \ --library elevenlabs_text_to_speech_voices --query "calm" invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@script.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ -i prompt=@script.txt -i voice_id= \ --max-credits --idempotency-key voice-1 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. `` is an `id` that `invideo library search` returns. #### When to stay in ElevenLabs Stay in ElevenLabs when the job is audio alone: a podcast voice, an audiobook or a voice agent. ElevenLabs Dubbing also dubs a finished video there. Its own tools hold your voice library and your Studio projects. Move to invideo when the sound needs a picture, captions and a cut, and an agent that edits both together. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | `generate` refuses the `voice_id` | A voice id belongs to one model. Search `elevenlabs_text_to_speech_voices` for `elevenlabs_text_to_speech.elevenlabs_tts_v4`. | | Captions run ahead of or behind the voice | Scribe times are in seconds. Multiply each by the timeline's fps from `get_timeline`, then check a few frames with `capture`. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Use Whisper timings with invideo](/integrations/whisper) - [Dub existing footage](/how-to/training/dub-existing-footage) - [Models](/reference/models) ### Whisper timings Source: https://docs.invideo.io/integrations/whisper.md Turn a Whisper transcript, SRT or word JSON into an editable caption track on an invideo timeline, with each word timed as it is spoken. It depends on where your transcript comes from. Whisper, and any tool that writes SRT or word-level JSON, gives you captions and subtitles as timed text; invideo turns that text into an editable caption track on a real timeline, with each word highlighted as it is spoken. invideo also makes its own transcript with `media` `audio.transcript`. Bring Whisper's when you already have one, when a person corrected it, or when someone checked the language by hand. #### When to use both Use Whisper's timings in invideo when the transcript is already done and trusted. Use `audio.transcript` when you have no transcript at all. - **You already ran Whisper.** The transcript exists on your machine. Your agent reads it and places the captions, so no second transcript runs. - **A person corrected the words.** Names, product terms and jargon are fixed in the file. A new transcript would bring the old mistakes back. - **The language was checked.** Someone who speaks the language read the transcript. Keep their version. - **You want speakers or a fresh pass.** Run `audio.transcript`. It gives every word with its time and its speaker. #### Hand-off: from Whisper into invideo Whisper writes its transcript as a file. The `whisper` command takes `--output_format` with `txt`, `vtt`, `srt`, `tsv`, `json`, `jsonl` or `all`. The `--word_timestamps True` option adds a time for each word, which Whisper's own help marks as experimental. ```bash whisper interview.mp4 --model turbo --language English \ --word_timestamps True --output_format json ``` SRT gives one time per line, so each line becomes a caption slide. Word JSON gives a time per word, so each word gets its own highlight inside its slide. Your agent brings the video into the project: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. The transcript file does not go into the project. The agent reads it on your machine, or you paste it or attach it in a chat app. The agent then writes one `add_captions` op. Each slide has `text`, `start_f` and `end_f`, and an optional `words` list with the same three fields. Times are in frames at the timeline's rate, so the agent multiplies Whisper's seconds by the timeline's fps. Words must sit inside their slide, and slide text cannot be empty. The fence is the bare list of ops that `--operations @ops.json` takes: ```json [ { "op": "add_captions", "track": "V2", "slides": [ { "text": "Welcome back to the show", "start_f": 0, "end_f": 60, "words": [ { "text": "Welcome", "start_f": 0, "end_f": 18 }, { "text": "back", "start_f": 18, "end_f": 28 }, { "text": "to", "start_f": 28, "end_f": 34 }, { "text": "the", "start_f": 34, "end_f": 42 }, { "text": "show", "start_f": 42, "end_f": 60 } ] } ], "style": { "highlight_color": "#ffd400", "stroke": true } } ] ``` The frame numbers are Whisper's seconds times the timeline's fps, from `get_timeline`. The `text` values come from the transcript file. After that the captions are clips like any other. The agent fixes one line with `set_caption_slide_text`, splits a long slide with `split_caption_fragment`, and turns captions off for one export with `set_clip_enabled`. #### Hand-off: from invideo to Whisper Two things go the other way. For a caption file, the agent reads the caption slides with `get_timeline` mode `collection` and writes the SRT or VTT file itself. For a new Whisper run on the edited cut, the agent exports the sound with `export` mode `audio` and `audio_format` `wav`, then runs Whisper on that file. #### Steps Your agent sets up with [invideo for AI agents](/agents) first. Then it runs these steps on a branch. The agent calls `add_media` on the timeline URL, or `start_upload` then `add_media` for a local file. Expected result: a sequence URL and a media bin id. The agent reads the SRT or word JSON and lists each line with its start and end in seconds. Expected result: lines in time order with no empty text. If a line is empty, the agent drops it. The agent runs `media` `audio.content` on the video and compares the speech spans with the first and last lines. Expected result: the first word starts where speech starts. The agent creates a branch with `timeline_history`, reads the fps with `get_timeline`, and checks the fields with `timeline_catalog`. Then it sends `add_captions` in one `edit_timeline` call. Expected result: a new `state_token` and a caption clip. The agent calls `capture` at a few caption times and runs `check_timeline`. Expected result: words on screen match the sound and sit inside the frame. The agent calls `export` with `format` `video` and an `idempotency_key`. Expected result: an export card with status `completed`. Placing captions from your own transcript costs nothing. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. #### When to stay in Whisper Stay with Whisper alone when you need only a transcript or a caption file and no video. Stay with it too when the audio must not leave your machine, because Whisper runs locally. For translation of the speech into English text, Whisper has `--task translate`. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | Every caption starts early or late by the same amount | The transcript came from a trimmed file. Shift every time by the gap that `audio.content` shows. | | One caption line is wrong or off time | Fix it with `set_caption_slide_text` or `trim_caption_slide`. | | `add_captions` is refused | Each word must sit inside its slide, and slide text cannot be empty. Drop empty lines and check the frame numbers. | | Avoid: resend after a timeout | Instead: retry the same request with the same token. | #### Related - [Word-by-word captions](/how-to/creators/word-by-word-captions) - [SRT for an LMS](/how-to/training/srt-for-an-lms) - [Cut ums and retakes](/how-to/creators/cut-ums-and-retakes) - [Use ElevenLabs with invideo](/integrations/elevenlabs) - [Edit operations](/reference/edit-operations) - [Check your video before you say it is done](/how-to/check-your-video) ### HeyGen or Synthesia Source: https://docs.invideo.io/integrations/heygen-synthesia.md Bring a HeyGen or Synthesia avatar clip into invideo as an MP4, then add b-roll, text, music, captions and variants on a timeline. It depends on what the video needs around the presenter. HeyGen and Synthesia make the AI avatar, the talking presenter; invideo adds what goes around that clip on a real timeline, with b-roll, text, music, captions and a branch for each variant. #### When to use both Use both when the avatar is one part of a bigger edit. The avatar renders in HeyGen or Synthesia. The finish happens in invideo. - **The presenter needs cutaways.** Stock or generated b-roll covers the jumps and keeps the viewer's eye moving. - **The video needs a brand look.** Titles, lower thirds and logo go on as text and image clips you can change later. - **You test variants.** One avatar take, several hooks, shapes or end cards, each on its own branch. - **You want captions you can edit.** Captions come from a transcript as a caption track, not burned into the picture. #### Hand-off: from HeyGen or Synthesia into invideo The avatar clip crosses as an MP4. Download it, then bring it into the project. - **HeyGen.** The `heygen` CLI downloads a finished video by its id: `heygen video download --output-path ./avatar.mp4`. HeyGen's CLI can also fetch a version with captions burned in (`--asset captioned`). Take the clean version, so the captions stay editable in invideo. - **Synthesia.** Open the video's three-dot menu, choose **Download**, then the .mp4 option. Synthesia's help says videos with interactive elements, such as buttons or branching, cannot be downloaded. Then your agent brings it in: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. Then the finish: - **Place the avatar** with `place_media` and `linked_audio` set to true, so the voice comes with the picture. - **B-roll** from `search_library` in `stock_video`, or from `seedance_2_5.frames` with `generate`. Placed on the track above with `place_media` mode `place_on_top`. - **Text** with `add_text`, styled with `set_text_style`. - **Music** from `search_library` in `stock_music`, under the voice with the `ducker` audio effect. - **Captions** with `media` `audio.transcript` on the avatar clip, then `add_captions` with slides and words. #### Hand-off: from invideo to HeyGen or Synthesia The way back is an MP4. `export` with `format` `video` renders the timeline. Use the file wherever HeyGen or Synthesia takes an uploaded video, as their own docs describe. For a project in Premiere Pro, Final Cut Pro or DaVinci Resolve instead, see [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut). #### Steps Your agent sets up with [invideo for AI agents](/agents) first. Then it runs these steps on a branch. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent calls `start_upload` and `add_media` on the timeline URL. Expected result: a sequence URL and a media bin id. The agent creates a branch with `timeline_history`, then places the clip with `place_media` and `linked_audio`. Expected result: one video clip and its linked sound. The agent searches `stock_video` and `stock_music` with `search_library`, adds the picks with `add_media`, and places them with `edit_timeline`. Expected result: cutaways over the jumps, titles on screen, music under the voice. The agent runs `find_models` with the cutaway in words, picks one, and reads its inputs with `get_model`. A good pick is `seedance_2_5.frames`. The agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the cutaway lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a caption clip with each word timed. The agent creates a branch per variant with `timeline_history` and changes the hook, shape or end card on each. Expected result: one branch URL per variant. The agent calls `capture` and `check_timeline` on each branch, then `export`. Expected result: an export card with status `completed` per variant. A missing shot from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo gen models --query "office cutaway, hands typing" invideo gen model --model seedance_2_5.frames invideo gen run --model seedance_2_5.frames --dry-run \ -i prompt="office cutaway, hands typing" invideo gen run --model seedance_2_5.frames \ -i prompt="office cutaway, hands typing" \ --max-credits --idempotency-key shot-1 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. ##### The quick case, inside invideo When you need a short talking clip and no HeyGen or Synthesia account, invideo runs avatar and lip-sync models with `generate`. Your agent prices each with `dry_run` first. - `heygen_photo_avatar` turns one still photo and one audio clip into a talking video. - `heygen_video_1.generate` is HeyGen Video as a model. - `kling_avatar.std`, `kling_avatar.pro` and `omni_human_2` are other avatar models. - `heygen_lipsync` and `sync_lipsync_v3.video` replace a video's sound and re-animate the speaker's lips to match. The voice for a photo avatar comes from `elevenlabs_text_to_speech.elevenlabs_tts_v4` with `generate`, priced with `dry_run` first. #### When to stay in HeyGen or Synthesia Stay in the avatar tool when the job is the avatar itself. - **Your own trained avatar.** HeyGen's Digital Twin and Synthesia's personal avatar are trained on your footage. - **Courses in an LMS.** Synthesia exports SCORM and adds in-video quizzes and branching scenarios. - **Translation with the same face.** Both tools translate and dub their own avatar videos. - **Compositing elsewhere.** HeyGen renders avatar videos with a transparent background as WebM. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | Captions show twice on the avatar clip | The HeyGen download has captions burned in. Download the clean version, without `--asset captioned`. | | Synthesia shows no **Download** for a video | Synthesia's help says videos with interactive elements cannot be downloaded. Use a version without buttons or branching. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [UGC ad with an AI actor](/how-to/marketing/ugc-ad-with-ai-actor) - [When to use HeyGen or Synthesia vs invideo](/compare/heygen-synthesia) - [Test hooks on branches](/how-to/marketing/test-hooks-on-branches) - [Word-by-word captions](/how-to/creators/word-by-word-captions) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Models reference](/reference/models) ### HyperFrames Source: https://docs.invideo.io/integrations/hyperframes.md Bring a HyperFrames composition into invideo as an MP4, or have your agent rebuild it as an editable timeline, then add voice, music and captions. It depends on what you are making. HyperFrames is strong at motion graphics written as HTML, rendered by your coding agent; invideo is where that motion meets real footage, voice, music and captions on a timeline a person can review and change. Your agent brings the composition in as a rendered MP4, or rebuilds its elements on the timeline from the HTML. #### When to use both Use both when the motion piece is one part of a longer video. HyperFrames makes the animated parts. invideo cuts them together with everything else. - **Animated titles inside a real edit.** A title card, a chart or a product callout from HyperFrames sits between interview clips or b-roll. - **The voice and music come later.** You record or generate the voice after the motion is done, and mix it with music on the timeline. - **A person reviews the cut.** Someone without a code editor watches the timeline in the browser and leaves changes. - **Variants.** Several hooks or end cards, each on its own branch, around the same render. #### Hand-off: from HyperFrames into invideo There are two paths in. The render comes in as footage, or your agent rebuilds the composition as clips, text and keyframes. ##### Bring the render in as footage HyperFrames renders a composition with its CLI: ```bash npx hyperframes lint npx hyperframes render --output intro.mp4 ``` The HyperFrames docs list `mp4`, `webm`, `mov`, `gif`, `png-sequence` and `hls` as render formats. Use MP4 for the hand-off. Your agent knows these commands from the HyperFrames skills, installed with `npx skills add heygen-com/hyperframes`. They include `/hyperframes` for making and rendering, `/hyperframes-cli` for commands, and `/media-use` for music, voiceover and images. Then your agent brings the MP4 into invideo: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. The MP4 becomes a clip like any other. It is footage, so the text and shapes inside it are pixels, not editable layers. To keep them editable, take the second path. ##### Rebuild the composition on a timeline The second path keeps each element editable. Your agent reads the HTML, CSS and JavaScript: the root's `data-width` and `data-height`, each element's `data-start` and `data-duration`, and the GSAP tweens and rebuilds each element with edit operations, on a branch. [Rebuild a Remotion, HyperFrames or Tesseract composition as an editable timeline](/how-to/developers/composition-to-timeline) gives the steps. The mapping in short: - **Size and timing.** `set_timeline_settings` with the composition's size and `fps`. HyperFrames times are in seconds, so the agent multiplies them by the frame rate. CSS `z-index` sets the layer order. - **Text.** `add_text`, `set_text_style` and `style_text_range`, with fonts uploaded through `add_media`. - **Images and video.** `add_media`, then `insert_media` or `place_media`, with `set_position` and `set_zoom`. - **Motion.** `add_keyframe_lane` and `add_keyframes` for position and zoom, `set_keyframes` for opacity and rotation. - **Layers with no op.** Canvas, WebGL or a third-party component: render that layer alone in HyperFrames and place it as a clip. ##### The finish On either path, the agent finishes the video: - **Footage and b-roll** placed around the render with `place_media`, from your files or `search_library`. - **Voice** from `elevenlabs_text_to_speech.elevenlabs_tts_v4` with `generate`, or your own recording. - **Music** from `search_library` in `stock_music`, mixed with `set_audio_gain` and `set_audio_fades`. - **Captions** with `media` `audio.transcript` on the voice, then `add_captions`. #### Hand-off: from invideo to HyperFrames The way back is an MP4. `export` with `format` `video` renders the timeline, and a HyperFrames composition takes it as a video clip, as the HyperFrames guide "Add images and video clips" describes. For an editor, `export` with `format` `premiere`, `davinci` or `final_cut` makes a project file for Premiere Pro, DaVinci Resolve or Final Cut Pro. #### Steps Your agent sets up with [invideo for AI agents](/agents) first. These steps follow the render path. For the rebuild, your agent follows the steps on the rebuild page. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent runs `npx hyperframes lint`, fixes the errors, then renders to MP4. Expected result: an MP4 on disk. The agent calls `start_upload`, puts the bytes, then `add_media` on the timeline URL. Expected result: a sequence URL and a media bin id. The agent creates a branch with `timeline_history` and places the render, footage and music with `edit_timeline`. Expected result: a new `state_token`. If you have no recording, the agent runs `find_models` with the voice-over in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. The agent can search for others with `find_models`. It picks a `voice_id` with `search_library`, calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the voice lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a caption clip. The agent calls `capture` at the joins between the render and the footage, and `check_timeline`. Then it calls `export`. Expected result: an export card with status `completed`. The voice from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo gen models --query "voice-over from a script" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo library search \ --library elevenlabs_text_to_speech_voices --query "calm" invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@script.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ -i prompt=@script.txt -i voice_id= \ --max-credits --idempotency-key voice-1 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. `` is an `id` that `invideo library search` returns. #### When to stay in HyperFrames Stay in HyperFrames when the whole video is motion graphics from code and nobody else edits it. Stay there too when you need what invideo's `export` does not make: a transparent render (HyperFrames keeps transparency in WebM and MOV), a GIF, or an HLS stream. For changes to a rendered animation, change the HTML and render again, then swap the clip in invideo with `place_media` mode `replace`. After a rebuild, change the element on the timeline instead. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | Text in the render cannot be changed in invideo | It is part of the picture. Rebuild that text with `add_text`, or change the HTML, render again, and replace the clip with `place_media` mode `replace`. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [When to use HyperFrames vs invideo](/compare/hyperframes) - [Use Remotion with invideo](/integrations/remotion) - [Intro, outro and logo animation](/how-to/creators/intro-outro-logo-animation) - [Launch video](/how-to/marketing/launch-video) - [Rebuild a composition as an editable timeline](/how-to/developers/composition-to-timeline) - [Check your video before you say it is done](/how-to/check-your-video) Not as a file. Your agent reads the HTML, CSS and JavaScript and rebuilds the elements as clips, text and keyframes you can edit. A rendered MP4 stays one clip: its text, shapes and timing are part of the picture, so a change to it means a new render in HyperFrames. Yes. When the render has sound, your agent places it with `place_media` and `linked_audio` set to true. The sound then moves with the picture on the timeline. ### Remotion Source: https://docs.invideo.io/integrations/remotion.md Bring a Remotion composition into invideo as an MP4, or have your agent rebuild it as an editable timeline, then finish it with voice, music and captions. It depends on who edits the video after the code. Remotion makes video from React code, rendered by you or your coding agent; invideo is where that video meets footage, voice, music and captions on a timeline a person can review and change without touching the code. Your agent brings the composition in as a rendered MP4, or rebuilds its elements on the timeline from the source. #### When to use both Use both when the Remotion render is one part of a finished video. The animated parts come from code. The edit around them happens in invideo. - **Data and motion inside a real edit.** A chart, a map route or a product callout from Remotion sits between interview clips or b-roll. - **The voice and music come later.** You add and mix them on a timeline, not in code. - **A person reviews the cut.** Someone without a code editor watches the timeline in the browser and asks for changes. - **Variants.** Several hooks or end cards on branches, around the same render. #### Hand-off: from Remotion into invideo There are two paths in. The render comes in as footage, or your agent rebuilds the composition as clips, text and keyframes. ##### Bring the render in as footage Remotion renders a composition by its id: ```bash npx remotion render MyComposition out/intro.mp4 ``` Without `--codec`, Remotion uses the H.264 encoder, and without an output path it writes to the `out` folder. You can also render from Remotion Studio with the **Render video** button. Your agent knows these steps from the Remotion skills, installed with `npx skills add remotion-dev/skills`, such as `/remotion-render` and `/remotion-docs`. Remotion has no hosted MCP server. It points agents at the `/remotion-docs` skill. Then your agent brings the MP4 into invideo: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. The MP4 becomes a clip like any other. It is footage, so the text and shapes inside it are pixels, not editable layers. To keep them editable, take the second path. ##### Rebuild the composition on a timeline The second path keeps each element editable. Your agent reads the React component: its `` size and `fps`, each `` with `from` and `durationInFrames`, and the values that `interpolate` and `spring` animate and rebuilds each element with edit operations, on a branch. [Rebuild a Remotion, HyperFrames or Tesseract composition as an editable timeline](/how-to/developers/composition-to-timeline) gives the steps. The mapping in short: - **Size and timing.** `set_timeline_settings` with the composition's size and `fps`. With the same `fps`, Remotion frame numbers copy over as they are. - **Text.** `add_text`, `set_text_style` and `style_text_range`, with fonts uploaded through `add_media`. - **Images and video.** `add_media`, then `insert_media` or `place_media`, with `set_position` and `set_zoom`. - **Motion.** `add_keyframe_lane` and `add_keyframes` for position and zoom, `set_keyframes` for opacity and rotation. - **Layers with no op.** Canvas, WebGL or a third-party component: render that layer alone in Remotion and place it as a clip. ##### The finish On either path, the agent finishes the video: - **Footage and b-roll** placed around the render with `place_media`, from your files or `search_library`. - **Voice** from `elevenlabs_text_to_speech.elevenlabs_tts_v4` with `generate`, or your own recording. - **Music** from `search_library` in `stock_music`, mixed with `set_audio_gain` and `set_audio_fades`. - **Captions** with `media` `audio.transcript` on the voice, then `add_captions`. ##### Text animation without Remotion For animated text on a clip inside invideo, your agent has three routes. `add_text` with `set_keyframes` animates text on the timeline, and edits are free. The models `dynamic_text.diy` and `dynamic_text.styles` make animated text. The model `uc_remotion_text` burns exact text onto a video as a single-font animated overlay. The models cost credits, so the agent prices them with `dry_run` first. #### Hand-off: from invideo to Remotion The way back is an MP4. `export` with `format` `video` renders the timeline, and a Remotion composition plays it with the `` component, from a URL or a local file. For an editor, `export` with `format` `premiere`, `davinci` or `final_cut` makes a project file for Premiere Pro, DaVinci Resolve or Final Cut Pro. #### Steps Your agent sets up with [invideo for AI agents](/agents) first. These steps follow the render path. For the rebuild, your agent follows the steps on the rebuild page. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent runs `npx remotion render` with the composition id and an output path. Expected result: an MP4 on disk. The agent calls `start_upload`, puts the bytes, then `add_media` on the timeline URL. Expected result: a sequence URL and a media bin id. The agent creates a branch with `timeline_history` and places the render, footage and music with `edit_timeline`. Expected result: a new `state_token`. If you have no recording, the agent runs `find_models` with the voice-over in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. The agent can search for others with `find_models`. It picks a `voice_id` with `search_library`, calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the voice lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a caption clip. The agent calls `capture` at the joins between the render and the footage, and `check_timeline`. Then it calls `export`. Expected result: an export card with status `completed`. The voice from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo gen models --query "voice-over from a script" invideo gen model \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 invideo library search \ --library elevenlabs_text_to_speech_voices --query "calm" invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \ -i prompt=@script.txt -i voice_id= invideo gen run \ --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \ -i prompt=@script.txt -i voice_id= \ --max-credits --idempotency-key voice-1 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. `` is an `id` that `invideo library search` returns. #### When to stay in Remotion Stay in Remotion when the video is data-driven and made from code end to end, such as one render per user or per row. Stay there too for what invideo's `export` does not make, such as other codecs like ProRes or an image sequence. For a change to a rendered animation, change the code and render again, then swap the clip in invideo with `place_media` mode `replace`. After a rebuild, change the element on the timeline instead. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | Remotion shows a composition picker, and the render waits | Name the composition id in `npx remotion render`. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [When to use Remotion vs invideo](/compare/remotion) - [Use HyperFrames with invideo](/integrations/hyperframes) - [CSV to videos](/how-to/developers/csv-to-videos) - [Rebuild a composition as an editable timeline](/how-to/developers/composition-to-timeline) - [Intro, outro and logo animation](/how-to/creators/intro-outro-logo-animation) - [Check your video before you say it is done](/how-to/check-your-video) Not as a file. Your agent reads the React source and rebuilds the elements as clips, text and keyframes you can edit. A rendered MP4 stays one clip: its text, shapes and timing are part of the picture, so a change to it means a new render in Remotion. Yes. When the render has sound, your agent places it with `place_media` and `linked_audio` set to true. The sound then moves with the picture on the timeline. ### OpenEdit Source: https://docs.invideo.io/integrations/openedit.md Caption a clip with OpenEdit on your machine, bring its MP4 into invideo as footage, and finish it with stock, music, generation and a timeline review. It depends on how much of the video you need. OpenEdit, VEED's open-source editing pipeline, burns captions and subtitles onto a clip from your coding agent; invideo adds the timeline a person can review, plus generation, stock and music around that clip. #### When to use both Use both when the captioned clip is one part of a finished video. OpenEdit does the captions on your machine. invideo does the rest of the edit. - **A captioned clip inside a longer cut.** The talking-head clip from OpenEdit sits between b-roll, titles and an end card. - **Stock and music around it.** invideo searches stock video and music and places them on tracks. - **Generated shots.** A missing shot or a product close-up comes from a video model in the same project. - **A person reviews the cut.** Someone opens the timeline in the browser, sees each clip on its own track, and asks for changes. #### Hand-off: from OpenEdit into invideo OpenEdit's finished file is an MP4 with the subtitles burned in. It lands under the `runs/` folder in your project, and the agent reports its path. Install OpenEdit's skill in your coding agent with this command: ```bash npx skills add veedstudio/open-edit --skill open-edit ``` OpenEdit transcribes in one of three ways: hosted by VEED with a veed.io account, with WhisperX on your machine, or from Whisper-family JSON your own service makes. With WhisperX, OpenEdit's README says nothing leaves your machine. Then your agent brings the MP4 into invideo: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. The MP4 becomes a clip like any other. Its captions are part of the picture, so invideo cannot restyle them or turn them off. Then the finish: - **Stock** from `search_library` in `stock_video` and `stock_image`, placed with `place_media`. - **Music** from `search_library` in `stock_music`, under the voice with the `ducker` audio effect. - **Generated shots** from a model such as `seedance_2_5.r2v` with `generate`, priced with `dry_run` first. - **Titles and an end card** with `add_text` and `set_text_style`. If you want captions you can change later, bring the clip without captions instead. Your agent then makes them in invideo with `media` `audio.transcript` and `add_captions`, or reads OpenEdit's own transcript JSON and places it as the [Whisper page](/integrations/whisper) shows. #### Hand-off: from invideo to OpenEdit The way back is an MP4. `export` with `format` `video` renders the timeline. OpenEdit takes a video file from your disk, so your agent downloads the export and gives OpenEdit its path. #### Steps Your agent sets up with [invideo for AI agents](/agents) first. Then it runs these steps. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent uses the `/open-edit` skill to caption the clip. If OpenEdit asks which transcription to use, the agent asks you. Expected result: an MP4 path under `runs/`. The agent calls `start_upload`, puts the bytes, then `add_media` on the timeline URL. Expected result: a sequence URL and a media bin id. The agent creates a branch with `timeline_history`, then places the clip, stock and music with `edit_timeline`. Expected result: a new `state_token`. The agent runs `find_models` with the missing shot in words, picks one, and reads its inputs with `get_model`. A good pick is `seedance_2_5.r2v`. The agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the shot lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent calls `capture` at a few caption times. Expected result: no caption covered by a title or cut off by a crop. The agent runs `check_timeline`, then calls `export`. Expected result: an export card with status `completed`. A missing shot from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo gen models --query "close-up of the product on a desk" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ -i prompt="close-up of the product on a desk" invideo gen run --model seedance_2_5.r2v \ -i prompt="close-up of the product on a desk" \ --max-credits --idempotency-key shot-1 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. #### When to stay in OpenEdit Stay in OpenEdit when the job is captions on one clip and nothing else. Stay there too when the audio must stay on your machine, with WhisperX. If you want a person to change the edit in VEED's editor, OpenEdit hands its edit to VEED as a project, as its README describes. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | A title covers a burned-in caption | Move the title or the clip with `set_position`, then `capture` again. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [When to use OpenEdit vs invideo](/compare/openedit) - [Use Whisper timings with invideo](/integrations/whisper) - [Use VEED with invideo](/integrations/veed) - [Word-by-word captions](/how-to/creators/word-by-word-captions) - [Reels and Shorts from your footage](/how-to/creators/reels-and-shorts-from-your-footage) No. OpenEdit burns the captions into the picture, so they are pixels in the MP4. For captions you can restyle, bring the clean clip and make the captions in invideo. ### Tesseract Source: https://docs.invideo.io/integrations/tesseract.md Bring a Tesseract edit into invideo as an MP4, or have your agent rebuild it as an editable timeline, then finish it with generation, stock and music. It depends on where the edit lives. Tesseract, from Mirage, edits and renders video on your computer through your AI agent; invideo is a cloud editor where your agent and the people you share with work on the same timeline, with generation, stock and music in the project. Your agent brings the edit in as a rendered MP4, or rebuilds its layers on the timeline. #### When to use both Use both when the Tesseract cut is one part of a bigger job, or when other people need to review it in a browser. - **A shared review.** Someone opens the invideo timeline from its URL and sees each clip on its own track. - **Generation and stock.** A missing shot, a voice or a music bed comes from a model or the stock library in the same project. - **Variants.** Several hooks, shapes or end cards around the same Tesseract render, each on its own branch. - **Captions on the finished cut.** A transcript of the whole edit becomes a caption track. #### Hand-off: from Tesseract into invideo There are two paths in. The render comes in as footage, or your agent rebuilds the edit as clips, text and keyframes. ##### Bring the render in as footage On this path, what crosses is an MP4 render. Tesseract's site says to keep the editable project and its source assets with the finished render. The `.tsrct` project stays with Tesseract for later changes. Install Tesseract's skills in your coding agent with this command: ```bash npx skills add mirage-hq/Tesseract ``` Then your agent brings the MP4 into invideo: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. The MP4 becomes a clip like any other. It is footage, so the layers inside it are part of the picture. To keep them editable, take the second path. ##### Rebuild the composition on a timeline The second path keeps each element editable. Your agent reads the edit in the `.tsrct` project, takes the media and fonts the project carries, and has Tesseract render single layers where it needs to. Then it rebuilds each element with edit operations, on a branch. [Rebuild a Remotion, HyperFrames or Tesseract composition as an editable timeline](/how-to/developers/composition-to-timeline) gives the steps. The mapping in short: - **Size and timing.** `set_timeline_settings` with the composition's size and `fps`. The agent converts each layer's times to frames at that rate. - **Text.** `add_text`, `set_text_style` and `style_text_range`, with fonts uploaded through `add_media`. - **Images and video.** `add_media`, then `insert_media` or `place_media`, with `set_position` and `set_zoom`. - **Motion.** `add_keyframe_lane` and `add_keyframes` for position and zoom, `set_keyframes` for opacity and rotation. - **Layers with no op.** Canvas, WebGL or a third-party component: render that layer alone in Tesseract and place it as a clip. ##### The finish On either path, the agent finishes the video: - **Stock** from `search_library` in `stock_video` and `stock_music`, placed with `place_media`. - **Generated shots** from a model such as `seedance_2_5.r2v` with `generate`, priced with `dry_run` first. - **Voice** from `elevenlabs_text_to_speech.elevenlabs_tts_v4` with `generate`. - **Captions** with `media` `audio.transcript`, then `add_captions`. #### Hand-off: from invideo to Tesseract The way back is an MP4 too. `export` with `format` `video` renders the timeline. Your agent downloads the export and gives Tesseract the file as footage, the way it gives Tesseract any clip. ##### Premiere Pro and After Effects Tesseract handles its own round trips with Adobe apps through its converter tool, `tsrct-conv`. Its README says it converts Premiere Pro `.prproj` files both ways and After Effects `.aep` files, and warns that some features may not convert exactly. invideo's `export` with `format` `premiere`, `davinci` or `final_cut` makes a project file for Premiere Pro, DaVinci Resolve or Final Cut Pro. #### Steps Your agent sets up with [invideo for AI agents](/agents) first. These steps follow the render path. For the rebuild, your agent follows the steps on the rebuild page. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. The agent asks Tesseract for an MP4 of the edit and keeps the `.tsrct` project. Expected result: an MP4 path on disk. The agent calls `start_upload`, puts the bytes, then `add_media` on the timeline URL. Expected result: a sequence URL and a media bin id. The agent creates a branch with `timeline_history`, then places stock, music and voice with `edit_timeline`. Expected result: a new `state_token`. The agent runs `find_models` with the missing shot in words, picks one, and reads its inputs with `get_model`. A good pick is `seedance_2_5.r2v`. The agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the shot lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a caption clip. The agent calls `capture` at each join and runs `check_timeline`. Then it calls `export`. Expected result: an export card with status `completed`. A missing shot from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo gen models --query "close-up of the product on a desk" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ -i prompt="close-up of the product on a desk" invideo gen run --model seedance_2_5.r2v \ -i prompt="close-up of the product on a desk" \ --max-credits --idempotency-key shot-1 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. #### When to stay in Tesseract Stay in Tesseract when the whole edit happens on your computer and nobody else needs to review it. Stay there too when you work with Premiere Pro or After Effects projects through its converter. For a change to a rendered Tesseract edit, give your agent the `.tsrct` project, render again, and replace the clip in invideo with `place_media` mode `replace`. After a rebuild, change the layer on the timeline instead. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | `add_media` refuses the `.tsrct` project | invideo takes video, image, audio and font files. Ask Tesseract for an MP4 render, or have your agent rebuild the layers from the project. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [When to use Tesseract vs invideo](/compare/tesseract) - [Use ChatCut with invideo](/integrations/chatcut) - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) - [Test hooks on branches](/how-to/marketing/test-hooks-on-branches) - [Rebuild a composition as an editable timeline](/how-to/developers/composition-to-timeline) - [Check your video before you say it is done](/how-to/check-your-video) Not as a file. Your agent reads the project and rebuilds its layers as clips, text and keyframes, or brings in an MP4 render. Keep the `.tsrct` project in Tesseract either way. ### ChatCut Source: https://docs.invideo.io/integrations/chatcut.md Cut talking footage by its transcript in ChatCut, bring the cut into invideo as an MP4, and finish with generation, stock, music and a shared review. It depends on where you want to cut. ChatCut edits video by its transcript, so you delete words and reorder paragraphs and the timeline follows; invideo adds generation, stock, music and a project that people and agents edit together, and it can do the transcript edit too. #### When to use both Use both when the transcript cut is done in ChatCut and the rest of the video is not. - **Generated shots and stock.** A missing shot, a product close-up or b-roll comes from a model or the stock library in the same project. - **Music and voice.** A music bed and a voice-over go on their own tracks and get mixed there. - **Collaboration.** Agents and people work in the same invideo project, and the person reviews each branch in the browser. - **Variants.** Several hooks, shapes or end cards around the same cut, each on its own branch. #### Hand-off: from ChatCut into invideo The cut comes in as an MP4. Export the finished cut from ChatCut as a video file, from the ChatCut desktop app or the web app at app.chatcut.io. ChatCut's site also lists an XML export for DaVinci Resolve, CapCut, Premiere and Final Cut Pro. invideo takes the video file, not the XML. Then your agent brings the MP4 into invideo: - **A public link.** `add_media` with `media_url`. - **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload `. - **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`. Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin. The agent places the cut with `place_media` and `linked_audio` set to true, so the voice comes with the picture. Then the finish: - **Stock** from `search_library` in `stock_video`, placed with `place_media` mode `place_on_top`. - **Generated shots** from a model such as `seedance_2_5.r2v` with `generate`, priced with `dry_run` first. - **Music** from `search_library` in `stock_music`, under the voice with the `ducker` audio effect. - **Captions** with `media` `audio.transcript` on the cut, then `add_captions`. #### Hand-off: from invideo to ChatCut The way back is an MP4. `export` with `format` `video` renders the timeline, and you bring the file into ChatCut as footage. When the cut goes on to an editor, `export` with `format` `premiere`, `davinci` or `final_cut` makes a project file for Premiere Pro, DaVinci Resolve or Final Cut Pro. #### The transcript edit inside invideo You can also do the transcript cut in invideo and skip the hand-off. Your agent reads the words, picks what to cut, and cuts it on the timeline. 1. The agent prices `media` `audio.transcript` with `dry_run`, then runs it on the clip. It gets every word with its time and speaker. 2. The agent runs `audio.content` for the spans of speech and silence. 3. The agent picks the ums, retakes and long pauses to cut, by reading the words. 4. The agent cuts each span with `edit_time_range` mode `close_gap`, all in one `edit_timeline` call, ordered last span first. Each closed gap moves everything after it earlier, so cutting from the end keeps the earlier frame numbers true. Times in `edit_time_range` are frames, so the agent multiplies the transcript's seconds by the timeline's fps. The full recipe is on [Cut ums and retakes](/how-to/creators/cut-ums-and-retakes). #### Steps Your agent sets up with [invideo for AI agents](/agents) first. Then it runs these steps for the hand-off. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. You or your agent export the cut as a video file. Expected result: an MP4 on disk. The agent calls `start_upload`, puts the bytes, then `add_media` on the timeline URL. Expected result: a sequence URL and a media bin id. The agent creates a branch with `timeline_history`, then places the cut, stock and music with `edit_timeline`. Expected result: a new `state_token`. The agent runs `find_models` with the missing shot in words, picks one, and reads its inputs with `get_model`. A good pick is `seedance_2_5.r2v`. The agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge. The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the shot lands. The agent reads that URL with `read`, and never calls `generate` again to check. The agent prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a caption clip. The agent calls `capture` at each join and runs `check_timeline`. Then it calls `export`. Expected result: an export card with status `completed`. A missing shot from a terminal: ```bash invideo agent register --name export INVIDEO_AS= invideo gen models --query "close-up of the product on a desk" invideo gen model --model seedance_2_5.r2v invideo gen run --model seedance_2_5.r2v --dry-run \ -i prompt="close-up of the product on a desk" invideo gen run --model seedance_2_5.r2v \ -i prompt="close-up of the product on a desk" \ --max-credits --idempotency-key shot-1 ``` `` comes from `invideo project new` or `list_projects`. `` is the name you choose in `invideo agent register`. `` is a page that `invideo notebook show ` lists. `` is the price the dry run returns. #### When to stay in ChatCut Stay in ChatCut when you want to cut by editing text with your own hands, in its transcript panel. Stay there too when the cut goes on to DaVinci Resolve, CapCut, Premiere or Final Cut Pro through ChatCut's XML export. #### If something goes wrong | Symptom | Fix | | --- | --- | | `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. | | `add_media` refuses ChatCut's XML export | invideo takes video, image and audio files. Export the cut from ChatCut as an MP4. | | `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. | | Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. | #### Related - [When to use ChatCut vs invideo](/compare/chatcut) - [Cut ums and retakes](/how-to/creators/cut-ums-and-retakes) - [Podcast edit and clips](/how-to/creators/podcast-edit-and-clips) - [Edit a long YouTube video](/how-to/creators/edit-a-long-youtube-video) - [Use Tesseract with invideo](/integrations/tesseract) No. `add_media` takes video, image and audio files, so the cut crosses as an MP4. Use ChatCut's XML for the editing apps it lists. ## Compare ### AI video tools compared Source: https://docs.invideo.io/compare/alternatives.md A neutral roundup of AI video tools by job: generate, edit, caption, avatars, code motion, NLE finishing and batch renders, with invideo as one entry. This page lists AI video tools and video editors by the job you want done. Each tool gets one paragraph, written from its own product pages. invideo is one entry here and gets the same plain treatment. Where a tool has its own compare page, the paragraph links to it. Each paragraph was checked against the tool's own pages on 29 October 2026. Tools change, so check the tool's own site before you decide. #### Generate shots from a prompt These tools make new video from text, images or references. Most of them do not edit a whole video around the shots. - **Runway.** Runway makes video models, Gen-4.5 among them, and calls its web app "an all-in-one cloud-based creative platform". It also has an API and plugins that bring its models into Premiere Pro and After Effects. See [When to use Runway vs invideo](/compare/runway). - **Higgsfield.** Higgsfield is a generation studio: video, images and voice from prompts or references, with presets, face swap and an "AI Influencer" builder. It has an MCP server for Claude. See [When to use Higgsfield vs invideo](/compare/higgsfield). - **Magnific.** Magnific is known for its image and video upscalers. Its MCP server lets an agent trim, join, grade and upscale clips, and deliver ProRes or DNxHR files. See [When to use Magnific vs invideo](/compare/magnific). - **Lovart.** Lovart calls itself an "AI Design Agent". You describe a poster or a menu and it makes the design. It is for still design assets, not a video timeline. See [When to use Lovart vs invideo](/compare/lovart). #### Edit footage you already have These tools take your own recordings and help you cut them. - **CapCut.** CapCut is a free editor on mobile, desktop and the web, with templates, auto captions and AI tools. It is built for quick social edits by hand. See [When to use CapCut vs invideo](/compare/capcut). - **Descript.** Descript transcribes your recording and lets you "Edit your words to edit your video". It cuts filler words in a click, and its AI editor Underlord makes a first cut. See [When to use OpusClip or Descript vs invideo](/compare/opusclip-descript). - **ChatCut.** ChatCut is a chat and transcript editor on macOS, Windows and the web. It exports an XML timeline for Premiere Pro and DaVinci Resolve, and editable CapCut drafts. See [When to use ChatCut vs invideo](/compare/chatcut). - **Tesseract.** Tesseract is an agent-run editor that "edits and renders on your computer". You keep an editable `.tsrct` project and share the MP4. See [When to use Tesseract vs invideo](/compare/tesseract). - **invideo.** invideo is a cloud video editor with a real timeline. Your agent works in the same project as you, through the CLI in a terminal or MCP in a chat app, and you see each edit land in the browser. It generates shots with many models, cuts footage, and adds captions, music and voice. Edits and exports are free. invideo needs a connection and has no offline mode. #### Captions and repurposing These tools turn one video into captioned clips for each platform. - **OpusClip.** OpusClip "turns long videos into high-quality viral clips", adds captions you can edit, and reframes for each platform. It has an API. See [When to use OpusClip or Descript vs invideo](/compare/opusclip-descript). - **VEED.** VEED is an online editor known for its subtitles. It also has translation, dubbing, avatars, a screen recorder and AI generation. See [When to use VEED vs invideo](/compare/veed). - **OpenEdit.** OpenEdit is VEED's open-source editor that your agent runs. It started with captions on a clip. It renders on your own Mac, and transcription runs through a veed.io account. See [When to use OpenEdit vs invideo](/compare/openedit). - **Pictory and Lumen5.** Both turn a blog post, a script or a URL into a video with stock visuals and templates. See [When to use Pictory or Lumen5 vs invideo](/compare/pictory-lumen5). #### Avatars and presenters These tools put a talking person on screen from a script. - **HeyGen.** HeyGen makes avatar videos and translates video with voice cloning and lip sync. It has APIs and exports SCORM packages for an LMS. See [When to use HeyGen or Synthesia vs invideo](/compare/heygen-synthesia). - **Synthesia.** Synthesia makes "Lifelike avatars from a script" for training, onboarding and sales. It publishes as a link, an embed or SCORM, and dubs existing videos. See [When to use HeyGen or Synthesia vs invideo](/compare/heygen-synthesia). #### Code motion These tools write video as code. They suit developers, charts and product motion. - **Remotion.** Remotion lets you "Create videos & motion graphics with React". You render on your own machines or in the cloud. Its license has separate terms for companies. See [When to use Remotion vs invideo](/compare/remotion). - **HyperFrames.** HyperFrames makes HTML video compositions with an agent and renders to MP4 on your computer. See [When to use HyperFrames vs invideo](/compare/hyperframes). - **Claude Motion.** Claude Motion is a beta feature in Claude that builds short animations of text, charts, shapes and images as code. It does not make realistic footage or people. See [When to use Claude Motion vs invideo](/compare/claude-motion). #### Finishing in an NLE An NLE (non-linear editor) is a desktop editing app for the final cut, the grade and the mix. - **DaVinci Resolve.** DaVinci Resolve has edit, color, Fusion effects and Fairlight audio in one app, on Mac, Windows and Linux. There is a free version and a paid Studio version. - **Premiere Pro.** Premiere Pro is Adobe's editor, with AI transcription, Firefly features and Generative Extend. It runs on desktop, with a mobile app too. See [When to use DaVinci Resolve or Premiere Pro vs invideo](/compare/davinci-resolve-premiere). #### Batch rendering These tools render many videos from one template through an API. - **Creatomate.** Creatomate is "the creative automation platform for developers and no-code users". It renders from templates or JSON, takes a spreadsheet for bulk runs, and connects to Zapier, Make and n8n. - **Shotstack.** Shotstack is a video editing API that says it can "Render thousands of videos in minutes". It has SDKs, sandbox and production API keys, an MCP server and a CLI. See [When to use Creatomate or Shotstack vs invideo](/compare/creatomate-shotstack). #### How to pick Start from the job, not the tool. The table names the group to read first. | You want | Read first | | --- | --- | | New shots from a prompt | Generate shots from a prompt | | A cut of your own recording | Edit footage you already have | | Captioned clips for every platform | Captions and repurposing | | A presenter on screen | Avatars and presenters | | Charts or product motion in code | Code motion | | A final grade and mix | Finishing in an NLE | | Many videos from one template | Batch rendering | Many teams use two tools: one to generate or record, and one to edit. invideo can take files from any tool on this page with `add_media`. For an NLE, `export` with `format` `premiere`, `davinci` or `final_cut` makes a project file for Premiere Pro, DaVinci Resolve or Final Cut Pro. #### Related - [invideo for AI agents](/agents) - [Is there an invideo API?](/api) - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) - [Finish an AI clip from Higgsfield, Runway or Magnific](/how-to/marketing/finish-an-ai-clip) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### CapCut Source: https://docs.invideo.io/compare/capcut.md CapCut for quick edits by hand on your phone and a free editor. invideo when your agent does the edit and the captions stay editable. Use CapCut when you edit by hand on your phone and want a free editor with templates. Use invideo when you want your agent to do the edit, and you want to change the cut and the captions afterwards. Both tools edit video and add auto captions (subtitles). The difference is who does the work. In CapCut, you tap through the edit yourself. In invideo, your agent runs the edit on a cloud timeline and you review it. #### One brief, two tools The brief: a 30 second vertical reel from a folder of phone clips, with word-by-word captions and music. **In CapCut.** You open the mobile app, pick a template or start a blank project, and add your clips. You trim each clip, turn on auto captions, and pick a style and a track. Then you export and post. It is fast when you know the app, and every change is a tap. **In invideo.** You tell your agent where the clips are. The agent uploads them with `start_upload` and `add_media`, transcribes the speech with `media` `audio.transcript`, and builds a 9:16 timeline on a branch. It cuts on the best lines, adds captions with `add_captions`, and adds music from `search_library`. It checks frames with `capture`, then exports with `export`. You open the timeline URL and change anything by hand or by asking again. #### At a glance Checked on 29 October 2026 against CapCut's site. It may change. | | CapCut | invideo | | --- | --- | --- | | Editable timeline after the cut | Yes, in the app | Yes, on a branch you can review | | Generation | AI image and video generators | Video, image, voice and music models through `generate` | | Captions | Auto captions with styles | `add_captions` from a transcript; each word stays editable | | Agent access | A "CapCut × Codex" plugin is listed, with no details | CLI and skills for Claude Code, Codex, Cursor and Antigravity; MCP server for ChatGPT, Claude on the web and the Gemini app | | Project files out | MP4 and other video formats | MP4, or a project for Premiere Pro, Final Cut Pro or DaVinci Resolve | | Offline | Desktop and mobile apps | No, invideo runs in the cloud | | Batch | Templates, one video at a time | `duplicate_timeline`, `set_text` and `export` per row, run in parts | #### Use CapCut when CapCut fits fast edits that a person makes by hand. - You edit on your phone, between other things. - You want a free editor. - You want a trending template and you are happy to tap through each change. - You work alone and do not need an agent or a project file. #### Use invideo when invideo fits edits that your agent runs and you review. - You want to say "cut this into a reel" and get a timeline back. - You want captions that stay editable after the cut. Your agent fixes a word with `set_caption_slide_text`, and the timing stays. - You want each change on its own branch, so you can compare and go back. - You want the cut in Premiere Pro, Final Cut Pro or DaVinci Resolve later. #### Use both Many creators shoot and rough-cut in CapCut, then finish with an agent. Export the CapCut edit as MP4. Your agent brings the file into invideo with `add_media`, then adds captions, music and the other platform sizes. The other way also works: export an MP4 from invideo and add a CapCut template on your phone. The setup for that hand-off is on [Use CapCut with invideo](/integrations/capcut). #### What CapCut does better Say it plainly. CapCut is better at some things. - **Mobile editing.** CapCut has a full app for phones and tablets. invideo has no app built for phone editing. - **Templates.** CapCut has a large library of social templates, and one tap applies one. - **Free to start.** You can edit online for free. invideo charges credits for generation, transcripts and paid stock. - **Local apps.** CapCut has desktop and mobile apps. invideo runs in the cloud and needs a connection. #### Try the brief in invideo Set up your agent first with [invideo for AI agents](/agents). Then give it the brief in your own words, like this. ```text Cut the clips in ./reel into a 30 second 9:16 reel. Add word-by-word captions and upbeat music. Work on a branch, price anything paid first, and show me frames before you export. ``` #### Cost Edits and exports are free in invideo. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Prices are on [Credits and what they cost](/account/credits). #### Related - [AI video tools compared, including invideo](/compare/alternatives) - [Use CapCut with invideo](/integrations/capcut) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Reels and Shorts from your footage](/how-to/creators/reels-and-shorts-from-your-footage) - [Trend edit like CapCut](/how-to/personal/trend-edit) ### OpusClip or Descript Source: https://docs.invideo.io/compare/opusclip-descript.md OpusClip for long video to short clips, Descript for editing by transcript. invideo when the cuts stay editable and your agent runs the pipeline. Use OpusClip to turn a long video into short clips, and Descript to edit a recording by its transcript. Use invideo when you want every cut to stay editable on a timeline, and your agent to run the whole job. All three tools transcribe speech and help you repurpose a long video into shorts. They differ in who drives the edit and what you can change after it. #### One brief, three tools The brief: a one hour podcast episode, cut into a clean full episode and five vertical clips with captions. **In OpusClip.** You upload the episode. OpusClip picks the highlight moments, reframes each one for vertical, and adds captions you can edit. You review the clips and download the ones you like. **In Descript.** Descript transcribes the episode. You "Edit your words to edit your video": you delete lines in the text and the video follows. You cut filler words "in a click", then make clips and add captions. **In invideo.** Your agent transcribes the episode with `media` `audio.transcript` and reads it with the speakers and times. It finds the ums with the transcript and the long pauses with `audio.content`. It cuts them on a branch with `split_clip` and `delete_clip`. For each clip, it makes a 9:16 timeline, adds captions with `add_captions`, and checks frames with `capture`. Every cut is a timeline edit, so you or the agent can undo one later. #### At a glance Checked on 29 October 2026 against OpusClip's and Descript's sites. They may change. | | OpusClip | Descript | invideo | | --- | --- | --- | --- | | Editable timeline after the cut | An editor with "full editing control" | Yes, the edit follows the text | Yes, every cut on a branch | | Generation | Not stated on its site | AI video, images, voices and voice clones | Video, image, voice and music models | | Captions | Auto captions you can edit | Captions in one click | `add_captions` from the transcript | | Agent access | An API | Underlord, its own AI editor, plus an API and MCP | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | Not stated on its site | XML for Premiere Pro and DaVinci Resolve, FCPXML for Final Cut Pro | A project for Premiere Pro, Final Cut Pro or DaVinci Resolve | | Offline | Not stated on its site | Not stated on its site | No, invideo runs in the cloud | | Batch | An API for your CMS | Not stated on its site | `duplicate_timeline` and `export` per clip, run in parts | #### Use OpusClip or Descript when These tools are built for the long-to-short job and for editing by text. - You want clips picked for you from a long video, with no setup (OpusClip). - You want to edit by deleting words in a document (Descript). - You want one button for filler words and retakes (Descript). - Your team already works in one of them every day. #### Use invideo when invideo fits the job when the transcript is only the start. - You already have a transcript, and you want the cuts as real timeline edits you can move or undo. - Your agent runs the pipeline end to end: transcript, cuts, captions, music, export. - You build your own pipeline in Claude Code or Codex, and you want the edit steps as named tools, not a separate app. - You want each clip on its own branch, and the full episode in Premiere Pro later. #### Use both Keep the tool you like for picking moments, and use invideo for the finish. Export the clip or the cut as MP4 from OpusClip or Descript. Your agent adds it with `add_media`, then adds brand captions, music and the other platform sizes. #### What OpusClip and Descript do better Say it plainly. These tools are better at some things. - **Picking clips with no prompt.** OpusClip chooses the highlights for you. In invideo, your agent reads the transcript and picks, so the result depends on what you ask. - **Editing by text.** Descript's whole editor is the transcript. invideo shows a timeline; the transcript is something your agent reads. - **One-click filler words.** Descript does it in one click. In invideo, your agent finds the ums and cuts them as separate edits. - **More export targets.** Descript also exports for Reaper, Audition and Pro Tools. #### Try the brief in invideo Set up your agent first with [invideo for AI agents](/agents). Then give it the brief in your own words, like this. ```text Transcribe this episode, cut the ums and long pauses on a branch, then make five 9:16 clips of the best moments with captions. Tell me the price of the transcript first, and show me frames before you export. ``` #### Cost Edits and exports are free in invideo. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Prices are on [Credits and what they cost](/account/credits). #### Related - [AI video tools compared, including invideo](/compare/alternatives) - [Podcast edit and clips](/how-to/creators/podcast-edit-and-clips) - [Cut ums, pauses and retakes](/how-to/creators/cut-ums-and-retakes) - [Repurpose one video for every platform](/how-to/creators/repurpose-for-every-platform) - [When to use ChatCut vs invideo](/compare/chatcut) ### Runway Source: https://docs.invideo.io/compare/runway.md Runway for generating shots and for its Premiere Pro and After Effects plugins. invideo for editing those shots, with a price check before each step. Use Runway to generate shots, and to generate inside Premiere Pro or After Effects with its plugin. Use invideo to edit shots into a finished video, with a dry run that prices each paid step before it runs. Runway makes video models, Gen-4.5 among them. invideo is a video editor with a timeline that can also run many generation models, Runway Gen-4.5 included, as `runway_gen45`. #### One brief, two tools The brief: a 30 second product ad from three product photos and one line of copy, with music and a voiceover. **In Runway.** You upload the photos to Runway's web app and generate a short clip from each one with Gen-4.5. You try prompts until each clip looks right. Then you take the clips into an editor for the cut, the text, the voice and the music. With the plugin, that editor can be Premiere Pro, where results "land at the playhead". **In invideo.** Your agent adds the photos with `add_media` and prices each clip with `generate` and `dry_run: true`. It tells you the price, then generates with `max_credits` set, using a model such as `runway_gen45`, `seedance_2_5.r2v` or `kling_v4.kling_v4_frames`. It makes a voiceover with `elevenlabs_text_to_speech.elevenlabs_tts_v4` and finds music with `search_library`. It places everything on a timeline, adds the line of copy with `add_text`, checks frames with `capture`, and exports. #### At a glance Checked on 29 October 2026 against Runway's site and its plugin page. They may change. | | Runway | invideo | | --- | --- | --- | | Editable timeline after the cut | In Premiere Pro through the plugin | Yes, on a branch you can review | | Generation | Its own models, Gen-4.5 among them | Many models, `runway_gen45` among them | | Captions | Not stated on its site | `add_captions` from a transcript | | Agent access | An API, an agent, and MCP and ChatGPT integrations | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | Results go into Premiere Pro or After Effects | A project for Premiere Pro, Final Cut Pro or DaVinci Resolve | | Offline | No, models run on Runway's servers | No, invideo runs in the cloud | | Batch | An API | `duplicate_timeline` and `export` per row, run in parts | #### Use Runway when Runway fits the shot, not the whole video. - You want the newest Runway models and features first, in Runway's own app. - You edit in Premiere Pro or After Effects and want generation inside them. - You re-render clips on your timeline with Aleph 2.0, or isolate a subject with no hand masking. - You build your own product on a generation API. #### Use invideo when invideo fits the job after the shots exist. - You want the shots cut into a video with text, voice, music and captions. - You want a price before each paid step. `dry_run` gives it, and `max_credits` stops any call above it. - You want to try models from several makers in one project and keep the best take. - You want your agent to do the edit and leave a timeline you can change. #### Use both Generate in Runway, finish in invideo. Download the clips from Runway. Your agent brings them in with `add_media` and builds the cut around them. The steps are on [Use Runway with invideo](/integrations/runway) and [Finish an AI clip from Higgsfield, Runway or Magnific](/how-to/marketing/finish-an-ai-clip). #### What Runway does better Say it plainly. Runway is better at some things. - **Its own models.** Runway builds the models. New Runway features appear in Runway's app, and invideo lists only the Runway models it carries. - **Adobe plugins.** One install puts Runway inside Premiere Pro and After Effects. invideo has no plugin for them; it exports a project file instead. - **Clip tools.** Aleph 2.0 re-renders a clip, Ruby converts to HDR, and its upscalers finish a shot. invideo exports 1080p and upscales after with `media` `video.upscale`. #### Try the brief in invideo Set up your agent first with [invideo for AI agents](/agents). Then give it the brief in your own words, like this. ```text Make a 30 second product ad from these three photos and this line: "Built for the long run." Price each generated clip first. Add a voiceover and music, check the frames, then export. ``` #### Cost Edits and exports are free in invideo. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. Prices are on [Credits and what they cost](/account/credits). #### Related - [AI video tools compared, including invideo](/compare/alternatives) - [Use Runway with invideo](/integrations/runway) - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Product photo to video](/how-to/marketing/product-photo-to-video) - [When to use Higgsfield vs invideo](/compare/higgsfield) ### Higgsfield Source: https://docs.invideo.io/compare/higgsfield.md Higgsfield for generating clips, presets and AI influencers. invideo for editing those clips into a multi-scene video with captions. Use Higgsfield when all you need is generated clips, from presets or an AI influencer. Use invideo when the clips go into a multi-scene video with an edit, captions, voice and music. Higgsfield is a generation studio for video, images and voice. invideo is a video editor with a timeline that also runs many generation models. #### One brief, two tools The brief: a 30 second UGC-style ad, with an AI actor holding your product in three scenes, captions and music. **In Higgsfield.** You pick a model or a preset, upload the product photo, and generate each scene. You can swap one element and keep the rest with its Genjutsu presets. You download the clips. The cut, the captions and the music happen in another editor. **In invideo.** Your agent adds the product photo with `add_media` and generates each scene with a model such as `seedance_2_5.r2v`, after a `dry_run` that gives the price. It makes the voice with a TTS model, places the scenes on a 9:16 timeline, and adds captions with `add_captions`. It keeps the real product photo as a clip where the product must look exact. Then it checks frames with `capture` and exports. #### At a glance Checked on 29 October 2026 against Higgsfield's site. It may change. | | Higgsfield | invideo | | --- | --- | --- | | Editable timeline after the cut | Not stated on its site | Yes, on a branch you can review | | Generation | Video, image and voice models, presets, face swap | Video, image, voice and music models through `generate` | | Captions | Not stated on its site | `add_captions` from a transcript | | Agent access | An MCP server for Claude | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | Generated files | MP4, or a project for Premiere Pro, Final Cut Pro or DaVinci Resolve | | Offline | No, it runs on the web | No, invideo runs in the cloud | | Batch | Not stated on its site | `duplicate_timeline` and `export` per row, run in parts | #### Use Higgsfield when Higgsfield fits when the clip is the product. - You want one striking clip, and an editor is not part of the job. - You want its presets or its "AI Influencer" builder. - You make many UGC-style clips with its UGC Builder, for someone else to cut. - You want face swap or virtual try-on. #### Use invideo when invideo fits when the clips are parts of a video. - You need several scenes in order, with a hook, a middle and an end. - You need captions, voice and music on the same timeline. - You want to fix one scene later and keep the rest. - You want your agent to do the edit and leave a timeline you can change. #### Use both Generate in Higgsfield, finish in invideo. Download the clips. Your agent brings them in with `add_media`, cuts them together, and adds captions, music and the other platform sizes. The steps are on [Use Higgsfield with invideo](/integrations/higgsfield) and [Finish an AI clip from Higgsfield, Runway or Magnific](/how-to/marketing/finish-an-ai-clip). #### What Higgsfield does better Say it plainly. Higgsfield is better at some things. - **Presets.** Higgsfield has ready-made presets you pick from. In invideo, you or your agent write the prompt. - **Creative tools around generation.** Face swap, virtual try-on and the "AI Influencer" builder are part of the app. - **A generation-first app.** If you only want clips, Higgsfield has fewer steps. invideo asks you to work in a project. #### Try the brief in invideo Set up your agent first with [invideo for AI agents](/agents). Then give it the brief in your own words, like this. ```text Make a 30 second 9:16 UGC ad in three scenes: an AI actor holds this product. Keep the real product photo where the label shows. Add captions and music. Price each generation before you run it. ``` #### Cost Edits and exports are free in invideo. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. Prices are on [Credits and what they cost](/account/credits). #### Related - [AI video tools compared, including invideo](/compare/alternatives) - [Use Higgsfield with invideo](/integrations/higgsfield) - [Make a UGC ad from product photos with an AI actor](/how-to/marketing/ugc-ad-with-ai-actor) - [Finish an AI clip from Higgsfield, Runway or Magnific](/how-to/marketing/finish-an-ai-clip) - [When to use Runway vs invideo](/compare/runway) ### HeyGen or Synthesia Source: https://docs.invideo.io/compare/heygen-synthesia.md HeyGen or Synthesia for avatar-first training, SCORM and long dubbing. invideo for explainers with no avatar, one-scene updates and bulk slides. Use HeyGen or Synthesia when a presenter on screen is the point, your LMS wants SCORM, or you dub long videos into many languages. Use invideo for explainers with no avatar, for changing one scene and keeping the rest, and for turning many slide decks into videos. All three tools make training and explainer videos from a script. HeyGen and Synthesia build around an AI avatar. invideo builds around a timeline, and can add an avatar as one clip. #### One brief, three tools The brief: a five minute onboarding video from a slide deck and a script, then a fix to one line after a policy change. **In HeyGen or Synthesia.** You drop in the deck or the script. The tool makes a draft video with an avatar presenter and a voice. You pick the avatar and adjust scenes in its editor. You publish as a link, an embed or a SCORM package for your LMS. To fix the line, you edit the script and publish again. Synthesia says embedded videos update when you edit. **In invideo.** Your agent turns the deck into images with `media` `document.pages`, which is free. It voices each slide with a TTS model such as `elevenlabs_text_to_speech.elevenlabs_tts_v4`, places the slides and the voice on a timeline, and adds captions with `add_captions`. To fix the line, it voices only the new line, swaps that clip on a branch, and exports again. The rest of the video stays as it was. #### At a glance Checked on 29 October 2026 against HeyGen's and Synthesia's sites. They may change. | | HeyGen | Synthesia | invideo | | --- | --- | --- | --- | | Editable timeline after the cut | Editable video, a text-based editor | An editor by scene | Yes, on a branch you can review | | Generation | Avatars, text, image and PDF to video | Avatars from a script, deck or URL to video | Many models; avatars as one clip with `heygen_photo_avatar` or `kling_avatar.pro` | | Captions | Yes | Not stated on its homepage | `add_captions` from a transcript | | Agent access | APIs, including a Video Agent API | An API | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | MP4 and SCORM | Link, embed or SCORM | MP4, or a project for Premiere Pro, Final Cut Pro or DaVinci Resolve | | Offline | No, it runs in the cloud | No, it runs in the cloud | No, invideo runs in the cloud | | Batch | APIs | Videos at scale from one template | `duplicate_timeline` and `export` per deck, run in parts | #### Use HeyGen or Synthesia when These tools are built for presenter-led training. - You want an avatar presenter on screen for most of the video. - Your LMS needs a SCORM package. invideo exports MP4, not SCORM. - You dub long videos into many languages with the speaker's own voice. - You want a personal avatar of yourself, made once and used again. #### Use invideo when invideo fits training that does not need a face. - You want an explainer from slides, screen shots, stock or generated scenes, with no avatar. - You change one scene or one line often, and want the rest of the video untouched. - You turn many decks into videos, one timeline per deck. - Your agent builds the video from a document and you review it. #### Use both Make the presenter in HeyGen or Synthesia, then finish in invideo. Export the avatar video as MP4. Your agent adds it with `add_media`, cuts it next to your slides and screen shots, and adds captions and music. For SCORM, export the final MP4 from invideo and wrap it in your LMS tool. The steps are on [Use HeyGen or Synthesia with invideo](/integrations/heygen-synthesia). #### What HeyGen and Synthesia do better Say it plainly. These tools are better at some things. - **Avatars.** Their avatars are the core product. HeyGen says Avatar V keeps "a single, coherent identity across every video". invideo runs avatar models as clips, not as a presenter studio. - **SCORM.** Both publish SCORM for an LMS. invideo does not. - **Translation at length.** HeyGen translates a video "with one click", and Synthesia dubs existing videos in the speaker's voice. invideo has no one-shot dubbing or translation model. Your agent dubs step by step. It reads the words with `audio.transcript` and translates them. It voices the new script with a TTS model, or clones the voice with `seed_audio_1_0.ta2a`. It swaps the sound with `video.replaceAudio`, then re-syncs the lips with `sync_lipsync_v3.video` or `kling_lipsync`. - **Embeds that update.** Synthesia updates shared links and LMS embeds when you edit. An invideo export is a new file. #### Try the brief in invideo Set up your agent first with [invideo for AI agents](/agents). Then give it the brief in your own words, like this. ```text Turn onboarding.pdf into a narrated video, one slide per scene, with captions. Use a calm voice. Price the voice first. Then show me how you would change only the slide on leave policy. ``` #### Cost Edits and exports are free in invideo. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. Prices are on [Credits and what they cost](/account/credits). #### Related - [AI video tools compared, including invideo](/compare/alternatives) - [Use HeyGen or Synthesia with invideo](/integrations/heygen-synthesia) - [Make a training explainer from a document, without an avatar](/how-to/training/explainer-from-a-document) - [Update one line and re-render, keep the rest](/how-to/training/update-one-line) - [Turn slides into a narrated video, one deck or hundreds](/how-to/training/slides-to-narrated-video) - [Dub existing footage](/how-to/training/dub-existing-footage) ### DaVinci Resolve or Premiere Pro Source: https://docs.invideo.io/compare/davinci-resolve-premiere.md DaVinci Resolve or Premiere Pro for finishing: grade, delivery above 1080p, LUTs and multicam. invideo to generate and assemble the cut, then hand over a project file. Use DaVinci Resolve or Premiere Pro to finish a video: the grade, delivery above 1080p, LUTs and multicam. Use invideo to generate shots and assemble the cut with your agent, then export a project file and finish in the NLE. An NLE (non-linear editor) is a desktop editing app. DaVinci Resolve and Premiere Pro are two widely used ones. invideo is a cloud editor with a timeline that your agent can drive, and it exports a project for either app. #### One brief, three tools The brief: a two minute brand film from interview footage, b-roll and two generated shots, graded and delivered above 1080p. **In DaVinci Resolve or Premiere Pro.** You import the footage, sync the cameras, and cut by hand. You make the generated shots in another tool, or in Premiere Pro with Firefly or a plugin. You grade with LUTs and color tools, mix the sound, and export at full resolution. You have full control of every frame. **In invideo, then the NLE.** Your agent transcribes the interview with `media` `audio.transcript`, finds the quotes, and lays the cut on a branch. It generates the two missing shots with a model such as `veo_31.frames`, after a `dry_run`. It adds music and temp captions, checks frames with `capture`, and exports a project with `export` and `format` set to `premiere`, `final_cut` or `davinci`. You open the project in the NLE for the grade, the mix and the final export. #### At a glance Checked on 29 October 2026 against the DaVinci Resolve and Premiere Pro product pages. They may change. | | DaVinci Resolve | Premiere Pro | invideo | | --- | --- | --- | --- | | Editable timeline after the cut | Yes | Yes | Yes, on a branch you can review | | Generation | Not stated; its AI tools do smart reframe and auto color | Firefly and Generative Extend | Video, image, voice and music models through `generate` | | Captions | Captions and subtitles on the Edit page | AI transcription and caption translation | `add_captions` from a transcript | | Agent access | Not stated on its product page | Not stated on its product page | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | Its own projects | Its own projects | A project for Premiere Pro, Final Cut Pro or DaVinci Resolve | | Offline | A desktop app for Mac, Windows and Linux | A desktop app, with a mobile app too | No, invideo runs in the cloud | | Batch | Not stated on its product page | Not stated on its product page | `duplicate_timeline` and `export` per row, run in parts | #### Use DaVinci Resolve or Premiere Pro when An NLE fits the finish. - You need a full grade, with LUTs, color tools and HDR. - You deliver above 1080p. invideo exports 1080p. - You cut multicam. Resolve has a sync bin for it. - You mix sound in depth, with Fairlight in Resolve or the audio tools in Premiere Pro. - You work on local media on your own computer. #### Use invideo when invideo fits the steps before the finish. - You want your agent to build the first cut from a transcript or a script. - You need generated shots, stock, voice or music in the same project. - You want a person and an agent in one project, each edit on a branch. - You want to hand an editor a project file, not a flat MP4. #### Use both This is the common path. Your agent assembles the cut in invideo, then runs `export` with `format` set to `premiere`, `final_cut` or `davinci`. `media_packaging` sets whether the media comes as a folder, a zip or not at all. The editor opens the project, grades and delivers. The steps and what carries over are on [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut). ```bash invideo edit export --format davinci --media-packaging zip ``` `` is the timeline's URL, from `invideo edit new` or `list_projects`. #### What DaVinci Resolve and Premiere Pro do better Say it plainly. These apps are better at some things. - **Color.** Resolve's color page is a full grading suite. invideo has `edit_grade` and `apply_lut`, which cover a look, not a full grade. - **Resolution.** Both deliver 4K. invideo exports 1080p, and upscales after with `media` `video.upscale`. - **Multicam and deep audio.** Resolve syncs many cameras and mixes on Fairlight. invideo has no multicam tool. - **Local work.** Both run on your computer with your local files. invideo runs in the cloud and needs a connection. - **Collaboration on Resolve.** Resolve has project libraries for local and remote work, with Blackmagic Cloud. #### Try the brief in invideo Set up your agent first with [invideo for AI agents](/agents). Then give it the brief in your own words, like this. ```text Build a two minute cut from these interviews and b-roll on a branch. Generate the two missing shots after a dry run. Then export a DaVinci Resolve project with the media in a zip. ``` #### Cost Edits and exports are free in invideo, project files included. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. Prices are on [Credits and what they cost](/account/credits). #### Related - [AI video tools compared, including invideo](/compare/alternatives) - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) - [Color grade log footage and match shots](/how-to/film/color-grade-log-footage) - [Generate a missing shot or extend a clip inside your edit](/how-to/film/generate-a-missing-shot) - [Documentary and interview edit](/how-to/film/documentary-and-interview-edit) ### VEED Source: https://docs.invideo.io/compare/veed.md VEED for captions on your footage in the browser. invideo for generation, an agent-run timeline, and sign-in with no API keys. Use VEED when you want captions on footage you already have, in the browser, by hand. Use invideo when you also need generated shots, when your agent should run the edit on a timeline, and when you want your agent to sign in with no API key. Both tools are online editors with auto captions (subtitles), translation and AI tools. VEED is built for a person in the browser. invideo is built for a person and an agent in the same project. #### One brief, two tools The brief: a talking-head video, captioned in a brand style, with a generated opening shot and a 9:16 and a 16:9 version. **In VEED.** You upload the video and turn on auto subtitles. You pick a subtitle style, set your brand colors and fonts, and fix any wrong word by hand. You make the opening shot with VEED's AI video generator, resize for each platform, and download each version. **In invideo.** Your agent transcribes the video with `media` `audio.transcript` and adds captions with `add_captions`. It applies your brand with `set_text_style`. It generates the opening shot with a model after a `dry_run`, and places it first. It makes one branch per size and sets each with `set_timeline_settings`. It checks frames with `capture`, then exports each branch. #### At a glance Checked on 29 October 2026 against VEED's site. It may change. | | VEED | invideo | | --- | --- | --- | | Editable timeline after the cut | Yes, in its video editor | Yes, on a branch you can review | | Generation | AI video generator, text and image to video, avatars | Video, image, voice and music models through `generate` | | Captions | Automatic subtitles with animated styles | `add_captions` from a transcript; `veed_subtitles` and `invideo_subtitles` as models | | Agent access | OpenEdit, a separate open-source editor your agent runs | CLI and skills for terminal agents; MCP server for clients without a shell; browser or device-code sign-in | | Project files out | Video download | MP4, or a project for Premiere Pro, Final Cut Pro or DaVinci Resolve | | Offline | No, it runs in the browser | No, invideo runs in the cloud | | Batch | Not stated on its site | `duplicate_timeline` and `export` per row, run in parts | #### Use VEED when VEED fits a person captioning footage in the browser. - You want captions on a recording and you fix them by hand. - You want a screen recorder, a teleprompter or eye contact correction in the same app. - You work alone in the browser and do not need an agent. - Your agent only needs captions on one clip, offline on a Mac. Then OpenEdit fits; see [When to use OpenEdit vs invideo](/compare/openedit). #### Use invideo when invideo fits when the captions are one step of a bigger edit. - You need generated or stock shots next to your footage. - Your agent runs the edit and you review a timeline, branch by branch. - Your agent signs in as you, in the browser or with a device code. There is no API key to make, store or leak. - You want the cut in Premiere Pro, Final Cut Pro or DaVinci Resolve later. #### Use both VEED's subtitle model runs inside invideo as `veed_subtitles`, for burned-in styled subtitles on a clip. You can also caption in VEED, download the video, and have your agent finish it in invideo with `add_media`. The steps are on [Use VEED with invideo](/integrations/veed). #### What VEED does better Say it plainly. VEED is better at some things. - **Caption editing by hand.** Subtitles are the center of VEED's app, and a person edits them directly. - **Tools around recording.** A screen recorder, a teleprompter, eye contact correction and noise removal sit in the same app. - **Simple start.** A person can open VEED and caption a video with no setup. invideo works best with an agent. #### Try the brief in invideo Set up your agent first with [invideo for AI agents](/agents). Then give it the brief in your own words, like this. ```text Caption this talking-head video in the brand font and colors. Add a generated opening shot, priced first. Make a 9:16 and a 16:9 branch, check the frames on each, then export both. ``` #### Cost Edits and exports are free in invideo. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. Prices are on [Credits and what they cost](/account/credits). #### Related - [AI video tools compared, including invideo](/compare/alternatives) - [Use VEED with invideo](/integrations/veed) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Sign in, device codes and sessions](/account/sign-in) - [Every placement from one master](/how-to/marketing/every-placement-from-one-master) ### Creatomate or Shotstack Source: https://docs.invideo.io/compare/creatomate-shotstack.md Creatomate or Shotstack for thousands of renders a day with API keys. invideo for tens of videos that a person runs with an agent, priced before each step. Use Creatomate or Shotstack when a server renders thousands of videos a day from a template, with API keys. Use invideo when a person runs tens of videos with an agent, reviews each one on a timeline, and wants a price before each paid step. All three tools render video from a template and data. Creatomate and Shotstack are render APIs for servers. invideo is an editor where each video is a timeline you can open and change. #### One brief, three tools The brief: a 15 second product video for each row of a product spreadsheet, with the name, the price and a photo. **In Creatomate or Shotstack.** You design a template in the online editor, with fields for the name, the price and the photo. Your server sends one API call per row, with an API key, and gets back one MP4 per row. Creatomate also takes the spreadsheet as a CSV, and connects to Zapier, Make and n8n. This scales to large runs with no person in the loop. **In invideo.** Your agent builds one timeline as the template and checks it with `capture`. For each row, it copies the timeline with `duplicate_timeline`, swaps the text with `set_text`, places the row's photo with `insert_media`, and runs `export`. For a large sheet, it runs in parts. Each video stays a timeline, so a person can open one and fix it by hand. #### At a glance Checked on 29 October 2026 against Creatomate's and Shotstack's sites and docs. They may change. | | Creatomate | Shotstack | invideo | | --- | --- | --- | --- | | Editable timeline after the cut | A template editor; renders are files | Studio and a white-label editor; renders are files | Yes, every video is a timeline | | Generation | AI voiceovers and AI video by API | AI models | Video, image, voice and music models through `generate` | | Captions | Auto subtitles, in its tutorials | Auto captions with word-level animation, in its docs | `add_captions` from a transcript | | Agent access | An MCP server | An MCP server, a CLI and a skill | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | MP4 and images | Video files | MP4, or a project for Premiere Pro, Final Cut Pro or DaVinci Resolve | | Offline | No, it renders in the cloud | No, it renders in the cloud | No, invideo runs in the cloud | | Batch | Spreadsheets, CSV and API calls at volume | "Render thousands of videos in minutes" | `duplicate_timeline`, `set_text` and `export` per row, run in parts | | Sign-in | API keys | Sandbox and production API keys | No API keys; a signed-in person | #### Use Creatomate or Shotstack when These tools are built for render volume. - You render thousands of videos a day, with no person watching. - Your server calls the API with a key, on a schedule or from your app. - You want to embed a video editor in your own product (Shotstack's white-label editor, Creatomate's preview SDK). - You run no-code automations in Zapier, Make or n8n (Creatomate). #### Use invideo when invideo fits volume that a person still oversees. - You make tens of videos, not thousands, and a person checks them. - You want each video to stay editable, so one fix does not mean a new render job. - You want a price before each paid step. `dry_run` gives it, and `max_credits` stops any call above it. - You want no API keys to manage. invideo has none, by design: every call runs as a signed-in person. See [Is there an invideo API?](/api). #### Use both Use invideo to design and approve the template with your team, then rebuild the approved look in Creatomate or Shotstack for volume. Or render the bulk in a render API and use invideo for the few videos that need a hand edit. Bring those files in with `add_media`. #### What Creatomate and Shotstack do better Say it plainly. These tools are better at some things. - **Volume.** They are built to render at server scale. invideo runs in parts and is not built for unattended volume. - **Server keys.** A server calls them with an API key. invideo signs in as a person, in the browser or with a device code. - **Embedding.** Shotstack has a white-label editor and Creatomate a preview SDK for your own app. invideo has no embeddable editor. - **No-code automation.** Creatomate connects to Zapier, Make and n8n out of the box. #### Try the brief in invideo Set up your agent first with [invideo for AI agents](/agents). Then give it the brief in your own words, like this. ```text Build one 15 second product video as a template. Then make one copy per row of products.csv with the name, price and photo, and export each. Run it in parts and tell me when each part is done. ``` #### Cost Edits and exports are free in invideo. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Prices are on [Credits and what they cost](/account/credits). #### Related - [AI video tools compared, including invideo](/compare/alternatives) - [Is there an invideo API?](/api) - [Turn a CSV into many videos with a script](/how-to/developers/csv-to-videos) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [Know the cost before you spend](/how-to/cost-before-you-spend) ### HyperFrames Source: https://docs.invideo.io/compare/hyperframes.md HyperFrames renders code motion on your computer for free. invideo adds footage, voice, music, polish and a project file on a shared timeline. Use HyperFrames when the video is motion your agent writes as code and you want a free render on your own computer. Use invideo when the video needs real footage, a voice, licensed music, color and sound polish, or a project file for Premiere Pro, Final Cut Pro or DaVinci Resolve. #### The same brief in both tools The brief: a 30 second launch video. It opens on an animated title card, cuts to three product clips, and ends on a logo, with a voiceover and a music bed. In HyperFrames, your agent writes the video as HTML, CSS and JavaScript. The title card and the logo are web animation, so this part is quick for an agent that writes web code. You add the product clips and a music track yourself. The voice comes from a local voice model, or from HeyGen voices with a HeyGen account. You preview it in the browser editor, then render an MP4 on your computer. In invideo, your agent makes a timeline with `new_timeline` and works on a branch from `timeline_history`. It finds product footage with `search_library` or makes shots with a video model through `generate`. It voices the script with a TTS model such as `elevenlabs_text_to_speech.elevenlabs_tts_v4`, finds music in the stock music library, and builds the title with `add_text` and `set_keyframes`. You watch each edit land in the editor and fix any clip by hand. Then the agent runs `export` for an MP4 or a project file. #### At a glance The rows below are the ones that change the choice for this job. | | HyperFrames | invideo | | --- | --- | --- | | How you make the video | HTML, CSS and JavaScript compositions | Edit operations on a real timeline | | Editable timeline after the cut | A browser editor to move, trim, split and align clips | Your agent rebuilds the composition's elements on a multi-track timeline from the source, which you and your agent share live | | Footage | Files you add | Stock video and images, and video models | | Voice | A local voice model, or HeyGen voices | TTS models and voice clones | | Music | Tracks you add, or a HeyGen music catalog | Licensed stock music and music models | | Captions | The agent transcribes and adds captions | `audio.transcript`, then an editable caption track | | Agent access | Agent skills, and a hosted MCP server | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | MP4, MOV, WebM, GIF or PNG | MP4, or a Premiere Pro, Final Cut Pro or DaVinci Resolve project | | Where it renders | On your computer, free, no account | In the cloud | | Batch | A JSONL batch of variable values, on Lambda | One timeline per row, run in parts | Checked on 29 October 2026 against the HyperFrames FAQ and the HyperFrames docs index. #### Use HyperFrames when HyperFrames fits work that is code from the start. - The video is motion graphics, a data card or a site animation that your agent writes as web code. - You want to render on your own machine, with no account and no cloud. - You need a GIF, a WebM or a PNG sequence out. - You already have a website or an HTML prototype that is close to a video. #### Use invideo when invideo fits work that needs media and a finish. - The video needs footage you do not have: stock clips or generated shots. - It needs a voice, a cloned voice or a dub, and licensed music. - It needs polish: a grade with `edit_grade` or `apply_lut`, a cleaned voice with `audio.clean`, and loudness set at export. - An editor will finish it in Premiere Pro, Final Cut Pro or DaVinci Resolve, so you need a project file. - A person reviews and changes the cut by hand while the agent works. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. #### Use both Write the code motion in HyperFrames, then finish it in invideo. The hand-off is an MP4, or a rebuild of the composition from its HTML. 1. Render the title card or the animated chart to MP4 in HyperFrames, or have your agent rebuild it on the timeline as text, shapes and keyframes. 2. Upload the files to the invideo project with `start_upload` and `add_media`. 3. Place them on the timeline, then add footage, voice and music around them. 4. Change the timing in invideo, with no new render of the motion. To change a rendered motion, render it again in HyperFrames. Your agent then replaces the clip on the timeline. A rebuilt element changes on the timeline. [Rebuild a composition as an editable timeline](/how-to/developers/composition-to-timeline) gives the steps. #### What HyperFrames does better Say it plainly: for motion written as code, HyperFrames is the more direct tool. - Your agent writes a composition in web code it already knows, with no timeline to drive. - Rendering on your computer is free and needs no account. - It is open source under Apache 2.0. - It renders more output formats than an MP4. #### Related - [Use HyperFrames with invideo](/integrations/hyperframes) - [When to use Remotion vs invideo](/compare/remotion) - [AI video tools compared, including invideo](/compare/alternatives) - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) - [Rebuild a composition as an editable timeline](/how-to/developers/composition-to-timeline) - [invideo for AI agents](/agents) ### Remotion Source: https://docs.invideo.io/compare/remotion.md Remotion renders React video code at volume. invideo lets you or your agent move one reveal on a timeline without a code change. Use Remotion when your video is React code and you render many versions of it. Use invideo when a person or an agent changes the cut by hand, like moving one reveal two seconds later, and you want footage, voice and music in the same place. #### The same brief in both tools The brief: a 15 second product reveal for a launch. The product slides in, a price card appears, and the logo closes. After the first review, the marketer asks to move the price card reveal a little later. In Remotion, your agent writes the video as a React component. Each frame is a function of the frame number, so the reveal time is a value in the code. To move the reveal, someone changes that value and renders again. The render runs on your machine, on a server, or on AWS Lambda. In invideo, your agent builds the same video as clips, text and keyframes on a timeline, on a branch from `timeline_history`. The price card is a clip. To move the reveal, the marketer drags the clip in the editor, or the agent sends one `move_clip` operation with `edit_timeline`. The rest of the cut stays as it was, and the agent checks it with `capture` before it runs `export`. #### At a glance The rows below are the ones that change the choice for this job. | | Remotion | invideo | | --- | --- | --- | | How you make the video | React components | Edit operations on a real timeline | | Editable timeline after the cut | Change the code and render again | Your agent rebuilds the composition's elements on the timeline from the source; then move, trim and retime them by hand or by agent | | Generation | Not part of the framework | Video, image and audio models through `generate` | | Captions | A captions how-to with code | `audio.transcript`, then an editable caption track | | Agent access | Agent skills; no hosted MCP server | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | Rendered media | MP4, or a Premiere Pro, Final Cut Pro or DaVinci Resolve project | | Where it renders | Your machine, a server, or AWS Lambda | In the cloud | | Batch | Render at volume with Lambda or a server | One timeline per row, run in parts | | License | Its own license, with free and Company License terms | invideo's terms | Checked on 29 October 2026 against the Remotion docs index, the Lambda page, the MCP page and the Remotion license. #### Use Remotion when Remotion fits video that is software. - Your team writes React and wants video in the same code and design system. - You render the same template many times with different data. - You want to own the render, on your own machine, a server, or Lambda. - The video is motion graphics and data, not footage that needs a person's eye. #### Use invideo when invideo fits video that people review and change. - The person who asks for changes does not write code. They drag the clip in the editor. - The video needs stock footage, generated shots, a voice or licensed music. - A person and an agent work on the same cut, and you want branches to compare versions. - An editor finishes the video in Premiere Pro, Final Cut Pro or DaVinci Resolve. - You want one set of terms for the whole job. invideo's terms for stock, music and generated media are on [Licensing and commercial use](/account/commercial-use). Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. #### Use both Keep the motion in Remotion and the finish in invideo. The hand-off is an MP4, or a rebuild of the composition from its source. 1. Render the animated parts to MP4 in Remotion, or have your agent rebuild them on the timeline as clips, text and keyframes. 2. Upload each file to the invideo project with `start_upload` and `add_media`. 3. Place them on a timeline, then add footage, a voice and music. 4. Make late timing changes on the timeline, where a person can review them. A change inside a rendered animation goes back to Remotion for a new render. Your agent then replaces the clip on the timeline. A rebuilt element changes on the timeline. [Rebuild a composition as an editable timeline](/how-to/developers/composition-to-timeline) gives the steps. #### What Remotion does better Say it plainly: for code-first video at volume, Remotion is the stronger tool. - It is a mature React framework. Even HeyGen's HyperFrames comparison calls it older and more established, with more templates and tutorials. - Lambda renders one video in parallel parts, which its docs call the fastest and most scalable way to render. - Each frame is a function of the frame number. The model is simple to hold in your head. - You control where it renders and what it runs on. Read its license before you ship. Remotion's license page says who can use it free and who needs a Company License. #### Related - [Use Remotion with invideo](/integrations/remotion) - [When to use HyperFrames vs invideo](/compare/hyperframes) - [Make many videos from a CSV with a script](/how-to/developers/csv-to-videos) - [Rebuild a composition as an editable timeline](/how-to/developers/composition-to-timeline) - [AI video tools compared, including invideo](/compare/alternatives) - [invideo for AI agents](/agents) ### OpenEdit Source: https://docs.invideo.io/compare/openedit.md OpenEdit burns captions into a clip on your own machine. invideo adds a timeline you review, generation, stock and music. Use OpenEdit when you want captions on one clip, made on your own machine, with no timeline to review. Use invideo when a person reviews the cut on a timeline, or the video needs generated shots, stock footage or music. #### The same brief in both tools The brief: subtitles on a 60 second talking-head clip for a reel, in the brand's caption style. In OpenEdit, you ask your coding agent to add subtitles. The agent transcribes the clip, styles the captions and renders. Transcription runs on VEED's service with a veed.io account, or locally with WhisperX. You get back an MP4 with the subtitles burned in and the path to the file. There is no GUI and no timeline, so a change is another request to the agent. In invideo, your agent uploads the clip with `start_upload` and `add_media`, then reads every word with `media` `audio.transcript`. It places an editable caption track with `add_captions` and styles it with `set_text_style`. You open the timeline and fix a word in the editor, or the agent does it with `set_caption_slide_text`. Then the agent checks frames with `capture` and runs `export`. You can turn the captions off for one export with `set_clip_enabled`. #### At a glance The rows below are the ones that change the choice for this job. | | OpenEdit | invideo | | --- | --- | --- | | Editable timeline after the cut | None; you ask the agent again | A multi-track timeline you and your agent share live | | Generation | Footage, images, music and sound through VEED | Video, image, audio and 3D models through `generate` | | Captions | Transcribed, styled and burned into the MP4 | An editable caption track, on or off per export | | Stock and music | Not listed in its README | Stock video, images and music through `search_library` | | Agent access | A skill for Claude Code, Codex or Gemini CLI | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | MP4 | MP4, or a Premiere Pro, Final Cut Pro or DaVinci Resolve project | | Offline | Renders locally; WhisperX transcribes locally after its first download | Cloud only | | Linux and CI | Its README lists Linux as supported and least tested | The CLI signs in with a device code on a server | | Batch | Not listed | One timeline per row, run in parts | Checked on 29 October 2026 against the OpenEdit README and VEED's OpenEdit launch page. The two disagree on platforms. The README lists Mac, Windows and Linux. The launch page lists Apple Silicon Macs on macOS 26 only. Check the README for your machine. #### Use OpenEdit when OpenEdit fits one-clip jobs that stay on your machine. - You want burned-in captions on a clip, and the file is the result. - The footage must not leave your computer. With WhisperX, its README says nothing leaves your machine. - You run the job inside a script or a CI step on your own hardware. - You want an open source pipeline under Apache 2.0. #### Use invideo when invideo fits jobs where a person reviews the cut. - Someone checks the captions and the cuts on a timeline before it ships. - The video needs B-roll from stock or from a video model. - It needs music that clears rights, from the stock music library or a music model. - You need captions that stay editable, or an SRT file read from the caption track. - An editor finishes it in Premiere Pro, Final Cut Pro or DaVinci Resolve. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. #### Use both Caption on your machine, then finish in invideo. The hand-off is the captioned MP4. 1. Run OpenEdit on the clip and get the MP4 with subtitles burned in. 2. Upload it to the invideo project with `start_upload` and `add_media`. 3. Add B-roll, music and titles on a timeline around it. 4. Export the finished video with `export`. Burned-in captions are part of the picture. To change a word later, run OpenEdit again, or make the captions in invideo instead. #### What OpenEdit does better Say it plainly: for one captioned clip on your own machine, OpenEdit is the shorter path. - It runs on your computer, and WhisperX transcribes on your machine. - One request to your agent returns a finished file. - The pipeline is open source, so you can read and change it. - It needs no account when you transcribe with WhisperX. #### Related - [Use OpenEdit with invideo](/integrations/openedit) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [When to use VEED vs invideo](/compare/veed) - [AI video tools compared, including invideo](/compare/alternatives) ### Magnific Source: https://docs.invideo.io/compare/magnific.md Magnific's MCP cuts, joins, grades and upscales finished clips. invideo adds captions, titles and a multi-track timeline. Use Magnific when your agent needs to cut, join, grade or upscale finished clips through its MCP server. Use invideo when the video needs captions, titles, and clips laid out on several tracks that a person can review. #### The same brief in both tools The brief: a 30 second product reel from four finished clips, graded to one look, with a title card, captions on the voiceover and a logo in the corner. With Magnific's MCP server, your agent trims each clip, joins the clips into one MP4, and grades them with a LUT from its catalog or by hand. It can also blend a cut with generated frames, upscale the result, or deliver ProRes or DNxHR for an editor. Its MCP docs list no caption, title or timeline tools. The title card, the captions and the logo need another tool. In invideo, your agent places the four clips on a timeline on a branch from `timeline_history`. It trims them with `trim_clip`, grades them with `apply_lut` or `edit_grade`, and adds the title with `add_text`. It reads the voiceover with `media` `audio.transcript` and places a caption track with `add_captions`. The logo goes on its own track. You see each edit in the editor, then the agent runs `capture` and `export`. #### At a glance The rows below are the ones that change the choice for this job. | | Magnific | invideo | | --- | --- | --- | | Editable timeline after the cut | None listed; each tool makes a new clip | A multi-track timeline you and your agent share live | | Cuts and joins | Trim, join, and a cut that generates frames across the join | `split_clip`, `trim_clip`, `move_clip` and transitions | | Grades | A LUT from its catalog, manual settings, or a match to a reference image | `apply_lut`, `edit_grade`, and LUT files you upload | | Captions and titles | Not in its MCP docs | `add_captions` and `add_text` | | Generation | Images, video, audio and 3D | Video, image, audio and 3D models through `generate` | | Upscale and HDR | Video upscale with Topaz or Magnific, SDR to HDR | `video.upscale`, `image.upscale`, and upscale and HDR models | | Agent access | Remote MCP server with OAuth sign-in | CLI and skills for terminal agents; MCP server for clients without a shell | | Files out | ProRes, DNxHR or HEVC video, 16-bit PNG or TIFF, layered PSD, WAV | MP4, or a Premiere Pro, Final Cut Pro or DaVinci Resolve project | | Offline | Cloud | Cloud | Checked on 29 October 2026 against Magnific's MCP docs. #### Use Magnific when Magnific fits work on single clips. - Your agent needs to trim, join or grade finished clips and hand back a file. - A cut needs generated frames across the join so it blends. - You want to restyle footage from a prompt, or add or remove an element, and keep the motion. - You deliver ProRes, DNxHR, 16-bit stills or layered PSD files to a finishing editor. #### Use invideo when invideo fits work that becomes one layered video. - The video needs captions that stay editable after the cut. - It needs titles and a logo on their own tracks. - Several clips, voice and music sit on different tracks and a person reviews the layout. - You want a project file for Premiere Pro, Final Cut Pro or DaVinci Resolve. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. #### Use both Magnific models also run inside invideo. `media` `image.upscale` takes `magnific_upscaler_creative` or `magnific_upscaler_precision_v2` as its `model`. Your agent runs `dry_run` first, because upscales cost credits. For a clip you made in Magnific, the hand-off is the file. 1. Make or grade the clip in Magnific. 2. Bring it into the invideo project with `add_media` from its URL, or `start_upload` for a local file. 3. Place it on a timeline, then add captions, titles and music. 4. Run `capture`, then `export`. #### What Magnific does better Say it plainly: on a single clip, Magnific's MCP does things invideo's timeline does not. - A cut that generates new frames across the join. - Prompt edits to footage that keep the motion: restyle, add, replace or remove. - A grade matched to a reference image. - Delivery as ProRes, DNxHR, 16-bit PNG or TIFF, or layered PSD. #### Related - [Use Magnific with invideo](/integrations/magnific) - [Finish an AI clip from Higgsfield, Runway or Magnific](/how-to/marketing/finish-an-ai-clip) - [Color grade log footage and match shots](/how-to/film/color-grade-log-footage) - [Add word-by-word captions](/how-to/creators/word-by-word-captions) - [AI video tools compared, including invideo](/compare/alternatives) ### Tesseract Source: https://docs.invideo.io/compare/tesseract.md Tesseract edits and renders on your computer and converts Premiere Pro and After Effects projects. invideo works online with generation and stock. Use Tesseract when the edit must stay on your computer, or when you move projects to and from Premiere Pro or After Effects through its converter. Use invideo when the work is online, needs generated shots or stock, and more than one person or agent works on the same cut. #### The same brief in both tools The brief: a 30 second vertical video from a folder of phone clips, with a preview before export. The editor finishes it in Premiere Pro. In Tesseract, your agent edits the clips and renders a preview on your computer. You get an MP4 and an editable `.tsrct` project with your media and fonts. To get to Premiere Pro, a separate converter tool, `tsrct-conv`, turns the `.tsrct` project into a `.prproj` file. Its README marks that direction as partial and says some features may not convert exactly. In invideo, your agent uploads the clips with `start_upload` and `add_media` and builds the cut on a timeline, on a branch from `timeline_history`. You watch the edit in the browser and change it by hand. The agent checks it with `capture`, then runs `export` with `format` `premiere` for an editable Premiere Pro project, or `video` for an MP4. #### At a glance The rows below are the ones that change the choice for this job. | | Tesseract | invideo | | --- | --- | --- | | Where it runs | Edits and renders on your computer | In the cloud, in the browser | | Editable timeline after the cut | An editable `.tsrct` project | Your agent rebuilds the edit's layers on a multi-track timeline from the project, which you and your agent share live | | Generation | Not on its help page or README | Video, image, audio and 3D models through `generate` | | Stock | Not on its help page or README | Stock video, images and music through `search_library` | | Collaboration | Not on its help page or README | People and agents in one project, with branches | | Agent access | Agent skills and a plugin; the agent runs its CLI | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | MP4 and `.tsrct`; Premiere Pro and After Effects through its converter | MP4, or a Premiere Pro, Final Cut Pro or DaVinci Resolve project | | Round trip in | Premiere Pro and After Effects projects through its converter | Media files, or a rebuild of a Tesseract edit by your agent | | Offline | Local edit and render | Cloud only | Checked on 29 October 2026 against the Tesseract help page, the Tesseract README and the Tesseract Converter README. The help page lists macOS and 64-bit Windows. The README also lists Linux. The converter README gives one support level per direction. | Adobe format | Into Tesseract | Out of Tesseract | | --- | --- | --- | | Premiere Pro `.prproj` | Partial | Partial | | After Effects `.aep` | Partial | Experimental | #### Use Tesseract when Tesseract fits work that stays on your machine. - The footage must not go to a cloud service. - You need an edit and a render on your own computer. - You start from a Premiere Pro or After Effects project and want your agent to work on it. - You want to send the result back to After Effects, and accept that the converter marks this experimental. #### Use invideo when invideo fits work that is shared and online. - You need shots you do not have, from a video model or from stock. - A person and an agent, or several agents, work on the same cut, and each round of changes is a branch. - The reviewer opens the project URL in the browser, with nothing to install. - You need a project file for Final Cut Pro or DaVinci Resolve, as well as Premiere Pro. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. #### Use both Generate and assemble online, then finish locally. The hand-off is a media file. 1. Make the missing shots and the rough cut in invideo. 2. Export the cut, or single shots, as MP4 with `export`. 3. Bring the files into Tesseract on your computer and finish the edit there. Keep the `.tsrct` project after you share the MP4. Tesseract's help page gives the same advice. The other way, your agent can rebuild a Tesseract edit on an invideo timeline as clips, text and keyframes, so a reviewer changes it in the browser. [Rebuild a composition as an editable timeline](/how-to/developers/composition-to-timeline) gives the steps. #### What Tesseract does better Say it plainly: for local work and Adobe round trips, Tesseract does things invideo does not. - It edits and renders on your computer. - It reads Premiere Pro and After Effects projects through its converter. - It writes an After Effects project, marked experimental. - Its project file carries your media and fonts with it. #### Related - [Use Tesseract with invideo](/integrations/tesseract) - [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut) - [Run several agents and a person in one project](/how-to/developers/several-agents-one-project) - [Rebuild a composition as an editable timeline](/how-to/developers/composition-to-timeline) - [AI video tools compared, including invideo](/compare/alternatives) - [invideo for AI agents](/agents) ### ChatCut Source: https://docs.invideo.io/compare/chatcut.md ChatCut edits talking-head video by editing its transcript. invideo adds a wide model catalog, stock, and branches for people and agents. Use ChatCut when you cut talking-head video by deleting words from its transcript. Use invideo when the video also needs shots from many generation models, stock footage and music, and several people or agents working on one cut with branches. #### The same brief in both tools The brief: a 10 minute interview cut down to a tight 3 minute version, with the ums and long pauses gone, captions, and two B-roll shots over the weak moments. In ChatCut, the app transcribes the interview and gives every word a timestamp. You delete words in the transcript and the matching footage leaves the cut, with the gap closed. You can also ask in chat, for example to remove every pause over a set length. ChatCut turns the transcript into timed captions. For B-roll, it generates a clip with Seedance 2.0 and places it on a track above the cut. In invideo, your agent reads every word with `media` `audio.transcript` and finds the silences with `audio.content`. It cuts on a branch from `timeline_history` with `split_clip` and `delete_clip`, or with `edit_time_range`. It adds captions with `add_captions`. For B-roll, it searches stock with `search_library` or picks a video model with `find_models` and runs `generate`. You review the branch in the editor, and the agent checks it with `capture` before `export`. #### At a glance The rows below are the ones that change the choice for this job. | | ChatCut | invideo | | --- | --- | --- | | Transcript editing | Delete words in the transcript to cut footage | The agent reads the transcript and cuts with edit operations | | Editable timeline after the cut | A multi-track timeline with manual controls | A multi-track timeline you and your agent share live | | Generation | B-roll with Seedance 2.0, images with GPT-Image-2, AI music | Video, image, audio and 3D models through `generate` | | Stock | Not on the pages checked | Stock video, images and music through `search_library` | | Captions | Timed captions from the transcript; SRT or TXT out | An editable caption track; SRT read from the track | | Collaboration | An invite link adds an editor; a watch link for viewers | People and agents in one project, with branches and checkpoints | | Agent access | An agent plugin for Claude Code Desktop and Codex Desktop | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | Its docs list a Premiere and DaVinci XML page | MP4, or a Premiere Pro, Final Cut Pro or DaVinci Resolve project | | Where it runs | A web app, and desktop apps for macOS and Windows | In the cloud, in the browser | Checked on 29 October 2026 against ChatCut's AI video editor page, text-based editing page and transcript editing docs. #### Use ChatCut when ChatCut fits edits that start from the words. - You cut an interview, a podcast or a talking head, and you think in sentences, not clips. - You want to delete a line of text and see the footage go with it. - You want captions straight from the transcript you already edited. - You work in a desktop app on macOS or Windows. #### Use invideo when invideo fits edits that need more than the words. - The cut needs B-roll from a wide choice of video models, or from stock. - It needs licensed stock music, or a voice from a TTS model. - Several people and agents work on one project, and each round of changes is a branch you can compare and restore. - Your agent works in a terminal with the CLI, or in a chat app with MCP. - An editor finishes it in Premiere Pro, Final Cut Pro or DaVinci Resolve. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. #### Use both Cut the words in ChatCut, then build out the video in invideo. The hand-off is the exported video. 1. Make the transcript cut in ChatCut and export the video. 2. Upload it to the invideo project with `start_upload` and `add_media`. 3. Add B-roll, music, titles and versions for each platform on a timeline. 4. Run `capture`, then `export`. For captions that stay editable in invideo, your agent runs `audio.transcript` on the uploaded file and places them with `add_captions`. #### What ChatCut does better Say it plainly: for editing speech by its text, ChatCut puts the transcript at the center. - Deleting a word deletes its footage, video and audio together. - You see the transcript and the timeline side by side, and drag a paragraph to move its clip. - Plain-language commands such as removing every filler word run in one step. - The person editing needs no agent at all. #### Related - [Use ChatCut with invideo](/integrations/chatcut) - [Cut ums, pauses and retakes, as reversible timeline edits](/how-to/creators/cut-ums-and-retakes) - [Podcast edit and clips](/how-to/creators/podcast-edit-and-clips) - [When to use OpusClip or Descript vs invideo](/compare/opusclip-descript) - [AI video tools compared, including invideo](/compare/alternatives) ### Pictory or Lumen5 Source: https://docs.invideo.io/compare/pictory-lumen5.md Pictory and Lumen5 turn an article into a video with their templates. invideo gives you an editable timeline after the first draft, with free edits. Use Pictory or Lumen5 when you want a blog post turned into a video fast, in the look of their templates. Use invideo when you want to keep editing after the first draft, on a real timeline, and edits and exports are free. #### The same brief in both tools The brief: turn a 1,200 word blog post into a 60 second video for LinkedIn, with a voiceover, stock visuals and the brand colors. In Pictory, you paste the post's URL. It builds the video with stock visuals or your uploads, synced captions in your brand style, and an AI voice. You pick layouts, transitions, text styles and subtitle themes from its templates. For a change, you ask its agent or open the editor and work scene by scene. In Lumen5, you paste the post's URL, upload a PDF, or add the text. Its AI Script Composer proposes scripts to choose from. Lumen5 then pairs the script with media, timing and motion for a rough cut. You add an AI voiceover and your branding. In invideo, your agent reads the post and writes the script. It voices the script with a TTS model, finds stock video and music with `search_library`, and builds the video on a timeline with `insert_media`, `add_text` and `add_captions`. The brand colors and fonts live in a `context/brands/` entry, applied with `set_text_style`. After the first draft, you or the agent move, trim and replace any clip, line or caption. Then the agent runs `capture` and `export`. #### At a glance The rows below are the ones that change the choice for this job. | | Pictory | Lumen5 | invideo | | --- | --- | --- | --- | | Article to video | From a URL, blog link or web page | From a URL, a PDF or text | Your agent reads the article and builds the timeline | | Look | Its templates library | Its video templates and branded templates | Your brand entry, applied to text and captions | | Editable timeline after the first draft | Scene editing, or ask its agent | An editor for text, visuals and brand after the rough cut | A multi-track timeline you and your agent share live | | Voice | AI voices by ElevenLabs | An AI voiceover library | TTS models and voice clones | | Captions | Synced captions in your brand style | Not on the page checked | An editable caption track | | Agent access | Its own agent, and the Pictory API | Not on the page checked | CLI and skills for terminal agents; MCP server for clients without a shell | | Project files out | A downloaded video | Not on the page checked | MP4, or a Premiere Pro, Final Cut Pro or DaVinci Resolve project | Checked on 29 October 2026 against pictory.ai and Lumen5's blog to video page. #### Use Pictory or Lumen5 when These tools fit a fast first video from text. - You want a video from a blog post in a few clicks, and the template look is fine. - A marketer makes the video alone, with no agent. - You make the same kind of article video every week and the template saves the design work. - Pictory fits when you want its API to make branded videos from your own product. #### Use invideo when invideo fits when the first draft is the start, not the end. - You want to change one scene, one line or one caption after the draft without starting again. - Your agent already has the article, and you want it to build the video in the same chat. - You want the timeline itself: tracks, keyframes, a grade and the mix. - You want to try two versions of the opening on branches from `timeline_history`. - An editor finishes it in Premiere Pro, Final Cut Pro or DaVinci Resolve. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. #### Use both Start in a template tool, then finish on a timeline. The hand-off is the downloaded video. 1. Make the first draft in Pictory or Lumen5 and download the video. 2. Upload it to the invideo project with `start_upload` and `add_media`. 3. Cut, reorder and add to it on a timeline: a new intro, music, captions. 4. Run `capture`, then `export`. The template's text is part of the picture after download. To change that text, rebuild the scene in invideo with `add_text`. #### What Pictory and Lumen5 do better Say it plainly: for a first draft from a URL, these tools have fewer steps. - A URL in, a video out, with no prompt to write. - Templates give a finished look with no design choices. - Lumen5 offers several script options before it builds the video. - A person with no agent and no editing skills gets a result. #### Related - [Turn a blog post URL into a video](/how-to/marketing/article-to-video) - [Make a training explainer from a document, without an avatar](/how-to/training/explainer-from-a-document) - [Turn release notes or a changelog into a video every week](/how-to/training/release-notes-to-video) - [AI video tools compared, including invideo](/compare/alternatives) - [invideo for AI agents](/agents) ### Lovart Source: https://docs.invideo.io/compare/lovart.md Lovart designs images, posters and brand assets on a canvas. invideo assembles them into a video on a timeline with voice, music and captions. Use Lovart when the job is design first: product shots, social posts, posters and a campaign kit. Use invideo when those assets become a video, cut on a timeline with voice, music and captions. #### The same brief in both tools The brief: a product launch campaign with a key visual, three social posts, and a 20 second video that uses the same look. In Lovart, you describe the campaign to its design agent. It makes the key visual and the posts on one infinite canvas, from your brand kit. You edit each element by prompt or with its tools. Its skills can also turn a brief into a finished video, with a shot list and consistent characters. You export PNG, SVG, PSD, PPTX or MP4. In invideo, your agent brings the key visual and the product photos into the project with `add_media`. It writes the brand into a `context/brands/` entry. It animates stills with an image-to-video model through `generate`, places the shots on a timeline, and times the cuts to the music with `media` `audio.beats`. It adds text with `add_text` and `set_keyframes`, a voice from a TTS model, and captions with `add_captions`. You change any shot or timing in the editor, then the agent runs `capture` and `export`. #### At a glance The rows below are the ones that change the choice for this job. | | Lovart | invideo | | --- | --- | --- | | Main surface | An infinite canvas for design | A multi-track timeline for video | | Design assets | Product shots, social posts, campaign kits, slides | Images from image models; no design canvas | | Video | Brief to finished video through its skills | Clips, text, voice and music assembled on a timeline | | Editable timeline after the cut | Not described in its docs | Move, trim and retime clips by hand or by agent | | Brand | A brand kit as an input | A `context/brands/` entry, applied with `set_text_style` | | Captions | Not on the docs page checked | An editable caption track | | Agent access | An in-app agent | CLI and skills for terminal agents; MCP server for clients without a shell | | Files out | PNG, SVG, PSD, PPTX, MP4 | MP4, or a Premiere Pro, Final Cut Pro or DaVinci Resolve project | Checked on 29 October 2026 against Lovart's docs and lovart.ai. #### Use Lovart when Lovart fits work where the picture is the product. - You need a set of matching stills: a key visual, posts, a poster, a deck. - You want to lay out and compare designs side by side on a canvas. - You need layered PSD or vector SVG files for a designer. - The video is a short piece that a design brief fully describes. #### Use invideo when invideo fits work where the timing is the product. - Several shots, a voice and a music bed have to line up, cut by cut. - You change one shot or one line and keep the rest of the cut. - The video needs captions that stay editable. - You make versions for each platform from one master. - An editor finishes it in Premiere Pro, Final Cut Pro or DaVinci Resolve. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. #### Use both Design in Lovart, then assemble in invideo. The hand-off is the exported files. 1. Make the key visual, the product shots and any short clips in Lovart. 2. Export them as PNG or MP4. 3. Upload them to the invideo project with `start_upload` and `add_media`. 4. Assemble them on a timeline with voice, music and captions. 5. Run `capture`, then `export`. Fonts come in the same way. Upload the brand's TTF or OTF file with `start_upload` and `add_media`, and `add_text` uses it. #### What Lovart does better Say it plainly: for design work, Lovart is the stronger tool. - One canvas holds graphics, ads, slides and video together. - Its agent makes finished design outcomes, not single images. - It exports layered PSD, vector SVG and PPTX files. - A brand kit set up once shapes every asset. #### Related - [Turn a product photo into a video without redrawing the product](/how-to/marketing/product-photo-to-video) - [Make a launch video from your product URL and screenshots](/how-to/marketing/launch-video) - [Every placement from one master](/how-to/marketing/every-placement-from-one-master) - [AI video tools compared, including invideo](/compare/alternatives) - [invideo for AI agents](/agents) ### Claude Motion Source: https://docs.invideo.io/compare/claude-motion.md Claude Motion animates charts and reports inside Claude. invideo edits its MP4 with footage, voice, music and captions on a timeline. Use Claude Motion when you want an animated chart or a short explainer made from your content, inside Claude. Use invideo when that animation becomes part of a longer video with footage, a voice and music, edited on a timeline. #### The same brief in both tools The brief: a 20 second animated chart intro for a quarterly report video. After the chart, the video cuts to the team's footage, with a voiceover and a music bed. In Claude Motion, you ask Claude in a chat for the animated chart. Claude writes code that animates the text, the chart, the shapes and the images. You change a word, a number or a timing in the chat or in the editor, and the rest of the animation stays the same. Then you export it as an MP4. Claude Motion does not use a video generation model, so it makes no realistic footage or people. In invideo, the MP4 comes into the project through the `import-claude-motion-from-url` tool, or your agent uploads the file with `start_upload` and `add_media`. The agent places it first on a timeline, then adds the team's footage after it. It voices the script with a TTS model such as `elevenlabs_text_to_speech.elevenlabs_tts_v4`, adds music from `search_library`, and adds captions with `add_captions`. You review the cut in the editor, and the agent runs `capture` and `export`. #### At a glance The rows below are the ones that change the choice for this job. | | Claude Motion | invideo | | --- | --- | --- | | What it makes | Animated charts, explainers and walkthroughs from your content | A full video from footage, stills, voice and music | | How it works | Claude writes animation code | Edit operations on a real timeline | | Change one detail | Ask Claude, or edit in its editor; the rest stays the same | Change one clip, text or keyframe; the rest stays the same | | Footage and people | None; no video generation model | Your footage, stock, and video models through `generate` | | Voice and music | Not in its help article | TTS models, voice clones, stock music and music models | | Captions | Not in its help article | An editable caption track | | Agent access | Inside Claude | CLI and skills for terminal agents; MCP server for clients without a shell | | Files out | MP4 | MP4, or a Premiere Pro, Final Cut Pro or DaVinci Resolve project | | Sharing | Private by default; share from the animation | Export pages and project URLs | Checked on 29 October 2026 against Anthropic's Get started with Claude Motion help article. #### Use Claude Motion when Claude Motion fits motion that comes straight from your content. - You want an animated chart for a board deck or an all-hands. - The data and the draft already live in your Claude chat. - You change numbers and words often and want the rest to stay put. - The whole video is text, charts, shapes and images, with no footage. #### Use invideo when invideo fits when the animation is one part of a video. - The video needs real footage, stock or generated shots around the animation. - It needs a voiceover, music that clears rights, or captions. - A person reviews and changes the full cut on a timeline. - You make versions for different platforms from one edit. - An editor finishes it in Premiere Pro, Final Cut Pro or DaVinci Resolve. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. #### Use both Make the animation in Claude Motion, then finish the video in invideo. The hand-off is the MP4. 1. Make the chart or explainer in Claude Motion. 2. Export it as an MP4. 3. Bring it into an invideo project with `import-claude-motion-from-url`, or upload it with `start_upload` and `add_media`. 4. Add footage, voice, music and captions on a timeline. 5. Run `capture`, then `export`. To change a number in the chart, change it in Claude Motion and export again. Your agent then replaces the clip on the timeline and keeps the rest of the cut. #### What Claude Motion does better Say it plainly: for animating your own content, Claude Motion is the shorter path. - It works where your content already is, in the chat. - It turns a chart or a report into motion with no timeline work. - One changed number or word leaves the rest of the animation the same. - You need no footage at all. #### Related - [Use Claude Motion with invideo](/integrations/claude-motion) - [Make a training explainer from a document, without an avatar](/how-to/training/explainer-from-a-document) - [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course) - [AI video tools compared, including invideo](/compare/alternatives) - [invideo for AI agents](/agents) ## Account ### Credits and what they cost Source: https://docs.invideo.io/account/credits.md What costs credits in invideo, what is free, how to see the price before you spend, and where to check your balance. Credits pay for AI work in invideo: generation, transcripts and paid stock. Edits and exports are free. Your agent runs a dry run first and tells you the price before it spends anything. This is the one page on money. For how credits work, start with the credits FAQ. Per-model prices are on the video, image and audio pricing pages, and in `find_models`. Top-ups are on the extra credits page. Plan prices are on the invideo pricing page. For one specific call, the dry run is the price. Do not infer pricing from anywhere else. ```json { "tool": "generate", "arguments": { "url": "", "model": "", "inputs": { "prompt": "slow push on the bottle" }, "dry_run": true } } ``` #### What costs credits These actions spend credits from the workspace you work in. - **Generation.** `generate` runs a model for video, images, audio or 3D. The price depends on the model and its inputs, such as length and resolution. - **Transcripts.** `media` with `audio.transcript`. Only the call that starts a transcript costs credits. Later calls on the same file to read the words cost nothing. - **Model ops in `media`.** `audio.separate`, `audio.clean`, `video.upscale`, `image.upscale`, `video.removeBackground` and `image.removeBackground` run a model and cost credits. Upscales charge by the length of the source. - **Paid stock.** `add_media` with `stock` places a stock result and charges its cost. For iStock, that is one of the workspace's iStock licenses. For other paid stock, it is a small credit charge. - **Agent Two in the invideo app.** Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. An outside agent's own chat, such as Claude or ChatGPT, runs on that app's plan. #### What is free These actions cost nothing. Your agent can use them as often as it needs. - Every timeline edit, by your agent with `edit_timeline` or by you in invideo Editor. - Every `export`: a video, its sound, a still, or an editable project. - Reads: `read`, `get_timeline`, `inspect_objects`, `capture`, `check_timeline`, `timeline_catalog`. - Price and model lookups: `find_models` and `get_model`. - Stock search with `search_library`, and a closer look at a stock result with `media`. - Looking at and listening to a file with `media`: `metadata`, `video.frames`, `audio.waveform`, `audio.loudness`, `audio.content`, `audio.onsets`, `audio.markers`, `audio.key`, `audio.sections` and `audio.beats`. - Bringing your own files in with `add_media` or `start_upload`, and importing from Google Drive. - Drawing in `/sketch`. Asking Agent Two to work from the drawing uses credits. `document.pages` and the tool ops in `media` that make a new file without a model, such as `video.trim`, `video.loop`, `image.crop` and `video.stitch`, can show a charge. The dry run shows its price before anything starts. #### See the price first Every call that can cost credits takes two fields. Use both, every time. - `dry_run: true` checks the inputs and returns the price. Nothing starts and nothing is spent. - `max_credits` is the most the call may cost. Nothing starts when the price is higher. `generate` needs it unless it is a dry run. `media` needs it on any op that costs. Run the dry run before the first paid call. Then tell the person the price, and start the real call with `max_credits` set to that price. Your agent calls `find_models` with a query. Each model comes back with its id and its price per generation, per second or per other unit. It sees a list of models with prices. Your agent calls `get_model` with the model id. It sees the input names it must fill. This call is free. Your agent calls `generate` or `media` with `dry_run: true` and the real inputs. It sees the price, and an error if an input is wrong. Nothing is spent. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. Your agent sends the same call without `dry_run` and with `max_credits`. It also passes an `idempotency_key`, so a retry after a timeout finds the first job and does not pay twice. It sees a thread URL at once. In a terminal, the same flags are on the commands that cost. ```bash invideo gen models --query "product video" invideo gen model --model invideo gen run --model --dry-run \ -i prompt="slow push on the bottle" invideo gen run --model --max-credits \ --idempotency-key -i prompt="slow push on the bottle" invideo media audio.transcript --dry-run invideo media video.upscale --dry-run ``` Where each value comes from: - `` comes from `invideo project new`. `` is a notebook page, from `invideo notebook new-page `, or a page listed by `invideo notebook show `. - `` is an id from `invideo gen models`, checked with `invideo gen model`. - `` is `estimated_credits` in the dry run's answer. Pass the same inputs on both runs. - `` is any text unique to this run. Reuse it on a retry. - `` is the file's URL, `…/notebook/seq-N.M`, from `invideo asset upload`. Paid `media` ops refuse a bin asset (`--asset`), so pass the sequence URL. When the pricing says the price is an estimate, the final charge can end above it. `max_credits` caps the estimate, not the final charge. Tell the person when a price is an estimate. #### See your balance Your agent can check the credits left before and after paid work. - **MCP.** `current_user` returns who is signed in and the credits left in the connection's default workspace. - **CLI.** `invideo auth status` prints the same, with the credits left. - **In the app.** Open your profile menu (your picture in the top right corner). It shows the credits left in the workspace, with **Top up credits** next to it. **Usage** shows credits, iStock and storage used this month. In a project, the project menu has **Project Usage** for that project's total. ```bash invideo auth status ``` #### When credits run out or reset A call that needs more credits than the workspace has is refused before it starts. In the CLI this is exit code 5, "a limit: credits or quota". Your agent stops and tells you. It does not retry. - **Plan credits.** On an active plan, credits and iStock reset each month on the date and time your plan started, in UTC. Unused plan credits do not roll over. - **Extra credits.** You can buy extra credits without changing your plan. They expire after a set period, or when your plan ends, whichever comes first. - **Plan ends.** When a plan ends, its credits do not carry over. See [Plans](/account/plans) for what changes by plan, and [Refunds and cancellation](/account/refunds) for credits after you cancel. #### Safety holds and confirmations A paid job can stop before it finishes. It does not charge again while it waits. Your agent follows it with `read` or `status`, and never calls `generate` again to check on it. | Status or exit code | What it means | What to do | | --- | --- | --- | | `held` | A safety review is running. It is not over. | Wait and read again later. | | Exit code 6 | A safety review holds the CLI job. It is not a refusal. | Wait, then run `invideo status` again. Do not resend. If it ends `failed`, change the input the review flagged. | | `needs_confirmation` | Only the person can confirm it, in invideo. | Send the person the URL to confirm. | | Exit code 8 | The CLI job needs the person's confirmation. | Stop and ask the person. | | `refused` | Nothing took effect. Nothing was spent. | Read `message` and fix the call once. | #### If something goes wrong Most cost problems come from a missing dry run or a resent call. | Symptom | Fix | | --- | --- | | The call is refused for a price above `max_credits`. | Run the dry run, tell the person the price, then send it with a higher cap. | | `generate` is refused without `max_credits`. | Add `max_credits`, or set `dry_run: true` to price it. | | A generation timed out and the agent wants to send it again. | Avoid a new call. Instead, resend with the same `idempotency_key`, or `read` the thread URL. | | The agent calls `audio.transcript` again to get the words. | This is correct. Only the first call spends credits. | | Exit code 5 in the CLI. | Stop. Tell the person the workspace is out of credits or quota. | | The price looks different from the pricing page. | Trust `find_models` and the dry run for that call. | #### Related - [Know the cost before you spend](/how-to/cost-before-you-spend) - [Plans](/account/plans) - [Refunds and cancellation](/account/refunds) - [Models](/reference/models) - [MCP tools](/reference/mcp-tools) - [Exit codes](/reference/exit-codes) ### Plans Source: https://docs.invideo.io/account/plans.md Where to find the invideo plans and prices for your region, what every plan includes, and how to change your plan. The plans and their prices are on the invideo pricing page. Plans differ by region, so the pricing page shows the plans for yours. For seats, storage, model access and the other limits of each plan, read the plan limits page and the credits FAQ. This page does not list plans or compare them. #### What every plan has The editor itself is the same on every plan. Every plan includes these. - The timeline editor, with color, audio and 3D tools. - Multiplayer editing in the same project. - Edits you make in invideo Editor, and edits an outside agent makes with `edit_timeline`. - Exports with `export`. - invideo MCP and the invideo CLI. Your agent signs in to your account the same way on every plan. Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything. See [Credits and what they cost](/account/credits). Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. #### What your plan controls for your agent Your plan sets the credits, seats, storage and models your workspace has. The pricing page and the plan limits page have the details. Your agent sees the effect, not the plan name. - `find_models` lists only the models your workspace can use, with each one's price. `invideo gen models` prints the same list. - A paid call is refused when the workspace is out of credits. `current_user` and `invideo auth status` show the credits left. ```bash invideo gen models --query "video" ``` `` comes from `invideo project new` or `invideo project list`. #### Change or add to your plan You manage your plan under **Subscriptions** in your profile menu (your picture in the top right corner). Your agent cannot change your plan or buy credits for you. - **Upgrade.** You can upgrade at any time. Upgrades are prorated, so you pay the difference for the rest of the billing period. - **Annual to monthly.** The change takes effect at the end of the current billing period. - **More credits.** You can buy extra credits without changing your plan or billing period. See the extra credits FAQ. - **More seats.** Set the number of seats under **Subscriptions**. See [Seats and workspaces](/account/seats). - **Card details.** Choose **Update payment method** under **Subscriptions**. Prices, currency and payment questions are answered on the pricing page and in the payments, invoices and errors FAQ. If you subscribe in the iOS or Android app, Apple or Google sets the price you see. #### If something goes wrong Most plan problems show up as a refused call. | Symptom | Fix | | --- | --- | | A model is missing from `find_models`. | Your plan does not include it. Pick another model, or change your plan under **Subscriptions**. | | A paid call is refused, or the CLI exits with code 5. | The workspace is out of credits or quota. Buy credits or wait for the reset. | | Your agent tells you a price for a plan. | Avoid prices from the agent. Instead, check the pricing page for your region. | #### Related - [Credits and what they cost](/account/credits) - [Seats and workspaces](/account/seats) - [Refunds and cancellation](/account/refunds) - [Models](/reference/models) - [Is there an invideo API?](/api) ### Refunds and cancellation Source: https://docs.invideo.io/account/refunds.md How to cancel an invideo plan on the website, iOS or Android, what happens to your credits, and how to ask for a refund. You can cancel an invideo plan at any time. The plan stays active until the end of the billing period you paid for. A refund is possible only for a plan you have not used, if you ask within the refund window in the terms after you buy or renew. The terms and conditions are the final word on refunds. How renewals, upgrades, cancellations and refunds work is on the subscriptions and refunds FAQ. Payment methods, invoices and failed payments are on the payments FAQ. Plans and billing periods are on the invideo pricing page. Your agent cannot cancel a plan or ask for a refund for you. There is no tool or command for billing. You do these steps yourself. #### Cancel a website subscription Use these steps if you paid on invideo.io with a card. Click your profile in the top right corner and choose **Subscriptions**. Click **Cancel** and follow the steps on the screen. The page shows that the plan stays active until the end of the billing period. You keep its features until then. At the end of the period, the paid features end and invideo removes your card from the account. #### Cancel an iOS or Android subscription If you subscribed in the invideo app, Apple or Google bills you. You cancel in the store, not on invideo.io. - **iOS.** Cancel in your Apple account. See Apple's guide to canceling a subscription. - **Android.** Cancel in Google Play. See Google's guide to canceling a subscription. #### What happens to your credits and projects Canceling does not take anything away before the period ends. These things change when the period ends. - **Plan credits.** Unused credits from the plan do not carry over. Plan credits do not roll over from month to month on any plan. - **Extra credits.** Credits you bought on top of the plan end when your plan ends. - **Credits are not refunded.** The terms say that credits are non-refundable and cannot be transferred. - **Projects.** Your projects stay in your workspace. You can still open and edit them. - **Exports.** Your exported videos stay yours. Exports are free, so you can export an edited project after the plan ends. #### Ask for a refund invideo reviews each request on its own and decides at its own discretion. A plan can qualify only when both of these are true. - You ask within the refund window after the first purchase or a renewal. The terms state the window. - You have not used the plan in the current billing period. The terms count a plan as used once credits were spent or a premium feature was used in that period. A used plan does not qualify. Contact support from the chat button on the invideo site, or email support@invideo.io. Include the email address of your invideo account and the reason for the refund. invideo replies by email. invideo processes an approved refund at once. Your bank can take several business days to show it. If you paid through the Apple App Store, Apple handles the refund. Use Apple's refund request page. If you paid through Google Play, start with support@invideo.io. The help center does not describe a separate path for Google Play refunds. #### Picked the wrong billing period If you chose an annual plan by mistake, you have two options. - **Ask for a refund.** If you have not used the plan, ask within the refund window, as above. - **Switch to monthly.** Under **Subscriptions**, choose the monthly version of your plan. The change takes effect at the end of the annual period, not at once. You lose the annual discount from then on. #### If something goes wrong These are the common problems with cancellation and refunds. | Symptom | Fix | | --- | --- | | You cannot find **Cancel** under **Subscriptions**. | You subscribed in the app. Cancel in the App Store or Google Play. | | You canceled, but the plan is still active. | This is expected. It stays active until the end of the period. | | The refund was declined. | Credits were spent or a premium feature was used in the period, or the window passed. | | You were charged after you canceled. | Check the date. A renewal before you canceled starts a new period. Contact support. | | Your agent offers to cancel the plan. | Avoid this. Instead, cancel under **Subscriptions** yourself. | #### Related - [Plans](/account/plans) - [Credits and what they cost](/account/credits) - [Seats and workspaces](/account/seats) - [Security and data](/account/security-and-data) - [How can I cancel my subscription?](/billing/how-can-i-cancel-my-subscription) - [Refunds: how to request one and what's covered](/billing/refunds-how-to-request-one-and-what-s-covered) ### Sign in, device codes and sessions Source: https://docs.invideo.io/account/sign-in.md How you and your agent sign in to invideo: in the browser, with a device code when there is no browser, and how to sign out. You sign in to invideo in your browser. Your agent then works in your account, in the workspaces you chose. When the agent runs where no browser can open, it signs in with a device code: it sends you a link and a code, and you approve on your own device. There are no API keys and no passwords. ```bash invideo auth login INVIDEO_NO_BROWSER=1 invideo auth login invideo auth status ``` #### How you sign in to invideo invideo has no passwords. On the sign-in page you choose one of these. - **Join with Google**, if you signed up with Google. - **Join with Apple**, if you signed up with Apple. - **Your email address.** invideo emails you a short code. Enter it on the page. If the code does not arrive, check your spam folder. If it still does not arrive, try another email address or contact support from the chat button on the invideo site. #### Sign in from an MCP client Each MCP client starts the sign-in when it connects to `https://mcp.invideo.io/mcp`. You sign in to invideo in the browser and choose the workspaces the agent may use. Clients differ in who starts the step. Terminal agents (Claude Code, Codex, Antigravity, and Cursor with the skills) sign in through the CLI, below. | Client | Who signs in, and how | | --- | --- | | Claude (claude.ai or desktop) | Add invideo in **Customize**, then **Connectors**, and click **Connect**. The client opens the sign-in and retries the call. | | ChatGPT | Install the official invideo plugin, then sign in when ChatGPT asks. The client runs the sign-in itself. | | Gemini app | Add invideo as a custom app in **Connected Apps** and follow the on-screen steps. Google limits who can add custom apps; see [Use invideo in Gemini](/start/gemini). | | Gemini CLI | Run `/mcp auth invideo` when invideo asks for sign-in. With no browser, use the invideo CLI for that session instead of MCP. | | VS Code and any other client | The client runs the OAuth sign-in when it connects. If it cannot, use the device code below. | #### Sign in from the CLI The CLI keeps one sign-in per machine. You sign in once, then every command runs as you. Run `invideo auth login`. It opens your browser on this machine and waits until you approve. Your agent runs it in the background, or with a long timeout, because the wait can take a few minutes. It sees the command finish when you approve. Sign in to invideo in the tab that opened, and approve. Then go back to the terminal. Run `invideo auth status`. It prints your name, email and the credits left. If it exits with code 4, the sign-in did not finish. Run `invideo auth login` again. The CLI keeps your sign-in on this machine, outside your project folders. `invideo auth logout` forgets it. #### Sign in with a device code Use a device code when no browser can open on the machine: over ssh, in a container, on a cloud machine, or in a cloud agent. You approve on a phone or laptop you hold. ```bash INVIDEO_NO_BROWSER=1 invideo auth login ``` It prints a link and a code. Open the link on another device and enter the code. Your agent never asks you to send the code back, and never asks for a password. Your agent runs the command in the background, because it waits for your approval. It sends you the link and the code in one message. You choose your workspaces and approve. This device code signs in the CLI only. It does not sign in an MCP connection, because the CLI and the MCP server use separate sign-ins. An MCP client with no browser uses the device flow over HTTP, below. #### Device flow over HTTP An agent that calls `https://mcp.invideo.io/mcp` with no browser and no CLI signs in with this flow. It ends with an access token and a refresh token. For CI jobs and servers, see [Run invideo in CI and on servers](/how-to/ci-and-servers). Fetch the server's protected-resource document. Its `invideo_device_authorization` field gives the `client_id` and the `device_authorization_endpoint`. The token endpoint is `/oauth/token` on that host. You see both URLs and the `client_id`. POST the `client_id` to the device endpoint. The answer has `device_code`, `user_code`, `verification_uri`, `expires_in` and `interval`. On `unauthorized_client`, the `error_description` names the right `client_id`. Send one message: open the `verification_uri` and enter the `user_code`. Say when it expires. The person chooses the workspaces there and approves. POST the same `device_code` to the token endpoint every `interval` seconds. On `authorization_pending`, wait. On `slow_down`, add 5 seconds. On `access_denied`, stop and tell the person. On `expired_token`, start one new flow. You see `access_token` and `refresh_token`. Send `authorization: Bearer ` on every request. The access token lasts for its `expires_in` seconds. Read the field; do not assume a length. ```bash MCP_URL=https://mcp.invideo.io/mcp ORIGIN=$(echo "$MCP_URL" | cut -d/ -f1-3) curl -s "$ORIGIN/.well-known/oauth-protected-resource${MCP_URL#"$ORIGIN"}" curl -s -X POST "$DEVICE_ENDPOINT" -d "client_id=$CLIENT_ID" curl -s -X POST "$TOKEN_ENDPOINT" \ -d grant_type=urn:ietf:params:oauth:grant-type:device_code \ -d "device_code=$DEVICE_CODE" -d "client_id=$CLIENT_ID" ``` `$DEVICE_ENDPOINT` and `$CLIENT_ID` come from the first command's answer. `$TOKEN_ENDPOINT` is `/oauth/token` on the device endpoint's host. `$DEVICE_CODE` comes from the second command's answer. To refresh, POST `grant_type=refresh_token` with the `refresh_token` and the `client_id` to the same token endpoint. Sessions and staying signed in, below, has the rules. #### The rule for agents Your agent never asks you for a password, an email code, or the device code back. It sends you the link and the code, once, in one message, and waits. - Send one message per code. Do not ask for a new code while one is waiting. - The person may be away for a while. Waiting is normal. Do not start a new code because they have not approved. - If the person denies the request, stop and tell them. - If the code expires, start one new sign-in with one new message. If that expires too, stop. - Keep tokens and codes out of chat, out of files the person sees, and out of logs. #### Sessions and staying signed in A sign-in lasts across sessions, but it can lapse. When it does, the next call returns a sign-in challenge, or the CLI exits with code 4. - **Claude Code, Codex, Cursor and Antigravity.** These use the CLI. Run `invideo auth login` again. - **Claude and ChatGPT.** The client asks you to sign in again. - **Any other shell.** Run `invideo auth login` again. - **Device flow over HTTP.** The agent keeps the refresh token in its own secret store, not in chat. When a call returns 401, it uses the refresh token to get a new access token. Each refresh returns a new refresh token, so the agent stores the new one every time. It starts a new device sign-in only when the refresh fails. To use a workspace you did not choose at sign-in, connect again and choose it. See [Seats and workspaces](/account/seats). #### Sign out How you sign out depends on where you signed in. - **CLI.** Run `invideo auth logout`. It forgets this machine's sign-in. - **MCP clients.** Remove invideo in the client. In Claude, remove the connector under **Customize**, then **Connectors**. In ChatGPT, remove the plugin. In the Gemini app, disconnect the custom app. In Gemini CLI or VS Code, remove the server. ```bash invideo auth logout ``` #### If something goes wrong Most sign-in problems are a step that only the person can do. | Symptom | Fix | | --- | --- | | The agent says it needs your account. | Finish the sign-in step for your client, then ask again. | | Claude Code or Codex does not use invideo. | Check the plugin with `claude plugin list` or `codex plugin list`. Then ask for the video job again. | | The CLI exits with code 4. | Run `invideo auth login`, or `INVIDEO_NO_BROWSER=1 invideo auth login` without a browser. | | `invideo auth login` stops before you approve. | The agent's shell timed out. Run it in the background or with a longer timeout. | | A project URL does not open for the agent. | The project is in a workspace you did not choose. Connect again and choose it. | | The agent asks you for a code or a password. | Avoid this. Instead, the agent sends you the link and code, and you approve. | #### Related - [invideo for AI agents](/agents) - [Is there an invideo API?](/api) - [Run invideo in CI and on servers](/how-to/ci-and-servers) - [Seats and workspaces](/account/seats) - [Environment variables](/reference/environment) - [Exit codes](/reference/exit-codes) ### Seats and workspaces Source: https://docs.invideo.io/account/seats.md How invideo workspaces, seats and members work, how to switch, and which workspaces and projects your agent can see. A workspace is where your projects, files and credits live. One account can belong to several workspaces, and each workspace has its own plan. A seat is one member's place in a workspace with an active plan, with its own monthly credits. Your agent works only in the workspaces you chose when you signed it in. ```json { "tool": "list_workspaces", "arguments": {} } ``` ```bash invideo workspace list ``` #### Workspaces Every project belongs to one workspace. Each workspace has a name, a URL and a plan. - **Your own workspace.** You get one when you create your account. - **Workspaces you join.** A colleague adds you as a member of their workspace. It then appears next to yours. - **One plan per workspace.** Each workspace has its own subscription. Credits spent in a workspace come from that workspace's plan. - **The name.** Change it under **Settings**, in **Workspace settings**. The name shows when you share a video. To switch workspaces in the app, click the profile icon in the top right corner and pick the workspace from the menu. #### Seats and members On an active plan, each member takes a seat. Each seat comes with its own monthly credits. The seat count you can buy depends on the plan. See [Plans](/account/plans), the plan limits page and the pricing page. Open your profile menu (your picture in the top right corner) and choose **Subscriptions**. Set the number of seats on your plan and confirm. Upgrades are prorated for the rest of the billing period. Open your profile menu and choose **Members**. Invite each person there. The person signs in, switches to your workspace and sees its projects. If they do not, check that they accepted the invite. Your agent cannot add seats or invite members. You do this in the app. #### Which workspaces your agent sees Your agent sees the workspaces you chose when you signed it in, and no others. Each MCP connection and each CLI sign-in has its own set. - `list_workspaces` lists those workspaces, each with its URL. One is marked as the default. - `invideo workspace list` prints the same list in a terminal. - `list_projects` and `new_project` work in the default workspace when the agent does not pass a workspace URL. To work in another one, the agent passes that workspace's URL as `url`. - `current_user` and `invideo auth status` show the credits left in the default workspace. To add a workspace, connect again and choose it at sign-in. In the CLI, run `invideo auth login` again. In a chat app, disconnect invideo and connect it again. See [Sign in, device codes and sessions](/account/sign-in). ```bash invideo project list invideo project new --title "Launch teaser" ``` `` is a workspace's URL, `https://invideo.io/@`, from `invideo workspace list` or `list_workspaces`. #### Who can see a project A project belongs to its workspace. Members of the workspace can open it and watch edits land live. You share a project with anyone else from the **Share** button in the project. It opens one share modal: add a person by email, see who has access and their role, and set the general access and copy the link. Your agent cannot share a project. You do this in the app. - **General access.** *Your workspace* is the default: members open the link, and anyone else sees a request-access page. *Anyone with the link* lets anyone signed in to invideo view, comment and fork. *Restricted*, on the plans that include it, allows only invited people and no link sharing. - **Adding a person.** *Add to workspace* gives the person a guest seat and access to every open project in the workspace; their credits come from your workspace. *Connect* gives access to this one project, uses no seat, and their credits come from their own workspace. - **Roles in a project.** *Editor* edits the project. *Viewer* views the whole project, comments and forks. *Preview only* sees the preview tab and the timeline previews, and comments. A person from outside the workspace can hold any role. - **Request access.** Someone who opens a link without access signs in and requests access. You get a notification that opens the share modal, where you add them to the workspace or connect them to the project. - **Restricted pages.** Some notebook pages are limited to some people. invideo refuses a write the person may not make there, before anything is made. - **Agents** act as the person who signed them in. An agent can open only what that person can open. - **Export pages** share a result outside the project. A new export page is private. `share_export_page` sets a page to `public` (anyone with the URL), `shared` (members of the workspace) or `private` (only you). See [Security and data](/account/security-and-data). Several agents can work in one project with a person. Each agent registers a name with `register` and passes it as `as`, so people see who did what. See [Run several agents and a person in one project](/how-to/developers/several-agents-one-project). #### Claude Team and Enterprise organizations In a Claude Team or Enterprise organization, an owner adds the invideo connector first, in the organization's connector settings. Each person then connects it to their own invideo account. #### If something goes wrong Most workspace problems come from the workspaces chosen at sign-in. | Symptom | Fix | | --- | --- | | A project URL is refused or not found. | The project is in a workspace the agent cannot see. Connect again and choose that workspace. | | `list_projects` shows the wrong projects. | The agent used the default workspace. Pass the right workspace URL from `list_workspaces`. | | The credits left look wrong. | `current_user` shows the default workspace. Check the workspace the project is in. | | A member cannot see the project. | Check that they switched to your workspace, and that the page is not restricted. | | Your agent asks you to add a seat for it. | Avoid this. An agent does not need a seat. It works as the person who signed it in. | #### Related - [Sign in, device codes and sessions](/account/sign-in) - [Plans](/account/plans) - [Security and data](/account/security-and-data) - [Run several agents and a person in one project](/how-to/developers/several-agents-one-project) - [How to switch between workspaces](/account-and-workspaces/how-to-switch-between-workspaces) - [How to add team members](/account-and-workspaces/how-to-add-team-members) ### Security and data Source: https://docs.invideo.io/account/security-and-data.md Where your invideo files live, who can see a project, how sharing and export permission work, and how to delete a project, workspace or account. Your footage, generations and exports live in your invideo project, in invideo's cloud. Members of the workspace can open the project, and so can the people you share it with. A new export page is private. Nothing leaves the workspace until you share the project, set an export page to `shared` or `public`, or download a file. You can delete a project, a workspace or your whole account. ```json { "tool": "share_export_page", "arguments": { "url": "", "visibility": "private" } } ``` #### Where your files live Everything you bring in or make belongs to one project in one workspace. - **Uploads and imports.** `add_media` and `start_upload` put your files in the project, as sequences in the notebook. - **Generations.** Each `generate` result is a sequence in the project. - **Project files.** Downloads, brief files, fonts and documents sit under the project's files, at its `…/assets` URL. - **Download links.** When your agent reads a file, it gets a fresh download URL. The URL expires. A new `read` gives a new one. - **Google Drive.** When you connect Google Drive, invideo sees only the files you pick, not the rest of your Drive. Storage counts against your plan. Open **Usage** in your profile menu to see how much you use. #### Who can see a project A project belongs to its workspace. These are the people and agents who can see it. - **You and the workspace members.** They open the project and watch edits land live. See [Seats and workspaces](/account/seats). - **People you share the project with.** The **Share** button in the project opens one share modal. You add a person by email, as a guest in your workspace or as a connect to this one project, and give them a role: editor, viewer or preview only. General access is your workspace by default; you can open the link to anyone signed in to invideo, or restrict it to invited people on the plans that include it. Someone without access who opens the link can request it. The roles and options are listed under [Who can see a project](/account/seats#who-can-see-a-project). - **Restricted pages.** Some notebook pages are limited to some people. A write the person may not make is refused before anything is made. - **Your agent.** It acts as you, in the workspaces you chose at sign-in. It can open only what you can open. It cannot share a project. What your agent reads goes into your AI app. Frames from `capture`, words from a transcript and file details come back to the agent's chat. That chat follows the AI app's own terms, not invideo's. Keep that in mind for private interviews or client footage. #### Share an export page An export page shares one result outside the project. A new export page is private. `share_export_page` sets who can see a page and what they can do. | Visibility | Who can see the page | | --- | --- | | `public` | Anyone with its URL. | | `shared` | Members of the workspace. | | `private` | Only you. | For each visibility, the page also sets whether people may comment and download. It also sets what the workspace may do with the page: view, comment or edit. Your agent asks you before it makes a page public. ```bash invideo export share --visibility shared \ --team-access comment ``` The export page's URL, `…/exports/`, comes from `add_to_export_page` or `invideo export add`. It is `` in the MCP call above and `` in the command. #### Export permission An export needs export permission on the project. Without it, `export` is refused and nothing is made. Ask the person who manages the project to give you the permission. Exports are free. #### How invideo handles your data The invideo CLI runs on your machine. - It keeps your sign-in on this machine, outside your project folders. `invideo auth logout` forgets it. - It talks only to invideo, over HTTPS. - It reads only the files you name, and writes only into the `--out` folder you give. - It sends no telemetry, and runs nothing but your browser for sign-in. For a security review, SSO or compliance reports, see the enterprise page. The terms and conditions say how invideo may use the content you upload, and how deleting it or closing your account stops that use. The privacy policy covers personal data. This page does not state retention periods. Read the privacy policy for them. #### Delete a project You delete a project in the app. Your agent has no tool to delete a project. Select the logo in the top left corner, then select **Show all**. Click the trash can icon on the project and select **Delete**. Confirm the deletion. The project is removed from your account for good. To delete exported videos, click **You** in the left panel, open **Downloads** with **See all**, click **Edit**, select the videos and click **Delete**. Inside a project, your agent can remove a context entry by writing it with empty markdown using `write`. The same call on a brief archives it. #### Delete a workspace or your account Deleting the workspace comes first, then the account. You are signed out when the account is gone. - **On the web.** Open **Settings**, choose **Manage account**, then **Delete workspace**, then **Delete account**. - **In the iOS or Android app.** Tap the arrow next to the logo in the top left corner. Open the **Members** page, delete the workspace, then delete the account. The app allows this only when no plan is active, so your plan must end first. See [Refunds and cancellation](/account/refunds). - **If it does not work.** Fill in the account deletion form. invideo deletes the account and emails you if it needs more information. After you delete the account, sign out of the CLI on each machine with `invideo auth logout`, and remove invideo from your AI apps. #### If something goes wrong These are the common problems with access and deletion. | Symptom | Fix | | --- | --- | | `export` is refused for permission. | Ask the person who manages the project for export permission. | | An export page does not open for someone. | The page is `shared` or `private`. Set it to `public`, or add the person to the workspace. | | A member cannot open the project. | They are in another workspace, or the page is restricted. | | A download link stopped working. | It expired. `read` the file again for a fresh URL. | | You cannot delete the account in the app. | The account has an active plan. Wait for it to end, or use the deletion form. | | The agent makes a page public without asking. | Avoid this. Instead, the agent asks you before it shares outside the workspace. | #### Related - [Seats and workspaces](/account/seats) - [Sign in, device codes and sessions](/account/sign-in) - [Licensing and commercial use](/account/commercial-use) - [Refunds and cancellation](/account/refunds) - [What does export visibility mean?](/projects-and-exports/what-does-export-visibility-mean) - [How do I delete my draft projects?](/projects-and-exports/how-do-i-delete-my-draft-projects) ### Licensing and commercial use Source: https://docs.invideo.io/account/commercial-use.md Who owns what you make in invideo, and how stock, music and generated media are licensed for commercial use. You own what you upload to invideo. You can use the videos you make, including for commercial work, under the invideo terms and conditions. Stock media inside a video stays under its own license. This page sums up the terms in plain words. The terms are the final word. ```json { "tool": "search_library", "arguments": { "url": "", "library": "stock_music", "query": "calm acoustic" } } ``` #### What you own The terms split what is in a video into three kinds. Each has its own rule. | What | The rule in the terms | | --- | --- | | Your uploads | You keep ownership of the files you bring in. | | Generated media | invideo gives you whatever rights it has in what you generate. You may use, change, share and sell it, worldwide, with no royalty. | | Stock media | Licensed to you for use in your videos. It stays under its own license, and you get no exclusive rights to it. | The rights in generated media hold "subject always to these Terms, applicable law and third-party rights". invideo cannot give you rights it does not have. For example, a prompt that copies a known character or a real person's likeness can break someone else's rights. #### Stock video, images and music Your agent finds stock with `search_library` in `stock_video`, `stock_image` or `stock_music`. Searching and looking are free. Your agent calls `search_library` with a library and a query. Each result has an id and a low-resolution `preview`. The person can look at it before anything is paid. Your agent calls `media` with `stock` set to the result's id, to read frames or sound. This is free. It reads the preview, not the clean file. Your agent calls `add_media` with `stock`. This charges the result's cost: one of the workspace's iStock licenses for iStock, or a small credit charge for other paid stock. On the timeline, paid stock shows invideo's stock mark. `export` renders it clean, without the mark. ```bash invideo library search --library stock_music \ --query "calm acoustic" invideo asset add --stock ``` `` comes from `invideo project new` or `invideo project list`. `` is a result's `id` from `invideo library search`. An active plan includes standard stock from libraries such as Storyblocks, Shutterstock, Pexels and Pixabay, and a monthly allowance of iStock licenses. The allowance resets each month and does not roll over. See [Plans](/account/plans). Stock music sits in `stock_music` and follows the same stock rules. The terms treat it as licensed audio. See [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects). #### Generated media Images, video, voice and music from `generate` are generated media under the terms. You may use them commercially. Some care is still on you. - **People and brands.** Do not generate a real person's likeness or voice, or another company's logo or character, without the right to use it. - **Voice clones.** Clone only a voice you have the right to use, such as your own. - **Ads.** Ad platforms have their own rules for AI content. See [Label AI content so the ad runs](/how-to/marketing/ai-disclosure-for-ads). #### What this page does not settle The help center and the terms do not answer some questions. Check the terms, or ask support@invideo.io, before you rely on these. - Whether a platform such as YouTube can raise a content claim on a stock music track. - The license terms of each stock provider. The terms include them by reference but do not quote them. - The terms of each model provider for the media it generates. #### If something goes wrong These are the common licensing problems. | Symptom | Fix | | --- | --- | | A stock clip cost credits you did not expect. | Paid stock is charged when the agent places it with `add_media` and `stock`. Each `search_library` result shows its `cost`. Ask your agent to tell you the cost first. | | `add_media` with `stock` is refused. | The workspace is out of credits, or out of iStock licenses for the month. Buy credits, swap the clip for standard stock, or wait for the reset. | | A video is claimed on a platform. | Contact support with the stock id and the claim. | | The agent saves a stock preview as a file and places it. | Avoid this. Instead, place stock with `add_media` and `stock`, so it is licensed and the export uses the clean file. | #### Related - [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects) - [Label AI content so the ad runs](/how-to/marketing/ai-disclosure-for-ads) - [Plans](/account/plans) - [Credits and what they cost](/account/credits) - [Security and data](/account/security-and-data) ## Help center --- ### Agents & models on invideo Source: https://docs.invideo.io/getting-started/agents-models-on-invideo.md invideo gives you the leading AI models for video, image, audio and 3D, next to a timeline editor, in one workspace. invideo gives you the leading AI models for video, image, audio and 3D, next to a timeline editor, in one workspace. Pick the model that fits your project, name it in your prompt, or select it in the **Agents & models** panel. See [Models](/reference/models) for the models by job. 1. From the homepage, click **Agents & models** in the bottom navigation. 2. Browse by category, or type the model name in your prompt. invideo sends the generation to that model. 3. Click the **settings icon** before you generate to see the exact cost for your settings. The cost depends on the model, resolution and duration. The video model pricing page has the full breakdown. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. See [Credits and what they cost](/account/credits). Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. See [Models](/reference/models#when-a-model-retires). ### Introducing invideo Editor Source: https://docs.invideo.io/getting-started/introducing-invideo-editor.md Explore invideo Editor’s multitrack timeline, Agent Two, audio mixing, color controls and generation in one project. invideo Editor is a professional video editor in your browser, with a timeline like the one in Premiere Pro or DaVinci Resolve. The difference is that an agent does the heavy lifting with you, and generates the shots, voices and music a project lacks. invideo Editor with source and timeline monitors, the Transitions panel and an agent editing the multitrack timeline Talk to Agent Two in the agent panel on the left. Tell it what you want, such as *"cut this down to 60 seconds"*, *"clean up the silences"* or *"match the color on these two shots"*. Agent Two works directly on your timeline. Every change shows up as real clips and cuts that you can grab, reshape or undo. Nothing is locked, and the edit stays yours. #### What makes this timeline different The agent understands your footage: what is in each shot, who is talking and how the whole thing is structured. So when you ask for a change, it makes an informed one. Hand it as much or as little as you like. Let the agent build the whole cut, or edit frame by frame yourself. Both happen on the same timeline. You can also bring people from your workspace into the same project. You work together, live, in one timeline, instead of passing files back and forth. #### For hands-on editing invideo Editor has what a serious editor expects: a multitrack timeline, keyframes, color grading, a full audio mixer, effects and transitions. Generate new shots, voiceovers or music without leaving the project. You can also open an existing project, or bring in a Premiere Pro or DaVinci Resolve project to keep working on it. When you are done, export an MP4, or make a project file for Premiere Pro, DaVinci Resolve or Final Cut Pro with your cuts intact. #### How to open it Follow these steps to start: 1. On invideo.io, select **Timeline Editor** below the prompt box and create a blank timeline. 2. Open **Media** and upload or drag in your footage. 3. Create an agent and tell it how to assemble your footage into a base cut. You can also open an existing project. ### How to get started with invideo Editor Source: https://docs.invideo.io/getting-started/how-to-get-started-with-invideo-editor.md Open invideo Editor, upload your footage and make your first timeline edit in your browser. Create a blank timeline, upload your footage and arrange it. invideo Editor is a professional video editing workspace with a multitrack timeline, audio mixing and color controls. Edit by hand, and bring in Agent Two or your own agent when you want help. #### Start a project Follow these steps for your first edit: 1. Sign in at invideo.io. 2. Select **Timeline Editor** below the prompt box and create a blank timeline. 3. Open **Media** and upload your video, images or audio. You can also drag files into the panel. 4. Drag media onto the timeline and arrange a short sequence. For help with the assembly, create an agent and describe the cut you want. 5. Preview the sequence in the **Monitor**. Refine the timing, then use the **Audio** and **Color** workspaces as needed. 6. Select **Export** when your edit is ready. For a first project, choose a few clips and one clear goal. Check the opening shot, the order of the sequence and whether the sound is easy to follow before you add more effects. Already started a project? Follow the [saved timeline guide](/projects-and-exports/how-to-find-and-reopen-a-saved-timeline-in-invideo-editor) to reopen your existing cut. Edits and exports are free. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. See [Credits](/account/credits). --- ### How credits are charged when using AI Agents Source: https://docs.invideo.io/credits-and-plans/how-credits-are-charged-when-using-ai-agents.md How Agent Two charges credits for its work and generation, how to check what you used, and how to approve each generation. Agent Two is invideo's own agent. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. What you pay depends on the models Agent Two uses and how much it makes in each exchange. Each time the agent answers you, it can do several things at once: reason through your brief, generate images, make video clips, design a voice and more. Each of these actions uses credits, based on the models that run in the background. An outside agent, such as Claude or ChatGPT, runs its own chat on that app's plan. It runs a dry run first and tells you the price before it spends anything. See [Credits and what they cost](/account/credits). The mode you choose changes how many credits each generation uses. #### Lite, Pro and Ultra: what's the difference? Agent Two has these modes: - **Lite**: fast and light on credits. Built for sketching, testing and early creative work. Use it when you want to move quickly and try many ideas. - **Pro**: premium quality across the board. Best for final output and finished work. Each generation costs more credits. - **Ultra**: the highest-quality models and settings, on top of Pro. Use it for your final cut. Exports are 1080p MP4 in every mode. In Pro and Ultra, Agent Two can upscale the exported file for a higher resolution. Lite does not upscale. #### How to check credits used After the agent finishes a response, click the **three dots (···)** on that message. You see the credits charged for that exchange, for the conversation and all media made in it. To see the total credits used across a project, close the Agent window, click the **three dots** in the top right corner, and select **Project Usage**. The three-dot menu in the top right corner open on the project usage panel, showing credits used in this project For the price of each model, see [Credits and what they cost](/account/credits). #### Set a credit limit for a member To cap what one person can spend, set a credit limit for them. Open your profile menu (your picture in the top right corner), choose **Members**, and open **Set limit** for that member. Choose **Unlimited** or **Set amount**, type the amount, then click **Set limit**. Agent Two stops generating for that member when they reach it. The Set limit dialog for one member, with Unlimited and Set amount options, an amount field and the Set limit button #### Staying in control of generations By default, the agent is set to **Always allow**. It generates without asking for permission. For more control, click the permission toggle in the chat box and select one of these: 1. **Ask before generating videos**: the agent asks for approval before it generates a video. 2. **Always ask before generating**: the agent asks for permission before any generation. When the agent asks for approval, you see an **Approve** popup. It shows what the agent is about to make: the prompt, model, duration and aspect ratio. You can approve it as it is, or change any of these before you confirm. This helps when you want tight control over credit usage. You review each generation before it runs, so your credit balance holds no surprises. For how credits work and the credit prices by model, see the how credits work, video model pricing, image pricing and audio pricing FAQ pages. ### Is invideo Editor free and which actions use credits Source: https://docs.invideo.io/credits-and-plans/is-invideo-editor-free-and-which-actions-use-credits.md Edits on the invideo Editor timeline are free. Generation, transcripts, paid stock and Agent Two's work use credits. Yes. Edits on the invideo Editor timeline are free, whether you make them yourself or an outside agent makes them. You can arrange clips, adjust picture and sound, and refine your cut without credits. #### What uses credits Generation, transcripts and paid stock use credits. Agent Two is invideo's own agent. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. One Agent Two response can include both work on your request and new media, so credits are not only for finished video clips. An outside agent's own chat runs on that app's plan. See [Credits and what they cost](/account/credits) and [How Agent Two charges credits](/credits-and-plans/how-credits-are-charged-when-using-ai-agents). To check a finished Agent Two exchange, open the message's three-dot menu. To see the project total, close the Agent window, open the project menu at the top right and select **Project Usage**. For what credits pay for, see the how credits work FAQ page. ### Does drawing with /sketch use credits? Source: https://docs.invideo.io/credits-and-plans/does-drawing-with-sketch-use-credits.md Drawing a reference in /sketch is free. Asking Agent Two to work from it, or to generate media, can use credits. No. Drawing in **/sketch** uses no credits. Asking Agent Two, invideo's own agent, to work from the reference or to generate images and videos uses credits. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. You can finish the drawing before you ask Agent Two for anything. To review media generation before it starts, choose **Always ask before generating** in the chat's generation permission settings. Agent Two's work uses credits even when it makes no new media. See [How Agent Two charges credits](/credits-and-plans/how-credits-are-charged-when-using-ai-agents) for the full explanation, and [Credits and what they cost](/account/credits) for what is free. For what credits pay for, see the how credits work FAQ page. ### Does importing files from Google Drive use invideo credits? Source: https://docs.invideo.io/credits-and-plans/does-importing-files-from-google-drive-use-invideo-credits.md Importing your selected Google Drive files is free. Agent Two's work and generation after the import can use credits. No. Importing files from Google Drive uses no invideo credits. The work you ask for after the import can use credits. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. Bringing footage into a project and asking Agent Two to edit it are separate actions. Edits you make on the timeline yourself use no credits. For the work Agent Two charges to your project, see [How Agent Two charges credits](/credits-and-plans/how-credits-are-charged-when-using-ai-agents). For what is free, see [Credits and what they cost](/account/credits). For what credits pay for, see the how credits work FAQ page. ### Does invideo MCP use credits for AI generation? Source: https://docs.invideo.io/credits-and-plans/does-invideo-mcp-use-credits-for-ai-generation.md Generation through invideo MCP or the invideo CLI uses invideo credits. Edits and exports are free, and your agent prices each run first. Yes. Generation, transcripts and paid stock cost invideo credits, whether your agent works through invideo MCP or the invideo CLI. Edits and exports are free. Your agent runs a dry run first and tells you the price before it spends anything. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. See [Credits and what they cost](/account/credits). #### What determines the number of credits used? Each model has its own price. The settings of your request, such as the length and the resolution, change the price too. The agent sees the price before it runs anything. It calls `generate` with `dry_run: true`, or runs the CLI command with `--dry-run`. Then it runs the real call with `max_credits` set to that price. For plans and credit allowances, see the invideo pricing page. #### Do edits use credits? No. Edits on the invideo Editor timeline are free, whether you make them yourself or an outside agent makes them. You can arrange clips, adjust picture and sound, and refine your timeline without credits. For more, see [Is invideo Editor free and which actions use credits?](/credits-and-plans/is-invideo-editor-free-and-which-actions-use-credits) #### Do my chat app's plan requirements still apply? Yes. Your chat app runs on its own plan. Chat apps such as Claude on the web and the Gemini app connect through invideo MCP. ChatGPT uses the ChatGPT plugin. Terminal agents such as Claude Code and Codex use the invideo CLI. See [invideo for AI agents](/agents) for the supported clients and how each connects. For how credits work and the credit prices by model, see the how credits work, video model pricing, image pricing and audio pricing FAQ pages. ### invideo plans and credits: everything you need to know Source: https://docs.invideo.io/credits-and-plans/invideo-plans-and-credits-everything-you-need-to-know.md Compare invideo plans on the pricing page, and learn what uses credits, what is free, and when credits reset. Visit the invideo pricing page to compare plans, included credits, features and seats. You can choose monthly or annual billing. Check the details of a plan before you subscribe. *You are never locked in. You can switch plans at any point in your billing cycle. Upgrades are prorated, so you pay only the difference for the rest of the period.* #### Are there plans for teams? Yes. The pricing page shows the plans for your region, including plans for workspaces with several seats. Compare them there, and see the plan limits page for what each includes. #### What are invideo credits used for? Credits pay for generation, transcripts and paid stock: images, video, voice and music. Agent Two is invideo's own agent. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. An outside agent's own chat runs on that app's plan. For Agent Two's modes, charges and how to check usage, see [How Agent Two charges credits](/credits-and-plans/how-credits-are-charged-when-using-ai-agents). #### Are edits in invideo Editor free? Yes. **Edits on the invideo Editor timeline use no credits, whether you make them or an outside agent makes them.** You can trim, split and rearrange clips without a credit charge. Agent Two's work and AI media generation use credits. Each model has its own price. Video models charge per second, and the resolution, a video input and generated audio change the rate. Your agent runs a dry run first and tells you the price before it spends anything. See [Credits and what they cost](/account/credits). #### Does exporting or downloading use credits? No. Exporting or downloading content uses no credits. #### When do credits reset, and do unused credits roll over? Credits on an active plan reset every month. Unused plan credits do not roll over into the next month. Extra credits you buy expire after a set period, or when your plan ends, whichever comes first. #### What if I need more credits? You can buy extra credits without changing your plan or billing cycle. You can also upgrade on your **Subscription** page for more credits. Upgrades are prorated, so you pay the difference for the rest of your billing period. For the full answers, see the how credits work, plan limits and extra credits FAQ pages. ### Will my credits and iStock roll over into the next month or billing cycle? Source: https://docs.invideo.io/credits-and-plans/will-my-credits-and-istock-roll-over-into-the-next-month-or-billing-cycle.md Credits and iStock reset every month at the date and time your plan started. Anything unused is lost at that point. Credits and iStock reset every month, on the same date and at the same time your plan started. Anything unused is lost at that point. Resets follow UTC. If your plan ends, the credits left from it do not carry over. For when credits reset and what each plan includes, see the how credits work and plan limits FAQ pages. ### Why am I being asked to pay extra when I already have a subscription? Source: https://docs.invideo.io/credits-and-plans/why-am-i-being-asked-to-pay-extra-when-i-already-have-a-subscription.md A paywall while you create means your credits ran low. A payment at download means the video uses more iStock than your plan includes. #### When you create or edit a video A paywall while you create or edit a video usually means your account does not have enough credits. Each video you make with generative media uses credits, based on its length. If your credits are not enough to finish the video, a paywall offers to sell you more credits. You can pay, or close the pop-up and make the video with stock media instead. Generative media are made by AI. Stock media are ready-made files. For how credits are calculated, see [invideo plans and credits](/credits-and-plans/invideo-plans-and-credits-everything-you-need-to-know) and [Credits and what they cost](/account/credits). #### When you download a video If you are asked to pay when you download a video, the video likely uses more iStock than your plan includes. An active plan includes standard stock from Storyblocks, Shutterstock, Pexels and Pixabay, and a monthly allowance of iStock licenses. For top-ups and what each plan includes, see the extra credits and plan limits FAQ pages. ### Do prices vary by country, and can I pay in my local currency? Source: https://docs.invideo.io/credits-and-plans/do-prices-vary-by-country-and-can-i-pay-in-my-local-currency.md Plans and prices differ by region. The pricing page shows the plans for yours, and the pricing FAQ covers currency and payment. Plans and prices differ by region. The invideo pricing page shows the plans and prices for your region, in the currency it charges you in. If you buy through the mobile app, from the Apple App Store or the Google Play Store, the price can look different. Apple or Google set the price in the app and can add local taxes and store fees. For currency, payment methods, invoices and payment errors, see the payments, invoices and errors FAQ page. For what each plan includes, see the plan limits page. ### Where can I see the credits calculated for my video / media before creating it? Source: https://docs.invideo.io/credits-and-plans/where-can-i-see-the-credits-calculated-for-my-video-media-before-creating-it.md See the credit cost before you create, with Agent Two, in the video generator, or with your agent's dry run. The credit check works differently for Agent Two, for the video generator and for your agent. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. #### Using Agent Two Agent Two can ask before it generates and show you what it is about to make. To see how Agent Two charges credits, see [How Agent Two charges credits](/credits-and-plans/how-credits-are-charged-when-using-ai-agents). #### Using the video generator When you enter your prompt and click **generate a video**, you see the number of credits it takes from your balance. The video settings panel with the Generate button highlighted, showing the credit cost Open the dropdown and select **Learn more**. You see a detailed breakdown and a description of the model for the option you selected. The settings dropdown below the prompt box open, with the Learn more option highlighted #### Using your agent Your agent runs a dry run first and tells you the price before it spends anything. See [Credits and what they cost](/account/credits). For the credit prices by model, see the video model pricing, image pricing and audio pricing FAQ pages. ### Where can I check my current usage? Source: https://docs.invideo.io/credits-and-plans/where-can-i-check-my-current-usage.md See the credits, iStock and storage you used this month on the Usage page, and find where your credits went. To see the credits, iStock and storage you used this month, click your profile icon in the top right corner and open the **Usage** page. The top of the page shows your usage for the current month. The Usage page showing remaining credits, iStock and storage for the current month #### See where your credits went Click **You** in the left panel. It shows everything you made and downloaded on your account: 1. **Projects**: videos made with Agent Two. 2. **AI videos**: all videos generated on your account. 3. **Downloads**: videos you downloaded. The You section with the Projects, AI videos and Downloads rows highlighted This shows what your account made and where your credits went. For past projects and downloads, see [Where can I check my history?](/projects-and-exports/where-can-i-check-my-history). For where to see your remaining credits and what each plan includes, see the plan limits FAQ page. --- ### How can I cancel my subscription? Source: https://docs.invideo.io/billing/how-can-i-cancel-my-subscription.md Cancel an invideo plan on the website, iOS or Android, and what happens when the billing period ends. Cancel in the app store you paid through, or under **Subscriptions** in your profile menu if you paid on the website. Your plan stays active until the end of the billing period. #### For in-app purchases If you subscribed in the mobile app, cancel in the app store you paid through. **iOS** App Store: follow Apple's guide to canceling a subscription. **Android** Play Store: follow Google's guide to canceling a subscription. #### For website subscriptions To cancel your plan, click your profile in the top right corner and select **Subscriptions**. If you cancel, your plan stays active until the end of the current billing period. Then the paid features end, and invideo removes your card from the account. Click **Cancel** and follow the steps on the screen to finish the cancellation. See [Refunds and cancellation](/account/refunds). For how cancellation and renewals work, see the subscriptions and refunds FAQ page. ### I accidentally selected a yearly plan instead of monthly. What are my options? Source: https://docs.invideo.io/billing/i-accidentally-selected-a-yearly-plan-instead-of-monthly-what-are-my-options.md Check which billing cycle you're on, switch from yearly to monthly, and see when a refund may apply. When you select a plan on invideo, the checkout page shows the billing cycle (monthly or annual) and the total amount before you confirm payment. If you are not sure which one you selected, check your email receipt, or open **Subscriptions** in your profile menu to see your current billing cycle. The plans page with the Monthly and Annual billing toggle above the plan cards #### Switching from yearly to monthly You can switch from an annual plan to a monthly plan at any time from **Subscriptions** in your profile menu. The change takes effect at the end of your current billing cycle, not at once. You stay on your annual plan until it ends. After that, invideo bills you monthly. #### How to make the switch Make the switch from **Subscriptions** in your profile menu: 1. Click your profile icon and choose **Subscriptions**. 2. Select the monthly version of your plan. 3. Confirm the change. It takes effect at the end of your current billing cycle. #### What about a refund If you have not used the plan, you can ask for a refund within the refund window. See [Refunds and cancellation](/account/refunds) and [How to request a refund](/billing/refunds-how-to-request-one-and-what-s-covered). **A note on the annual discount.** Annual plans on invideo cost less than paying monthly. If you switch to monthly at the end of your cycle, you lose this discount and pay the standard monthly rate from then on. You can switch back to annual at any time. For how upgrades, downgrades and refunds work, see the subscriptions and refunds FAQ page. ### Refunds: how to request one and what's covered Source: https://docs.invideo.io/billing/refunds-how-to-request-one-and-what-s-covered.md When an invideo plan can be refunded, how to ask for a refund, and what to do if you paid through the App Store. invideo reviews each refund request on its own and decides at its own discretion. Read the refunds section of the terms and conditions too. #### What qualifies for a refund A refund is possible only within the refund window after the first purchase or a renewal, and only if you have not used the plan. The terms state the window. A plan counts as used if anything was generated or downloaded in the current billing period. A used plan cannot get a refund. You can **[cancel](/billing/how-can-i-cancel-my-subscription)** at any time, and the plan stays active until the end of the billing cycle. #### How to submit a request Email support@invideo.io with your account details and the reason for the request. invideo replies by email. invideo processes an approved refund at once. Your bank can take several business days to show it. If you paid through Google Play, start with support@invideo.io too. See [Refunds and cancellation](/account/refunds). **Subscribed through the Apple App Store?** Apple handles billing for iOS purchases, so you ask Apple for the refund, not invideo. See how to request a refund through Apple. For the refund rules, see the subscriptions and refunds FAQ page. ### How can I update my card details? Source: https://docs.invideo.io/billing/how-can-i-update-my-card-details.md Update the card on your invideo plan from **Subscriptions** in your profile menu, and your next bill goes to the new card. You update your card details under **Subscriptions** in your profile menu. 1. Click your profile picture in the top right corner, then **Subscriptions**. The profile menu in the top right corner with the Subscription option highlighted 2. Select **Update payment method** and enter your new card details. The Subscriptions page with the Payment method card and the Update payment method link highlighted Your next bill goes to your updated card. For payment methods, invoices and payment errors, see the payments, invoices and errors FAQ page. ### Is there a referral program or affiliate rewards? Source: https://docs.invideo.io/billing/is-there-a-referral-program-or-affiliate-rewards.md Join the invideo affiliate program, share your link, and earn a commission on the plans people buy through it. Yes. invideo runs an affiliate program through Impact.com. Sign up on the invideo affiliate page. After you sign up, you get a unique link to share with your audience. invideo tracks each person who signs up through your link as your referral, for the period the affiliate page states. You earn a commission on every monthly and annual plan bought through your link. The affiliate page has the commission rates and payment terms. #### Program overview The program works like this. **Earning commissions** - You earn a commission when someone buys a plan through your link. - You earn no commission for sign-ups that do not buy a plan. **Commission duration** - Commissions are for the first billing cycle only. - Monthly plan: the commission is for the first month. - Annual plan: the commission is for the first year. **Referrals** - You can refer as many customers as you like. **Payment schedule** - Transactions lock after a set period, and payments follow after the month they lock. The affiliate page states the days. **Payment method** - Payments go to the Impact account you used to sign up for the program. **Tracking** - Impact.com manages the program. - Your Impact dashboard shows every transaction. **Referral window** - A referral from a click counts for a set period, and sign-ups in that period count for you. - Paid subscriptions have no time limit on attribution. --- ### How to log in to my invideo AI account? Source: https://docs.invideo.io/account-and-workspaces/how-to-log-in-to-my-invideo-ai-account.md Sign in to invideo with Google, Apple or your email address. Email sign-in uses a short code instead of a password. First, create an account at invideo.io. To sign in, select **Join with Google** if you registered with Google, or **Join with Apple** if you registered with Apple. The Welcome to invideo AI sign-in page with Join with Google, Join with Apple and the Email field highlighted You can also enter your email address. invideo then sends a short code to your email. Use this code to finish signing in. The invideo AI email with a six-digit login code Enter the code in the field on the sign-in page. The sign-in page with the Paste login code here field highlighted above the Login button invideo does not use passwords. Enter your email address, and invideo sends you a code to open your account. #### What if I don't receive the code? Automated emails can land in spam, or some email domains do not deliver them. If the code still does not arrive, you can: 1. Change the email address. 2. Contact support from the chat button on the invideo site, or email support@invideo.io. See [Sign in, device codes and sessions](/account/sign-in) for how your agent signs in. ### How can I change my email? Source: https://docs.invideo.io/account-and-workspaces/how-can-i-change-my-email.md Ask invideo to change the email on your account with the email change form. To change your email, fill out the email change form. invideo reviews the form and updates your email. If invideo needs more information, it contacts you by email. If the new email is linked to another account, invideo deletes that account first. ### How can I delete my workspace? Source: https://docs.invideo.io/account-and-workspaces/how-can-i-delete-my-workspace.md Delete your workspace and account from Settings, and what to do if the deletion doesn't go through. Delete your workspace with these steps: 1. Click **Settings** in the menu. The profile menu in the top right corner with the Settings option highlighted 2. Select **Manage account**, then **Delete workspace**, then **Delete account**. The Manage account page with the Delete workspace confirmation dialog open When the account is deleted, invideo signs you out. If something goes wrong, fill out the account deletion form. invideo deletes the account and emails you if it needs more information. See [Security and data](/account/security-and-data) for what happens to your projects and files. ### How to delete my account on iOS device? Source: https://docs.invideo.io/account-and-workspaces/how-to-delete-my-account-on-ios-device.md Delete your invideo workspace and then your account from the invideo app on your iOS device. The video shows how to delete the workspace and then the account in the invideo app on an iPhone. The steps below say the same. Delete your workspace first, then your account, in the invideo app. 1. Sign in to the app on your iOS device. The app opens the page where you can generate videos. 2. Tap the arrow next to the logo in the top left corner. The invideo app home screen on a phone with the back arrow and logo in the top left corner highlighted 3. Open the **Account** tab in the bottom bar, then **Members**. The app's bottom bar with the Account tab highlighted 4. On the **Members** page, delete your workspace. The Account screen in the app with the Members option highlighted under Workspace The Members page in the app showing the workspace owner and the Delete Workspace button 5. Delete your account. The Account tab in the app with the Delete Account option highlighted You can delete the workspace and the account only when no plan is active. See [Security and data](/account/security-and-data). ### How to delete my account on Android device? Source: https://docs.invideo.io/account-and-workspaces/how-to-delete-my-account-on-android-device.md Delete your invideo workspace and then your account from the invideo app on your Android device. Delete your workspace first, then your account, in the invideo app. 1. Sign in to the app on your Android device. The app opens the page where you can generate videos. 2. Tap the arrow next to the logo in the top left corner. The invideo app home screen on a phone with the back arrow and logo in the top left corner highlighted 3. Open the **Account** tab in the bottom bar, then **Members**. The app's bottom bar with the Account tab highlighted 4. On the **Members** page, delete your workspace. The Account screen in the app with the Members option highlighted under Workspace The Members page in the app showing the workspace owner and the Delete Workspace button 5. Delete your account. The Account tab in the app with the Delete Account option highlighted You can delete the workspace and the account only when no plan is active. See [Security and data](/account/security-and-data). ### How to add members to my workspace? Source: https://docs.invideo.io/account-and-workspaces/how-to-add-team-members.md Workspace members work together in the same workspace, each with their own seat and monthly credits. Workspace members work together in the same workspace. Each member has their own seat and monthly credits. #### How to add seats Add seats from your profile menu: 1. Click your picture in the top right corner and choose **Subscriptions**. 2. Set the number of seats you need on your plan. 3. Confirm. Each seat comes with its own monthly credits. When your seats are added, invite people from your workspace settings. Select **Members** in your profile menu. The plans panel with the seat picker and the member limit on each plan card #### Which plans support multiple seats? How many seats you can add depends on your plan. The pricing page shows the seats and credits per seat for each plan. For custom seats and credits, see the custom plans page. **Good to know.** Upgrades are prorated. You pay only the difference for the rest of your billing cycle. See [Seats and workspaces](/account/seats) for how seats and members work. ### How to switch between workspaces? Source: https://docs.invideo.io/account-and-workspaces/how-to-switch-between-workspaces.md Switch to another person's workspace from the profile menu to create videos together. If you added someone to your workspace, or a colleague added you to theirs, switch workspaces to create videos together. #### How to switch Switch from the profile menu: 1. Click the profile icon in the top right corner. 2. Select the other workspace from the dropdown menu. You can now work together and create videos. One account can belong to several workspaces. Each workspace has its own plan. To bring people into your workspace, add seats and invite them. See [Seats and workspaces](/account/seats). ### How can I change my workspace name? Source: https://docs.invideo.io/account-and-workspaces/how-can-i-change-my-workspace-name.md Change your workspace name in Settings. The name shows when you share a video. To change your workspace name, open the drop-down menu in the top right corner and go to **Settings**. Then update the name in the **Workspace settings** section. The workspace name shows when you share a video. See [Seats and workspaces](/account/seats). A shared video page with the workspace name in the line 'Made with invideo AI by The invideo zone' --- ### How can I download the video to my computer? Source: https://docs.invideo.io/projects-and-exports/how-can-i-download-the-video-to-my-computer.md Find your exported videos in the You section and download them to your device. Open the **You** section and download the video from its page. 1. Click **You** in the left-hand panel. Your exported videos are there. The left-hand panel with an arrow pointing at the You section 2. Select the video you want to download. 3. Click **Download** on the next page. The video saves to your device. The Downloads section of the You page showing an exported video ### How can I edit my previously downloaded video? Source: https://docs.invideo.io/projects-and-exports/how-can-i-edit-my-previously-downloaded-video.md Open an exported video from the You section and click Edit to keep working on it. Open the video from the **You** section and click **Edit**. invideo opens the project, and you keep editing on its timeline. 1. Click **You** in the left-hand panel. Your exported videos are there. The left-hand panel with an arrow pointing at the You section 2. Select the video you want to edit. 3. Click **Edit** at the top right of the next page. An exported video page with the project name and its Edit button highlighted ### Where can I check my history? Source: https://docs.invideo.io/projects-and-exports/where-can-i-check-my-history.md Find your projects from the logo menu in the top left corner. Your projects are in the project list, and your exported videos are in the **You** section. 1. Select the logo in the top left corner. 2. Select **Show all**. invideo lists your projects. The left-hand panel with Recent Projects and History, and the Show all link under History highlighted 3. For your exported videos, click **You** in the left-hand panel. To see the credits you used, read [Where can I check my current usage?](/credits-and-plans/where-can-i-check-my-current-usage) ### How do I delete my exported projects? Source: https://docs.invideo.io/projects-and-exports/how-to-delete-my-exported-projects.md Delete one or several exported videos at once from the Downloads section under You. Delete exported videos from the **Downloads** section of **You**. You can delete one video or several at once. 1. Click **You** in the left-hand panel. The left-hand panel with an arrow pointing at the You section 2. Scroll down to the **Downloads** section and click **See all**. 3. Click **Edit** to turn on selection mode. 4. Select the videos you want to delete. Pick them one by one, or click **Select all**. The Downloads page in selection mode with Select All and Done at the top and the Delete button at the bottom 5. Click **Delete**. invideo deletes the selected videos. ### How do I delete my draft projects? Source: https://docs.invideo.io/projects-and-exports/how-do-i-delete-my-draft-projects.md Find your draft projects in your project list and delete the ones you no longer need. Delete a draft from your project list with its trash can icon. 1. Select the logo in the top left corner, then select **Show all** to see your projects. 2. Click the trash can icon next to the project and select **Delete**. The project list with an arrow pointing at the trash can icon next to a project 3. Confirm the deletion. invideo deletes the project permanently. The confirmation dialog asking if you want to delete the session, with Cancel and Delete buttons ### How can I make my shared video public or private? Source: https://docs.invideo.io/projects-and-exports/how-can-i-make-my-shared-video-public-or-private.md Only your workspace sees your project. Set an export page to public, shared or private when you share it. Set the visibility of the export page. Only your workspace can see your project. Nobody outside it sees a video until you share an export page. The visibility has three values: - **Public** (`public`): anyone with the page URL can watch the page. - **Shared** (`shared`): members of your workspace can watch the page. - **Private** (`private`): only you can see the page. To change it, use one of these places: 1. Open your exported video and use the visibility dropdown in the panel on the right. The visibility dropdown beside an exported video, open on the visibility options 2. Or click **Share** to open the sharing panel. An exported video page with an arrow pointing at the Share button next to Download 3. In the sharing panel, choose a value from the **Permissions** dropdown. The Share dialog with the Permissions dropdown open on the visibility options A new export page starts as private. Your agent sets the visibility with `share_export_page`, or in a terminal with `invideo export share` and `--visibility`. The agent asks you before it makes a page public. See [Security and data](/account/security-and-data). Your workspace settings also have a **Default export visibility** dropdown. Workspace settings with the Default export visibility dropdown open on the visibility options ### What does export visibility mean? Source: https://docs.invideo.io/projects-and-exports/what-does-export-visibility-mean.md Only your workspace sees your project. Choose public, shared or private when you share an export page. Export visibility sets who can watch an export page. Only your workspace can see your project. Nobody outside it sees a video until you share an export page. The visibility has three values: - **Public** (`public`): anyone with the page URL can watch the page. - **Shared** (`shared`): members of your workspace can watch the page. - **Private** (`private`): only you can see the page. A new export page starts as private. You choose who sees it when you share it. To see the default for your workspace, follow these steps: 1. Open the profile menu in the top right corner and select **Settings**. The profile menu in the top right corner with the Settings option highlighted 2. Find the **Default export visibility** dropdown and choose a value. The Default export visibility dropdown in Settings, open on the visibility options You can also change the visibility of one video from the panel on the right of the exported video, or from the sharing panel with the **Share** option. The visibility dropdown beside an exported video, set to Public, with the other options below The Share dialog with the Permissions dropdown set to Public, with the other options below Your agent sets the same values with `share_export_page`, or in a terminal with `invideo export share` and `--visibility`. The agent asks you before it makes a page public. See [Security and data](/account/security-and-data). ### How to find and reopen a saved timeline in invideo Editor Source: https://docs.invideo.io/projects-and-exports/how-to-find-and-reopen-a-saved-timeline-in-invideo-editor.md Find a previously created timeline in your projects and reopen it in invideo Editor to continue editing. Your timeline is saved in its project. Reopen it from the chat of the agent you worked with. 1. From the homepage, go to **Projects** and open the project you were working on. 2. On the **Notebook page** on the right, select the agent you were working with. 3. Open that agent's chat. Your timeline is there under **Timeline**, and you pick up where you left off. ### How to share a timeline for review in invideo Editor Source: https://docs.invideo.io/projects-and-exports/how-to-share-a-timeline-for-review-in-invideo-editor.md Share the project with a reviewer as preview only from the Share button, collect comments by timecode, and keep the rest of the project hidden. Share the project with your reviewer as **Preview only**. The reviewer sees the preview tab and the timeline previews, and can comment. Every other tab stays hidden. You do not need to export to Premiere Pro or DaVinci Resolve to get feedback from a client or a colleague. #### Share with a reviewer 1. Open the project and click **Share**. One share modal opens. It always shares the project. 2. Type the reviewer's email. Choose how to add them: **Connect** gives access to this one project and uses no seat. **Add to workspace** gives a guest seat and access to every open project in the workspace. 3. Set the role to **Preview only**. 4. Open the preview tab and click **Copy link**. The link opens the preview the reviewer should watch first. They can switch to the other exports in the project. 5. Send the link. The reviewer signs in to invideo, watches in the browser, and comments by timecode. Commenting always needs an invideo login. #### Share a link without adding people Under **General access** in the share modal, pick who can open the link. | Option | Who can open the link | | --- | --- | | **Your workspace** (default) | Members of your workspace. Others see a request-access page. | | **Anyone with the link** | Anyone signed in to invideo. They can view, comment and fork. | | **Restricted** (Enterprise) | Only people invited to the project. No link sharing. | When someone opens a link they cannot access, they request access. You get a notification that opens the share modal, where you add them to the workspace or connect them to the project. #### Send a finished result instead To hand over a result rather than the project, export the timeline from the **Notebook**. A new export page is private. Set it to anyone with the link before you send its URL. See [Export a video, audio or a PNG still from invideo Editor](/projects-and-exports/how-to-export-video-audio-or-a-png-still-from-invideo-editor). No MCP tool or CLI command shares a project. Your agent can set an export page's access with `share_export_page`; it cannot add a person to a project. You do that in the share modal. #### Related - [Seats and workspaces](/account/seats), for guest seats, connects and roles - [Security and data](/account/security-and-data) ### How to export video, audio or a PNG still from invideo Editor Source: https://docs.invideo.io/projects-and-exports/how-to-export-video-audio-or-a-png-still-from-invideo-editor.md Export your timeline as an MP4 video, an audio file or a PNG image of the frame at the playhead. Open **Export** in invideo Editor and choose the output you need. Use **H.264 · MP4** for a finished video, **Audio only** for sound, **Still frame** for a PNG image, or **Editable project** for a project file. #### Export an MP4 video 1. Open your timeline and select **Export** in the top toolbar. The Export Settings dialog with MP4 selected and Range, Format, Resolution and Loudness target options 2. Choose **H.264 · MP4**. 3. Check **Range**, **Resolution**, **Frame rate** and **Quality**. Review **Loudness target** for your delivery needs. 4. Check the summary and select **Export**. #### Export an audio file 1. Choose **Audio only** in the Export window. 2. Check **Range** and select the available **Format** you need. The listed audio formats are WAV, AAC and Opus. 3. Review **Loudness target**, then select **Export**. #### Export a PNG still 1. Move the playhead to the frame you want to save and check it in the Monitor. 2. Open **Export** and choose **Still frame**. 3. Choose **Resolution** and check **Frame** to confirm the playhead position. 4. Select **Export**. After exporting, open the file and check the picture or sound. Choose settings for your destination. An example's resolution, frame rate or loudness target is not a universal requirement. #### Export an editable project An editable project lets you keep working in another editing app. 1. Choose **Editable project** in the Export window. 2. For Premiere Pro or Final Cut Pro, export an editable project. For DaVinci Resolve, export with **OpenTimelineIO**. 3. Open the project in the other app and check the imported timeline before you continue your edit. Your agent makes the same file with `export` and `format`. It makes a project file for Premiere Pro, DaVinci Resolve or Final Cut Pro, with a `format` of `premiere`, `davinci` or `final_cut`. The agent reads the export card again until the files list is present, then gives you the files. See [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut). #### Share your timeline for review To collect feedback, follow [How to share a timeline for review](/projects-and-exports/how-to-share-a-timeline-for-review-in-invideo-editor). When access is set to **Anyone with the link** (`public`), viewers can watch without an account. Reviewers need an invideo account to leave comments. --- ### How to use the timeline in invideo Editor Source: https://docs.invideo.io/editor/how-to-use-the-timeline-in-invideo-editor.md Learn how to navigate invideo Editor timeline, work with video and audio tracks, preview clips and find editing controls. The timeline in invideo Editor is where you arrange video, images and audio into a finished cut. Use tracks to organize picture and sound, the playhead to choose the moment you are viewing, and the Monitor to preview your edit. Edit by hand, or ask an agent, such as Agent Two or your own agent, to work on the same timeline. The invideo Editor timeline with video tracks V1 to V4, audio tracks A1 to A3 and Agent Two editing #### Understand the timeline and panels | **Panel or control** | **What it does** | | --- | --- | | Media | Holds the video, images and audio available for your edit. | | Timeline | Shows when clips start, how long they last and how they fit together. | | Video tracks such as V1 and V2 | Organize the visual layers in your sequence. | | Audio tracks such as A1 and A2 | Organize dialogue, music and other sound. | | Playhead and time ruler | Identify the moment you are reviewing. | | Monitor | Displays the picture at the playhead position. | | Inspector | Shows settings for the selected clip or timeline. | #### Make your first timeline edit 1. Open a timeline and select **Edit** at the top of invideo Editor. 2. Open **Media**, upload your files and drag the media you want to use onto the timeline. 3. Arrange your clips in the order you want them to play. Keep dialogue, music and sound effects organized across audio tracks. 4. Move the playhead along the time ruler and preview the sequence in the **Monitor**. Zoom into the timeline when you need to inspect a cut more closely. Zoom changes your view, not the video's duration. 5. Select a clip to inspect its settings. Use **Audio** to adjust the sound balance and **Color** to adjust the image. 6. Play through the cut, check the joins between clips and open **Export** when you are ready to create a file. #### Find a missing panel Open the layout menu beside the workspace controls and choose **Panels**. Enable the panel you need, such as Timeline, Media or Inspector. The menu also includes **Reset to Saved Layout** for returning to a saved panel arrangement. The layout menu open on Panels, listing Inspector, Media, Timelines and others, with Reset to Saved Layout #### Work with agents The agent chat on the left of the editor, with the Source monitor and Media panel on the right Open the agent panel and ask Agent Two for an editing task, then review the changes on your timeline. You can continue adjusting the clips yourself. Edits and exports are free. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. See [Credits](/account/credits). ### How to edit clips in invideo timeline Source: https://docs.invideo.io/editor/how-to-edit-clips-in-invideo-timeline.md Trim clip boundaries, split a clip into sections and rearrange footage in invideo Editor. Trim a clip to change its start or end, split it to make separately editable sections, or move it to change when it appears in your video. These are manual timeline edits in invideo Editor. #### Trim the beginning or end 1. Select the clip. Zoom in until its boundaries are easy to see. 2. Drag its beginning or end inward to remove material from that edge. 3. Preview the boundary and the neighboring clip to check the timing. #### Split a clip into sections 1. Select the clip you want to divide. 2. Position the playhead at the intended cut. 3. Select the **Blade Edit tool**, then click the clip at the playhead to split it into two sections. The Blade Edit tool selected in the toolbar, splitting a clip on V1 at the playhead 4. Select the resulting sections separately to continue editing. To isolate a section in the middle, split at its beginning and end. #### Rearrange clips 1. Drag the clip to the intended time position on the appropriate track. 2. Check the nearby clips for gaps, overlaps or an unintended change in order. 3. Play across the joins and listen for changes in the sound. When moving footage with linked audio, check that both parts remain in sync. If a clip does not move, inspect the track's lock control. Review one change at a time so you can identify what altered the sequence. ### How to upload and organise media in invideo Editor Source: https://docs.invideo.io/editor/how-to-upload-and-organise-media-in-invideo-editor.md Upload video, images and audio to invideo Editor, organize them into folders and add them to your timeline. Upload your footage, images and audio in the **Media** panel, then group them in folders. #### Uploading your media 1. Open the **Media** panel in invideo Editor. 2. Click upload, or drag your files into the panel. 3. Drag your media from the panel onto the timeline. Bring in everything from your shoot and work through it in one place. Storage depends on your plan. See [Plans](/account/plans). #### Creating folders to stay organized For bigger projects, folders keep your media tidy. Create a folder in the Media panel and group your clips by scene, by camera or by type. This matters most for **multicam** work: upload each camera angle to its own folder, then tell your agent which camera has the best audio and ask it to line the angles up by their sound. The agent places each angle on its own track. #### Supported media You can upload video, image and audio files. You can also generate shots, voiceovers or music in the project with the leading video, image, voice and music models. The result lands in your project, and you or the agent place it on the timeline next to your own footage. ### How do I switch between Simple and Professional layouts in invideo Editor? Source: https://docs.invideo.io/editor/how-do-i-switch-between-simple-and-professional-layouts-in-invideo-editor.md Change the editor’s interface layout from Settings. Choose **Simple** or **Professional** from the **Layout** setting. 1. Open **Settings** at the top right of the editor. 2. Open the **Layout** dropdown and select **Simple** or **Professional**. The Layout dropdown in Settings open on the Professional and Simple options Return to this setting to switch layouts again. ### How do I change the interface mode in invideo Editor? Source: https://docs.invideo.io/editor/how-do-i-change-the-interface-mode-in-invideo-editor.md Choose between Auto, Mobile and Desktop interface modes. The **UI Mode** setting lets you choose between Auto, Mobile and Desktop. 1. Open **Settings** at the top right of the editor. 2. Under **Interface**, open the **UI Mode** dropdown. 3. Select **Auto**, **Mobile** or **Desktop**. The Interface settings with the UI Mode dropdown open on Auto, Mobile and Desktop It is separate from **Layout**, which provides the Simple and Professional options. ### How do I duplicate a clip on the timeline? Source: https://docs.invideo.io/editor/how-do-i-duplicate-a-clip-on-the-timeline.md Create another copy of a clip using its right-click menu. Duplicate a clip when you want to reuse it in another part of your edit or place a copy on another track. 1. Right-click the clip you want to copy. 2. Select **Duplicate**. 3. Locate the duplicated clip and move it to the position you want. The clip right-click menu on the timeline with the Duplicate option highlighted Preview the affected section to check the copy’s timing and any overlap with other clips. ### How do I show protected tracks that are hidden from the timeline? Source: https://docs.invideo.io/editor/how-do-i-show-protected-tracks-that-are-hidden-from-the-timeline.md Check the protected-track visibility setting. Clear the **Hide protected tracks** setting. When it is on, protected tracks do not show on the timeline. 1. Open **Settings** at the top right of the editor. 2. Find the **Timeline** section. 3. Clear the **Hide protected tracks** checkbox. The Timeline section of Settings with the Hide protected tracks checkbox selected The protected tracks show on the timeline again. ### How do I show a clip’s keyframes on the timeline? Source: https://docs.invideo.io/editor/how-do-i-show-a-clip-s-keyframes-on-the-timeline.md Display the keyframes for the property you want to inspect. Right-click the clip and open **Show Clip Keyframes**. The timeline then shows how its opacity, position or another animated property changes over time. 1. Right-click the clip on the timeline. 2. Open **Show Clip Keyframes**. 3. Select the property whose keyframes you want to display. The clip right-click menu with Show Clip Keyframes open on a list of properties, Opacity checked The available properties include **Opacity**, **Position X**, **Position Y**, **Zoom X**, **Zoom Y**, **Anchor X**, **Anchor Y** and **Rotation**. For example, select **Opacity** to inspect the keyframes controlling the clip’s visibility. ### How do I create a slow zoom or pan with keyframes in invideo Editor? Source: https://docs.invideo.io/editor/how-do-i-create-a-slow-zoom-or-pan-with-keyframes-in-invideo-editor.md Animate a clip’s zoom and position between two moments on the timeline. Set a keyframe for the framing at the start of the move and another at the end. For a slow zoom, set the initial zoom, then a larger zoom later in the clip. For a pan, change position between the two keyframes. The Keyframe panel showing opacity, zoom and anchor keyframes on a clip's timeline The Inspector Transform section with keyframe buttons next to Zoom, Position and Anchor Point The time between the keyframes controls how long the move takes. Preview the full move and adjust the framing so the subject stays where you want it. Use Bezier easing to change how the movement begins and settles. These are manual adjustments to the existing clip in invideo Editor. Your agent makes the same move with `add_keyframe_lane` on `zoom_x` and `zoom_y` (or `position_x` for a pan), then `add_keyframes`, or with the `dynamic_zoom` effect. ### How do I make a keyframed move start and stop more smoothly? Source: https://docs.invideo.io/editor/how-do-i-make-a-keyframed-move-start-and-stop-more-smoothly.md Use Bezier easing to control acceleration and deceleration in your animation. Adjust the easing between keyframes in invideo Editor. A linear move changes at a constant rate. An eased move can begin gently, accelerate and settle into its final position. Custom Bezier curves let you shape that change. First establish the right start and end positions, then refine how the animation travels between them. Watch the move in the sequence, especially where it follows a cut or accompanies a musical accent. Keep the motion easy to follow when animating titles or product details. ### How do I fade a visual layer in or out with opacity keyframes? Source: https://docs.invideo.io/editor/how-do-i-fade-a-visual-layer-in-or-out-with-opacity-keyframes.md Change a clip’s visibility over time while keeping the fade adjustable. Animate the clip’s opacity in invideo Editor. For a fade in, begin with an opacity keyframe at zero, then add a later keyframe at the visibility you want. Reverse that progression for a fade out. The Keyframe panel in curve view showing the opacity value of a clip changing over time Move the keyframes farther apart for a longer fade or closer together for a shorter one. Preview the layer together with the footage underneath it, because the result depends on both layers. Check that a title or graphic stays fully visible long enough to read before it fades away. ### How can I use timeline markers to plan an edit or revision pass? Source: https://docs.invideo.io/editor/how-can-i-use-timeline-markers-to-plan-an-edit-or-revision-pass.md Mark important moments so you can return to them while refining the cut. Use markers in invideo Editor to identify moments you want to revisit, such as a product reveal, a change of scene or an edit that needs attention. Markers give you reference points while you refine the sequence. For a structured review, watch the edit once and mark the moments that need work, then return to them for a focused pass. Give clear timestamps when you brief your agent about those changes. A marker identifies a point in the timeline. It does not make the edit for you. ### What does snapping help with when I move clips on the timeline? Source: https://docs.invideo.io/editor/what-does-snapping-help-with-when-i-move-clips-on-the-timeline.md Use alignment assistance to place clips more precisely. Snapping helps align clips with timeline reference points as you position them in invideo Editor. It is useful when you want adjoining clips to meet cleanly instead of leaving a small accidental gap. Clips with opacity curves on the timeline being moved so their edges snap together After positioning a clip, zoom in and check the join. Listen across the edit as well as watching it. Correct visual alignment does not by itself guarantee a smooth audio transition. Check linked audio too whenever you reposition footage. ### Can I animate the crop of a clip over time? Source: https://docs.invideo.io/editor/can-i-animate-the-crop-of-a-clip-over-time.md Change the visible area of a clip with crop keyframes. Yes. In invideo Editor, crop is the **Crop** effect (`crop`). Keyframe its left, top, right and bottom settings. Set the crop at one moment, then change it at a later moment to reveal or conceal more of the image over time. Your agent does the same with `add_effect` for `crop`, then `create_effect_keyframe_lane` on one setting, such as `left`, and `add_keyframe` for each point. Use crop to control the visible area. Use position or zoom to change where the image sits and how large it appears. Review the entire motion so important details remain visible. For a reveal over another shot, check the relationship between the cropped layer and the footage beneath it. ### How do I make a video effect change gradually during a shot? Source: https://docs.invideo.io/editor/how-do-i-make-a-video-effect-change-gradually-during-a-shot.md Keyframe an effect parameter to build or reduce a treatment over time. Use keyframes on the effect parameter you want to change in invideo Editor. Set an initial value at one moment and a different value later in the clip, then preview how the treatment changes between them. For example, a treatment can build toward a reveal and become subtler afterward. The available controls depend on the effect. Check the full shot for abrupt changes and adjust the keyframe timing or easing. Keep the effect’s purpose clear so its movement supports the footage. ### How to mix audio and adjust color in invideo Editor Source: https://docs.invideo.io/editor/how-to-mix-audio-and-adjust-color-in-invideo-editor.md Balance dialogue and music in the Audio workspace, then adjust your shots in the Color workspace. Use the **Audio** workspace in invideo Editor to balance sound across your timeline. Use **Color** to adjust the appearance of your shots. Both workspaces let you refine the same edit without moving to another application. #### Mix audio The audio timeline above the Audio Track Mixer, with faders for Voiceover, Music, SFX, Ambience and two buses 1. Open a timeline containing sound and select **Audio** at the top. 2. Find your audio tracks, such as **A1**, **A2** and **A3**, and their corresponding controls in the **Audio Track Mixer**. 3. Play a section containing dialogue and music. Identify which tracks carry each part of the mix. 4. Adjust the relevant faders while listening. Keep speech understandable and bring the other sounds into balance around it. 5. Use a track's solo control to listen to it alone, or mute to silence it. Return to the full mix to check the result. 6. Listen across the whole sequence before exporting. If you cannot hear a track, check that it has audio at the playhead. Check its mute and solo settings and its fader level. Also check your device's playback output and volume. #### Adjust color The Color Grading panel with Correction sliders such as Brightness, Contrast and Saturation, and color wheels 1. Select **Color** at the top and choose the shot you want to adjust. 2. Review the shot in the **Monitor** and open **Basic Correction** in the **Color Grading** panel. 3. Make a small adjustment to the relevant control, such as brightness, contrast or exposure. 4. Use **Temperature and Tint** when the shot's color balance needs attention. 5. Compare the shot with its neighbors and review the transition in playback. The workspace also includes **Color Wheels**, **Tone Curve** and **Scopes** for more detailed adjustments. Change one control at a time so you can see its effect. The same slider values on different shots do not always make them look alike. The track faders control the balance of your mix. The export loudness target sets the level of the delivered audio. Edits and exports are free. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. See [Credits](/account/credits). ### Can I import a custom LUT into invideo Editor? Source: https://docs.invideo.io/editor/can-i-import-a-custom-lut-into-invideo-editor.md Bring an existing color look into the project and adjust its strength. Yes. invideo Editor imports .cube and PNG LUTs. The **Color** workspace has an **Add LUT** button and a strength control. Your agent brings the .cube or PNG file in with `add_media`, then applies it with `apply_lut` and sets `strength` from 0 to 1. The Color Grading panel with the LUT section open and an arrow pointing at the Add LUT button After importing a LUT, check it on your footage and combine it with other color corrections as needed. Confirm the LUT is intended for the material you are grading. ### How do I adjust one colour range without changing the whole image? Source: https://docs.invideo.io/editor/how-do-i-adjust-one-colour-range-without-changing-the-whole-image.md Use a color qualifier for a targeted correction in invideo Editor. Use hue, saturation and luminance qualifiers to select the color range you want to adjust. Refine the selected range, then review the result across the shot. The Qualifier section of the Color panel with Hue, Saturation and Luminance range sliders and Pick color Other areas containing the same color may also be selected. Check neighboring objects and moving subjects before finishing the correction. ### How can the waveform scope help me judge exposure? Source: https://docs.invideo.io/editor/how-can-the-waveform-scope-help-me-judge-exposure.md Check brightness levels alongside the picture while refining a grade. The waveform scope in invideo Editor shows the distribution of image brightness. Use it alongside the Monitor to understand how shadows, mid-tones and highlights change as you adjust the shot. Compare similar shots for sudden differences in brightness, then check whether those differences fit the scene. Keep watching the picture as well as the scope. A deliberately dark scene does not need to resemble a bright exterior. A scope helps you judge the signal. It does not choose the creative look for you. ### How do I reuse a colour grade across several shots? Source: https://docs.invideo.io/editor/how-do-i-reuse-a-colour-grade-across-several-shots.md Carry a starting look between clips and refine it for each shot. In the **Color** workspace, copy the grade from one clip and paste it onto another. Your agent does the same with `paste_attributes` and the `effects` attribute. Review each shot afterward. Differences in exposure, lighting and color can require individual adjustments even when the same grade is applied. ### Which audio effects are available in invideo Editor? Source: https://docs.invideo.io/editor/which-audio-effects-are-available-in-invideo-editor.md Find the audio effects in Effects and choose the one that fits the problem. Open **Effects** and select **Audio** to see the audio effects in invideo Editor. The list has **Click Remover** (`click_remover`), **Compressor** (`compressor`), **De-Esser** (`de_esser`), **Ducker** (`ducker`), **Limiter** (`limiter`), **Parametric EQ 8** (`eq`), **Pitch** (`pitch_shift`), **Plate Reverb** (`plate_reverb`), **Verb One** (`voice_reverb`) and **Voice EQ** (`voice_eq`). Your agent adds one with `add_audio_effect`. The Add effect menu listing the audio effects, including Click Remover, Compressor, De-Esser and Pitch These processors work on sound already in your edit. They are separate from asking an agent to find or generate a sound effect, such as footsteps or an impact. Identify whether you need repair, level control, tonal adjustment or a creative treatment before choosing a processor. Listen in the full mix after making a change. ### How do I make audio waveforms easier to see? Source: https://docs.invideo.io/editor/how-do-i-make-audio-waveforms-easier-to-see.md Adjust waveform visibility and appearance in Settings. Change the opacity, style and scale of the waveforms in the **Audio waveform** settings. 1. Open **Settings** at the top right of the editor. 2. Find the **Audio waveform** section. 3. Increase **Opacity** if the waveforms are too faint. 4. Choose a **Style**: **RMS**, **Outline** or **Peaks**. 5. Choose a **Channels** display: **Loudest**, **Average** or **Stereo**. 6. Select a **Linear** or **Logarithmic** scale. The Audio waveform settings with Style, Channels, Scale and Opacity controls The **Noise floor** setting applies only to the logarithmic scale. Waveform opacity applies to the timeline, source monitor and media browser. In the Audio view, each channel always has its own lane. ### How do I display audio output levels and the loudness meter? Source: https://docs.invideo.io/editor/how-do-i-display-audio-output-levels-and-the-loudness-meter.md Turn on audio output levels and the loudness meter (LU) in invideo Editor settings to monitor the sound in your edit. Audio output levels and the loudness meter help you monitor the sound in your edit. 1. Open **Settings** at the top right of the editor. 2. Under **Panels**, enable **Audio output levels** to display output levels. 3. Under **Audio waveform**, enable **Loudness meter (LU)** to display the loudness meter. The Audio waveform settings in the editor with the Loudness meter (LU) checkbox highlighted Each display has its own setting, so you can enable them separately. ### Why should I route related audio tracks through a bus? Source: https://docs.invideo.io/editor/why-should-i-route-related-audio-tracks-through-a-bus.md Control a group of sounds together while retaining their individual track balance. A bus brings related audio tracks together so you can manage their combined output. invideo Editor’s audio mixer supports tracks and buses, allowing voice, music and effects to be organized within the mix. The audio mixer with faders for tracks A2 to A6, the timeline and the MAIN bus The MAIN bus panel open on the Effects tab, with Verb One and Compressor applied Use individual tracks to balance elements within a group, then use the group’s bus when you want to change them together. For example, several ambience tracks may need their internal balance preserved while the whole atmosphere becomes quieter. Check the bus and overall mix levels as you work. ### Can I change the pitch of a sound in invideo Editor? Source: https://docs.invideo.io/editor/can-i-change-the-pitch-of-a-sound-in-invideo-editor.md Use the Pitch effect for a tonal or creative change to an audio element. Yes. invideo Editor has the **Pitch** effect (`pitch_shift`). Open **Effects**, then **Audio**, and add **Pitch** to the sound. Pitch changes how high or low a sound is, which gives an effect a different character or makes a deliberately stylized sound. Your agent adds the same effect with `add_audio_effect` and `pitch_shift`. The Pitch effect controls with Semitones and Cents sliders, both set to 0 Review the result alongside the picture and the rest of the mix. Check intelligibility when working with speech and listen for unwanted artifacts. Start with a small adjustment if you want the sound to remain close to the original. ### How do I try an alternative cut without losing the cut I like? Source: https://docs.invideo.io/editor/how-do-i-try-an-alternative-cut-without-losing-the-version-i-like.md Use a timeline branch to explore another creative direction. Make a branch in invideo Editor. A branch is another direction for the timeline. Test a different opening, pace or treatment on it, and the cut you like stays on its own branch. The branch button in the editor toolbar open on the Switch branches/tags menu, listing main and Branch 1 The branches overview showing main, Branch 1 and a third branch splitting from an export checkpoint Define what you want to compare before changing the branch, such as a shorter introduction or a different visual treatment. Review the alternatives against the same brief, then decide which branch you want to keep working on. ### What is the difference between a branch, a tag and history? Source: https://docs.invideo.io/editor/what-is-the-difference-between-a-branch-a-version-tag-and-history.md Choose a branch, a checkpoint or a tag to match the change you want to make. A branch is another direction for a timeline. A checkpoint saves the state of a branch at one moment. A tag is a name on a checkpoint, such as the cut you sent for review. History is the list of checkpoints on a branch. invideo Editor has all of them on every timeline. Use a branch for an experiment, a tag to name a milestone, and a checkpoint to go back to an earlier state. Use clear names where the controls allow them, so collaborators know which branch or checkpoint they are discussing. ### Can I return to an earlier timeline state after an AI edit? Source: https://docs.invideo.io/editor/can-i-return-to-an-earlier-timeline-state-after-an-ai-edit.md Use undo or a checkpoint to recover the edit you want to continue from. Yes. Undo the last edit, or restore a checkpoint. Agent edits stay part of the same editable timeline in invideo Editor. To undo your most recent edit on a Mac, press **Command + Z (⌘Z)** while working in the timeline. The editor toolbar with the Undo button and its tooltip To return to an earlier state, restore a checkpoint. invideo keeps a backup of the state you leave, so you can go back to it. Your agent does this with `timeline_history`, or in a terminal with `invideo branch restore`. To try a different approach and keep the current cut, use a **branch**. --- ### How to ask AI agents to edit your timeline Source: https://docs.invideo.io/ai-agents/how-to-ask-ai-agents-to-edit-your-timeline.md Give Agent Two clear editing instructions and review its changes on the invideo Editor timeline. Agent Two in invideo Editor helps you assemble and revise your cut. Describe the change in the agent panel, explain which footage to use and identify anything that should stay the same. The result remains available for manual editing on your timeline. The agent panel in invideo Editor with a request to cut a trailer from the footage already on the timeline #### Give an editing instruction 1. Open the project and timeline you want to work on. 2. Open the agent panel on the left and describe the task. 3. Include the length you want, relevant clips or section, and details to preserve. 4. Review the updated sequence in the Monitor and on the timeline. 5. Make a manual adjustment or give a focused follow-up instruction. **Example instructions.** *"Build a short introduction from these clips. Open on the product close-up and end on the logo."* *"Shorten this section while keeping the speaker's explanation in its original order."* *"Lower the background music during the dialogue."* *"Adjust these two shots so their color feels consistent."* Treat these as starting briefs. Add the names, sections and references that make the request clear in your project, then check the result before continuing. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. You can set Agent Two to ask before it generates. An outside agent, such as Claude or ChatGPT, runs a dry run first and tells you the price before it spends anything. See [Credits and what they cost](/account/credits). For the generation approval settings, see [How Agent Two credits work](/credits-and-plans/how-credits-are-charged-when-using-ai-agents). For the same steps from a chat app, see [Make a video with invideo without a terminal](/start/no-terminal). ### How Agent Two works with invideo Editor Source: https://docs.invideo.io/ai-agents/how-agent-two-works-with-invideo-editor.md Understand how Agent Two helps create your video and how invideo Editor gives you control over the timeline. Agent Two is invideo's own agent. It plans and creates videos from your instructions. invideo Editor is the editing workspace where you arrange and refine picture and sound on a professional timeline. You can direct AI work and make manual edits as part of the same project. #### Start with a creative brief Give Agent Two your idea, audience, story and useful references. For a film, campaign or series, include character and brand details that should carry through the work. Agent Two helps with scripting, storyboarding, generating media and assembling the cut. #### Refine the video in Editor Use invideo Editor to inspect the sequence, adjust clips, mix audio and grade the picture. You can also ask Agent Two to make changes, review the result and continue editing by hand. #### Understand agents and models An agent coordinates work toward your creative goal. A model performs a particular task, such as generating an image, video or voice. Direct model generation lets you work with a selected model for a specific asset. invideo Editor is where you shape assets into the finished sequence. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. See [Credits and what they cost](/account/credits). ### How to use multiple AI agents in an invideo project Source: https://docs.invideo.io/ai-agents/how-to-use-multiple-ai-agents-in-an-invideo-project.md Give specialist agents separate jobs and coordinate their work using shared project context. Several agents can work on different parts of an invideo project in parallel. Each agent has its own assignment, while a shared brief carries the project's characters, locations, references and creative rules. 1. Define your project brief and the details that should remain consistent. 2. Assign focused jobs, such as casting, locations, individual scenes or music. 3. Give feedback to the agent responsible for that task. 4. Review the outputs together before moving toward the finished cut. **Example.** *"Develop location options while another agent plans the opening scene. Keep both in line with the approved character and visual references."* Each agent works on its own branch, and branches do not merge. The agents share one brief and send each other messages. Review the results for continuity before you continue. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. An outside agent such as Claude or ChatGPT runs its own chat on that app's plan. See [Credits and what they cost](/account/credits) and [Run several agents and a person in one project](/how-to/developers/several-agents-one-project). ### Will an assigned agent job continue if I close the browser tab? Source: https://docs.invideo.io/ai-agents/will-an-assigned-agent-job-continue-if-i-close-the-browser-tab.md What happens to an Agent Two job after you close the browser tab. Yes. Jobs you assign to Agent Two run in the cloud and continue after you close the browser tab. You can reopen your saved timeline in invideo Editor to review the result. This applies to work you already sent to Agent Two. Send the request before you leave, and let file uploads finish before Agent Two uses those files. To find the project again, see [How to find and reopen a saved timeline in invideo Editor](/projects-and-exports/how-to-find-and-reopen-a-saved-timeline-in-invideo-editor). ### How do I use sketch to show Agent Two the composition I want? Source: https://docs.invideo.io/ai-agents/how-do-i-use-sketch-to-show-invideo-agent-the-composition-i-want.md Draw a visual reference in the Agent Two chat and use it to guide image or video generation. Sketch lets you show Agent Two what you want. You can create a reference to guide image or video generation, or sketch directly on a generated image to explain the edits you want. #### How do I create a visual reference? 1. Type **`/sketch`** in the Agent Two chat to open the drawing space. 2. Build your reference using freehand drawing, shapes or uploaded photos. 3. Arrange and annotate these elements to show your preferred framing, layout or object placement. 4. Attach your finished sketch to your message and explain what you want Agent Two to generate. The agent chat box with /sketch typed and the Sketch option to draw a reference for images and videos #### How do I edit a generated image using Sketch? You can sketch directly on any generated image to point out specific changes. - **Circle an area** to show where you want an edit. - **Add labels** to explain what should change. - **Drop in pictures** to provide visual references for the edit. The Sketch tool on a generated bridge image with a ship photo dropped in and the label 'medieval style small ship' The regenerated image of the stone bridge at golden hour with a small sailing ship on the river Ask Agent Two to apply the changes indicated by your annotations. The agent uses your sketch to make those targeted edits. For example, circle an object and label it with the color you want. If you add a reference picture, explain which detail the agent should use. ### Can I draw over an uploaded photo instead of starting a sketch from scratch? Source: https://docs.invideo.io/ai-agents/can-i-draw-over-an-uploaded-photo-instead-of-starting-a-sketch-from-scratch.md Annotate a photo to explain framing, object placement or a requested change. Yes. In **/sketch**, you can upload a photo, draw on it and layer shapes or other visual elements over it. Circle the area you want Agent Two to look at, or mark where an object should go. Add a short written explanation with the attachment. Say which marks are instructions and which visual details should appear in the result. This helps when a location or product photo already gives most of the context and you want to explain one change to the composition. ### How do I import Google Drive files into an invideo project from agent chat? Source: https://docs.invideo.io/ai-agents/how-do-i-import-google-drive-files-into-an-invideo-project-from-agent-chat.md Connect Google Drive once, then choose files to bring into your project. Connect Google Drive in Settings. In the Agent Two chat, type `/google-drive` or ask Agent Two for your Drive files. Select the images, videos or other files you want to import. The agent chat box with /goog typed and the Google Drive option to select files from Google Drive The selected files go into the project for Agent Two to use, so you do not need to download them to your computer and upload them again. Tell Agent Two which files are footage for the edit and which are creative references. Selecting a file adds it to the project. Add an editing request when you want Agent Two to do something with it. ### How do I save files from invideo to Google Drive? Source: https://docs.invideo.io/ai-agents/how-do-i-save-files-from-invideo-to-google-drive.md Ask Agent Two to save files to your Drive and organize them in a named folder. You can save files to Google Drive from the Agent Two chat. Tell Agent Two what to save and, if needed, which folder to use. 1. Connect **Google Drive** in **Settings** if it is not connected. You connect it once. 2. In the Agent Two chat, tell Agent Two which files you want to save. For example: **"Save this to my Drive."** 3. To organize the files in a specific folder, include its name in your request. For example: **"Put these in my Drive in a folder called Launch cuts."** 4. When the files are saved, Agent Two gives you a link to each file. Open a link to view the saved file in Google Drive. Files are saved inside an **invideo AI** folder in your Drive. If you name a folder, it becomes a subfolder inside that folder. For example, **Launch cuts** goes inside **invideo AI**. For this feature, invideo works only with the files it saves in that folder. ### Can Agent Two see my whole Google Drive after I connect it? Source: https://docs.invideo.io/ai-agents/can-the-invideo-agent-see-my-whole-google-drive-after-i-connect-it.md Agent Two gets only the Drive files you choose for the project. No. Agent Two sees only the files you pick through the Google Drive connection. It does not see the rest of your Drive. An agent chat message asking you to pick Drive files, with the Choose files from Google Drive button Choose the specific material needed for the project, such as the footage, product photos and reference files for that edit. ### How do I let Claude upload my files to invideo? Source: https://docs.invideo.io/ai-agents/how-do-i-let-claude-upload-my-files-to-invideo.md Allow m.invideo.io in Claude's settings once, so Claude can bring the images and videos you attach to a chat into your invideo project. To let Claude add the images and videos you attach in a chat to your invideo project, allow m.invideo.io in Claude's settings. You do this once. #### Allow m.invideo.io in Claude Follow these steps in Claude on the web or the desktop app. 1. In Claude, open **Settings**, then **Capabilities**. The direct link is claude.ai/settings/capabilities. 2. Check that **Create and edit files** is on, and under it, that **Use the internet while making files** is on. 3. Next to **Allowed websites**, click **Manage**. Claude's Capabilities settings with Create and edit files and Use the internet while making files turned on, and the Manage button next to Allowed websites 4. In the **Add a website** box, type m.invideo.io and click **Add**. m.invideo.io appears in the list under the box. The Allowed websites page in Claude with the Add a website box and its Add button, and m.invideo.io in the list under the box 5. Start a new chat with invideo turned on, attach the images or videos, and ask Claude to add them to your invideo project. Each file shows in the project's Media panel when its upload ends. #### If something goes wrong Check these if your files still do not reach invideo. | Symptom | Fix | | --- | --- | | Claude says it cannot upload your files to invideo | Allow m.invideo.io as in the steps above, then attach the files in a new chat. | | You cannot change Claude's settings | Your Claude account belongs to an organization. Ask an organization owner. | #### Add files without this setting You can also add files without changing anything in Claude. Open the project in invideo and drag the files into its Media panel. Then name the files in the chat, and Claude uses them by name. --- ### Adding dynamic text to your videos Source: https://docs.invideo.io/models/adding-dynamic-text-to-your-videos.md Add styled, animated text overlays to a video with the Dynamic Text models, from a preset style or from a prompt. Dynamic Text adds styled, animated text overlays to a video. The text sits in front of the person in the shot, like a motion graphic. It comes as two models: - `dynamic_text.styles` (Dynamic Text: Styles) puts a preset text style on your video. - `dynamic_text.diy` (Dynamic Text: DIY) makes free-form motion graphics from a prompt, on your video or on their own. Dynamic Text is motion text, not a captioning tool. It does not transcribe speech. For captions that follow each spoken word, see [Word-by-word captions](/how-to/creators/word-by-word-captions), or use the `invideo_subtitles` model. The Tools tab in the model search with 'dyn' typed and the Dynamic Text result #### How to get started In the invideo app, open Dynamic Text from the generative models and tools on the homepage. 1. Search for **Dynamic Text** in the tools. 2. Upload the video you want to add text to. 3. Pick a preset style, or describe the motion graphic you want in a prompt. 4. Confirm the credit cost and generate. 5. Preview the result and download it, or place it on your timeline. Your agent uses the same models through `generate` and reads the inputs with `get_model`. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### Text styles `dynamic_text.styles` takes a source video and a `text_style`. The styles are `NEON_COUNTDOWN`, `PIXEL`, `SCRIBBLE`, `SKETCH_STICKERS` and `STYLISH`. Each style comes with its own fonts, and you can set a `font` from its list and a font color. The `safe_zone` input keeps the text clear of the TikTok or Instagram buttons. `dynamic_text.diy` takes a `prompt` and an optional source video. Without a video, it gives you the motion graphic on its own. You can add reference documents for the content of the graphic. | Tip | Why it helps | | --- | --- | | Use a shot with one clear subject | The text sits in front of the subject, so a clear subject gives a clean result | | Set a safe zone for short-form content | Keeps the text visible on TikTok and Instagram, where the app's buttons can cover it | | Match the style to the content | Pick bold and playful styles for ads and UGC, and calmer styles for brand and editorial work | | Use the DIY model for your own design | Describe the words, the motion and the look in the prompt | Dynamic Text gives you a video file. A timeline export from invideo is a 1080p MP4. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. See [Models](/reference/models#when-a-model-retires). ### Creating storyboards with invideo Source: https://docs.invideo.io/models/creating-storyboards-with-invideo.md Vision turns a text prompt into a storyboard grid with consistent characters, lighting and art direction across every frame. Vision is a storyboard tool in the invideo app. It turns a text prompt into a storyboard grid with consistent characters, lighting and art direction across every frame. It is built for pre-production: you lock your visual language before you start generating video. Your agent does not use Vision. It makes storyboards with image models instead. See [Storyboards and previs](/how-to/film/storyboards-and-previs). #### How to get started In the invideo app, open Vision from the AI tools on the homepage. 1. Go to **Agents & models**, then **AI tools**. 2. Describe your scene and add any reference images. 3. Vision generates a storyboard grid. #### Storyboard options Vision has three modes: - **Boards** generates your storyboard sequence from the prompt. - **Looks** keeps your character's appearance consistent across every frame. - **Angles** shifts the camera perspective on any frame and keeps the character the same. | Tip | Why it helps | | --- | --- | | Describe your character clearly in your first prompt | Vision uses this as the reference across every shot | | Specify lighting and mood upfront | Vision carries this through the entire storyboard | | Use Angles after your first generation | Gives you more control than describing every camera angle in the first prompt | | If a frame is almost right, extract it and use it as a reference image | Saves you from making the whole storyboard again | #### Extracting a frame Select any frame from your storyboard. Extract it as a standalone image, or send it directly into video generation to build out the scene. ### Create with Seedance 2.0 Source: https://docs.invideo.io/models/create-with-seedance-2-0.md Make cinematic video with Seedance 2.0, with consistent characters, precise motion and reference images, video and audio. Seedance 2.0 makes cinematic video with consistent characters, precise motion and reference inputs. Your agent calls it as `seedance_2_0.r2v` (Seedance 2.0: Reference to Video) or `seedance_2_0.frames` (Seedance 2.0: Frames). The same family also has `seedance_2_0.edit` and `seedance_2_0.extend`. The Generative models row with an arrow pointing at the Seedance 2.0 card #### How to get started In the invideo app, open Seedance 2.0 from the generative models on the homepage. 1. Select **Generative models**, then select **Seedance 2.0**. 2. Upload a reference image, video or audio, or start from a text prompt alone. 3. Enter a detailed description of your scene. 4. Select your resolution and duration, confirm the credit cost, and generate. 5. Download your video. The agent uses the same model through `generate`. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### Spec information `seedance_2_0.r2v` takes a prompt with reference images, videos and audio. `seedance_2_0.frames` takes a first frame. A timeline export from invideo is a 1080p MP4. For resolutions, durations, sizes and shapes, the agent reads `get_model`. #### Prompt best practices Seedance 2.0 responds well to structured, specific prompts. A strong prompt covers these parts, in this order: **Shot type, subject, action, environment, lighting, style** *Example: Bright sunny afternoon on a tree-lined city sidewalk. Golden light filters through leaves, creating warm, dappled highlights. Soft bokeh of pedestrians and storefronts. Dry, warm tone.* | Tip | Why it helps | | --- | --- | | Be explicit about camera movement, such as dolly in, tracking shot, wide pan or bird's eye | Seedance reads motion direction directly from the prompt | | Describe lighting specifically, such as "golden hour backlight" or "soft studio rim light" | Gives the model a visual anchor to work from | | Keep character descriptions in the first prompt | Seedance uses this as its consistency reference across the generation | | For video references, prompt only for what changes | Describe the new subject and environment, not the motion itself | #### Content restrictions The model provider restricts realistic human faces in input images and videos. If your reference shows a clearly visible face, the provider is likely to block the generation. Use an illustrated or 3D rendered style, or an original character, for character references. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. See [Models](/reference/models#when-a-model-retires). ### Creating with Kling 3.0 Source: https://docs.invideo.io/models/creating-with-kling-3-0.md Make cinematic video with native audio, multi-shot scenes and consistent characters with Kling 3.0 on invideo. Kling 3.0 is a video generation model, available on invideo. Your agent calls it as `kling_v3_video` (Kling 3.0 Video). It makes cinematic video with native audio, multi-shot scenes, consistent characters and lip sync. It is built for creators who need finished output for ads, UGC, short films and social content. #### How to get started In the invideo app, open Kling 3.0 from the generative models on the homepage. 1. Select **Agents & Models**, then **Generative models**, then **See all**, then **Kling 3.0**. 2. Upload a first or last frame image, or start from a text prompt alone. 3. Enter your prompt and select your settings: shot type, resolution and duration. 4. Confirm the credit cost and generate. 5. Download your video. The agent uses the same model through `generate`. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### Spec information `kling_v3_video` takes a prompt, an optional first and last frame, and optional voice audio. It makes sound when you turn `sound` on, and multi-shot mode gives a scene of several shots. The aspect ratios are 16:9, 9:16 and 1:1. A timeline export from invideo is a 1080p MP4. For resolutions, durations and sizes, the agent reads `get_model`. #### Prompt best practices Kling 3.0 responds well to prompts that describe the scene, characters, action and camera in one structured statement. *Example: Over-the-shoulder tracking shot following a man in a dark coat through a rain-soaked Tokyo alley at night, neon reflections on wet pavement, handheld camera, tense thriller tone, ambient city noise and distant traffic.* | Tip | Why it helps | | --- | --- | | Describe each character distinctly in your prompt | Kling 3.0 uses character descriptions to keep identity across shots | | Specify audio direction explicitly | Kling makes native audio. Describe dialogue tone, ambient sounds or music style | | Use multi-shot mode for scene sequences | Kling 3.0 handles camera transitions when you describe the story of the scene | | Upload a first frame for character anchoring | Gives the model a visual reference to lock character appearance across the generation | Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. See [Models](/reference/models#when-a-model-retires). ### Creating with Veo 3.1 Source: https://docs.invideo.io/models/creating-with-veo-3-1.md Make cinematic video with native audio from a prompt or images with VEO 3.1, Google's video model, on invideo. VEO 3.1 is Google's flagship video model, available on invideo. Your agent calls it as `veo_31.frames` (VEO 3.1: Frames) or `veo_31.ingredients` (VEO 3.1: Ingredients), and `veo_31.extend` makes a clip longer. It makes cinematic video from text prompts or images, with character consistency, native audio and control over camera, lens, lighting and style. Use it for promos, social media content, product demos and other video without a shoot. #### How to get started In the invideo app, open VEO 3.1 from the generative models on the homepage. 1. Select **Generative models**, then **See all**, then **VEO 3.1**. 2. Upload a reference image, or start from a text prompt alone. 3. Add a first and last frame if you want to control how your video opens and closes. 4. Select your resolution and duration, confirm the credit cost, and generate. 5. Download your video. The agent uses the same model through `generate`. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### Spec information `veo_31.frames` takes a prompt and an optional first and last frame. `veo_31.ingredients` takes reference images. The aspect ratios are 16:9 and 9:16. For resolutions, durations and sizes, the agent reads `get_model`. #### Prompt best practices VEO 3.1 responds well to a layered prompt, in this order: **Camera and lens, subject, action, environment, lighting, style, audio** *Example: Wide tracking shot, a woman in a red coat walks through a foggy cobblestone street at dawn, warm lamplight, cinematic film texture, ambient city sounds.* | Tip | Why it helps | | --- | --- | | Follow the layered formula | Gives VEO 3.1 every part it needs for a precise, polished scene | | Specify camera and lens details | VEO 3.1 reads cinematic language directly: dolly, tracking, wide angle, close-up | | Include audio direction in your prompt | VEO 3.1 makes matching sound. Describe ambient sounds, music tone or dialogue | | Upload a reference image for consistency | Anchors character appearance and scene style across generations | | Use first and last frame for transitions | Useful for projects with several scenes, where visual continuity matters | Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. See [Models](/reference/models#when-a-model-retires). ### Creating images with Nano Banana Pro Source: https://docs.invideo.io/models/creating-images-with-nano-banana-pro.md Make and edit photorealistic images with Nano Banana Pro, Google's image model, with strong character consistency and text rendering. Nano Banana Pro is Google's image generation and editing model, available on invideo. Your agent calls it as `nanobanana_pro`. It generates and edits photorealistic images, with strong character consistency and precise text rendering. #### How to get started In the invideo app, open Nano Banana Pro from the generative models on the homepage. 1. Select **Generative models**, then **Image models**, then **See all**, then **Nano Banana Pro**. 2. Upload a reference image to edit, or start from a text prompt alone. 3. Enter a detailed description of the image you want to create. 4. Preview your result, refine it with a follow-up prompt, and download it. The agent uses the same model through `generate` and reads the inputs with `get_model`. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. #### Prompt best practices Nano Banana Pro responds well to prompts that describe subject, environment, lighting and style together. The more specific the prompt, the more precise the output. *Example: Close-up portrait of a man in a navy suit standing in a glass office at golden hour, warm backlight, shallow depth of field, editorial photography style.* | Tip | Why it helps | | --- | --- | | Describe lighting and mood explicitly | Nano Banana Pro relights the whole scene with coherent shadows and highlights | | Specify camera angle in your prompt | Wide, medium, close-up and top-down angles can all come from the same scene description | | Include the text you want in the image | Nano Banana Pro renders text in many languages. Describe the font style and placement | | Use image editing for targeted changes | Describe only what should change. The model keeps everything else as it is | Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. See [Models](/reference/models#when-a-model-retires). ### Creating with Gen-4 Aleph (Runway) Source: https://docs.invideo.io/models/creating-with-gen-4-aleph-runway.md Edit a video you already have with Aleph 2, Runway's video-to-video model: add or remove objects, relight a scene or change the angle. Aleph 2 is Runway's in-context video-to-video editing model, available on invideo. Your agent calls it as `aleph2`. It is an editing layer after generation. Take a video you already made or uploaded, and change it with a text prompt. Add or remove objects, change the camera angle, relight the scene or change a character, without a new shoot or a new generation. Aleph 2 replaces the earlier Gen-4 Aleph model on invideo. #### How to get started In the invideo app, open Aleph 2 from the generative models on the homepage. 1. Select **Generative models**, then **See all**, then **Aleph 2**. 2. Upload the video you want to edit. You can add keyframe images at set times in the clip. 3. Enter your prompt. Describe what you want to change. 4. Confirm the credit cost and generate. 5. Preview the result, refine it with follow-up prompts, and download it. The agent uses the same model through `generate` and reads the inputs with `get_model`. Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost. Aleph 2 charges by the length of the source video. #### Spec information `aleph2` takes a `video` and a `prompt`, both required. Optional `keyframes` are images, each pinned to a time in the source clip. The aspect ratios are 16:9, 9:16, 4:3, 1:1, 3:4 and 21:9. For the length of source video it takes, the agent reads `get_model`. #### Prompt best practices Aleph 2 works best when you describe the edit precisely: what exists, what should change and what should stay the same. *Example: Keep the product and table surface. Change the background to a dark moody kitchen at night. Add soft warm rim lighting from the right.* | Tip | Why it helps | | --- | --- | | Describe what stays, as well as what changes | Being explicit about what stays avoids edits you did not want | | Specify lighting direction and quality | The model relights scenes well when you name the light source and its quality | | Use camera language for angle changes | "Change to a medium close-up" or "shift to bird's eye view" gives the model a precise target | | Use keyframe images to pin a look | A keyframe image at a set time shows the model what that moment should look like | Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. See [Models](/reference/models#when-a-model-retires). --- ### How can AI-generated visuals be modified? Source: https://docs.invideo.io/invideo-ai/how-can-ai-generated-visuals-be-modified.md Use Remix in the Media section to change or animate an AI-generated image or video in your invideo AI video. You can change or animate an AI-generated image or video with the **Remix** option in the **Media** section. 1. Click **Edit**, then **Media**. Opening the Media section from the Edit menu 2. Go to **Generative Media**. The Generative Media tab in the Media section 3. Click the media you want to change, then select **Remix**. You can make basic changes to the AI-generated media here. The Remix option on a generated media item 4. Write clear instructions for the change or the animation you want, then click **Remix**. Remix uses credits, and the cost depends on the length of the media. See how credits work. You can check what you used on your [usage page](/credits-and-plans/where-can-i-check-my-current-usage). The Remix prompt box with instructions for the animation 5. Replace the old media with the new media, then preview the video. The newly generated media ready to replace the original ### How can I add a delay to the voiceover? Source: https://docs.invideo.io/invideo-ai/how-can-i-add-a-delay-to-the-voiceover.md Add a gap to your script so the voiceover pauses while the media and music keep playing. To delay the voiceover, add **(gap: Xs)** to your script. Replace X with the number of seconds you want the voiceover to wait. #### Add a gap from the Script section 1. Click **Edit**, then **Script**. 2. Type **(gap: Xs)** between the chapters where you want the pause. 3. Click **Save changes**. A gap tag typed between two chapters in the Script section #### Remove a gap with the Magic Box Type one of these commands in the Magic Box: - **Remove all (gap) from the video.** This removes every gap. - **Remove (gap: 3s) from all chapters.** This removes only the gaps of that length. A command to remove gaps typed in the Magic Box A video opens in Theatre mode in invideo AI. Click **Edit & Download** to leave Theatre mode. The Magic Box then shows below the video. Clicking Edit & Download to leave Theatre mode and show the Magic Box #### Play only media and music during a gap Add a gap between lines or chapters when you want only the media and the music to play. You can also [add a new line between sentences](/invideo-ai/how-can-i-split-a-line-add-a-new-line-or-merge-2-lines-in-my-script) and put the gap there. A gap on its own line between two sentences in the script ### How can I add, duplicate, and delete chapters in my video? Source: https://docs.invideo.io/invideo-ai/how-can-i-add-duplicate-and-delete-chapters-in-my-video.md Add, duplicate or delete chapters from the Script section of your invideo AI video. You can add, duplicate and delete chapters from the **Script** section. 1. Click **Edit**, then **Script**. Opening the Script section from the Edit menu 2. Go to the chapter you want to change. 3. Click the three dots at the top right of the chapter. 4. Choose an option: - **Duplicate chapter** makes a copy of this chapter. - **Add chapter before** adds a new chapter before this one. - **Add chapter after** adds a new chapter after this one. - **Delete chapter** deletes this chapter. The chapter menu with Duplicate, Add before, Add after and Delete options 5. Click **Save changes**. The Save changes button in the Script section When you add a new chapter in the Script section, also add a media keyword. The AI uses the keyword to find media for the new sentence. The media keyword field on a new chapter ### How can I add, edit, or delete text shown on my video? Source: https://docs.invideo.io/invideo-ai/how-can-i-add-edit-or-delete-text-shown-on-my-video.md Add, edit or delete the on-screen text of your invideo AI video from the Script section. You can add, edit or delete the text shown on screen from the **Script** section. 1. Click **Edit**, then **Script**. Opening the Script section from the Edit menu 2. Type new text in the text box, or edit or delete the text that is there. The on-screen text box on a chapter in the Script section New text typed in the on-screen text box 3. Pick a text style if you want one. See [how to change the chapter text style](/invideo-ai/how-to-change-the-chapter-text-style). The text style options for on-screen text 4. Click **Apply**. The Apply button under the text box 5. Click **Save changes** to save your new script. The Save changes button in the Script section Preview your video to see the new text. The video preview with the edited on-screen text ### How can I add more media between existing clips? Source: https://docs.invideo.io/invideo-ai/how-can-i-add-more-media-between-existing-clips.md Add more media to a chapter of your invideo AI video by adding keywords, from stock or generated by AI. To add more media to a chapter, add more keywords. The AI then puts more media in the video. 1. Click **Edit**, then **Media**. Opening the Media section from the Edit menu 2. Go to the place where you want the new media, for example after Media 1 in Chapter 1. 3. Select **Script** at the top, then click **Generative media**. If the video uses stock media, click **Stock media** instead. The Generative media and Stock media tabs The media list of a chapter with its existing clips 4. Click **+ add media**. 5. Enter keywords or phrases for the new media. 6. Click **apply**. The AI adds the media for you. The add media box with keywords entered You can also choose where the new media comes from: - **Switch to stock** picks media from the stock library. - **Switch to generative** makes the media with AI. This uses credits. The Switch to stock and Switch to generative options Preview your video to see the new media. You can also replace it with your own media or pick other media from the library. The video preview with the new media added between clips ### How can I add multiple voiceovers in the video? Source: https://docs.invideo.io/invideo-ai/how-can-i-add-multiple-voiceovers-in-the-video.md Add more than one speaker to your invideo AI video, from the prompt, the Use my Script flow or the Settings section. You can give your video more than one speaker. Do it when you create the video, or later in the **Settings** and **Script** sections. #### When you create a new video Ask for multiple speakers in your prompt, then click the arrow button to continue. A prompt that asks for a video with several speakers #### From the Use my Script flow 1. Select **Use my Script** on the prompt page. The Use my Script flow on the prompt page 2. Click the **Voice Actors** icon. 3. Add the speakers you want, next to one narrator. The product shows how many speakers you can add. The Voice Actors panel with a narrator and extra speakers For example, pick a male or female Clear American voice as the narrator. Then add speakers with different accents. All speakers speak the same language as the narrator. #### After the video is generated Give each chapter or sentence its own speaker so the video flows like a conversation. 1. Go to the **Settings** section. 2. Click the **+** button and pick a female or male voice. For more on voices, see [how to add or change the voice of the voiceover](/invideo-ai/how-can-i-add-or-change-the-voice-of-the-voiceover). The plus button to add a voiceover in the Settings section 3. Go to the **Script** section. 4. Pick a voiceover from the drop-down menu on each chapter or sentence. The voiceover drop-down menu on a chapter in the Script section Different voiceovers chosen for different sentences ### How can I add or change the voice of the voiceover? Source: https://docs.invideo.io/invideo-ai/how-can-i-add-or-change-the-voice-of-the-voiceover.md Pick the voiceover voice when you start an invideo AI video, or change it later with the Magic Box. When you start your video, you can name a voice in your prompt. You can also pick a voiceover and a style in the flow panel. The voiceover settings in the flow panel A prompt that names the voiceover voice You cannot play a voice before you generate the video. #### Change the voice of a generated video If your video is already generated, ask for a new voice in the Magic Box. A command to change the voiceover typed in the Magic Box #### Voices you can name in your prompt Each voice comes as a male or a female voice: - Clear American voice - Voice with a Californian accent - Voice with a New Yorker accent - Voice with a Southern accent - Voice with a Midwestern accent - Voice with standard Midwestern accent - Transatlantic voice - Voice with a Pacific Northwest accent - American Young Kid's voice - Middle-aged British voice - Old husky British voice - Indian English voice - Young Indian voice - Australian voice - Heavy Northern English voice - Colombian Spanish Voice - Castillian Spanish Voice - Mexican Spanish Voice - Canadian French Voice - French Voice - Italian Voice - Japanese Voice - Korean Voice - Dutch Voice - Polish Voice - Brazilian Portuguese Voice - Portuguese Voice - Russian Voice ### How can I adjust the media starting point? Source: https://docs.invideo.io/invideo-ai/how-can-i-adjust-the-media-starting-point.md Set where a clip starts playing in your invideo AI video with the trim from setting in Media properties. You set where a clip starts with the trim **from** setting in **Media properties**. 1. Click **Edit**, then **Media**. Opening the Media section from the Edit menu 2. Select **Media properties**. The Media properties option on a clip 3. Set trim **from**. This is the point in the clip where playback starts. If you set it partway into the clip, the video skips the part before it. The trim from field in Media properties 4. Check trim **to**. It shows how long the clip plays after the new start point. If the clip is too short for the sentence, it loops to fill it. The trim to field in Media properties The full length of the clip shows at the top as **Duration**. Use it to pick the right start point. The Duration of the clip shown at the top of Media properties 5. Play the clip from the side panel to check that it starts at the right time. 6. Click **proceed**, then **save changes**. ### How can I change the aspect ratio of my video? Source: https://docs.invideo.io/invideo-ai/how-can-i-change-the-aspect-ratio-of-my-video.md Change your invideo AI video to landscape or portrait with a command in the Magic Box. To change the aspect ratio of a video, type a command in the Magic Box. A video opens in Theatre mode in invideo AI. Click **Edit & Download** to leave Theatre mode. The Magic Box then shows below the video. Clicking Edit & Download to leave Theatre mode and show the Magic Box 1. Click the Magic Box. The Magic Box below the video 2. Type a command for landscape or portrait: - Change the aspect ratio to **Landscape** - Change the aspect ratio to **Portrait** You can also use words like 16:9, 9:16, vertical or horizontal. An aspect ratio command typed in the Magic Box 3. Click the arrow to apply the change. The arrow button that applies the Magic Box command invideo AI then generates your video in the new aspect ratio. ### How can I change the duration of my video? Source: https://docs.invideo.io/invideo-ai/how-can-i-change-the-duration-of-my-video.md Make your invideo AI video longer or shorter by adding or deleting chapters in the Script section. You change the length of your video in the **Script** section. Add chapters to make it longer, or delete chapters to make it shorter. 1. Click **Edit**, then **Script**. Opening the Script section from the Edit menu 2. Add chapters to make the video longer, or delete chapters to make it shorter. The chapter menu with options to add and delete chapters 3. For each new chapter, add **media keywords**. The AI uses them to show a matching image or video. You can replace it with your own later. The media keyword field on a new chapter 4. Click **Save Changes**. In a video with generative media, a new chapter uses credits because the AI generates new visuals. To save credits, add media from stock for the new chapter. ### How can I change the media duration? Source: https://docs.invideo.io/invideo-ai/how-can-i-change-the-media-duration.md Change how long each image or video plays in your invideo AI video, or replace a clip with a longer one. In invideo AI, the AI sets the duration of each media from the length of the footage. You can change it. How you do it depends on how many media are in the segment. #### A segment with more than one media A segment with two or more media has no gray lines between them. Here you can make each media longer or shorter. 1. Select the pen icon on the media. 2. Uncheck **trim automatically**. 3. Set the duration you want for this media. The trim automatically option unchecked on a media To check the length of a segment, open **Media properties**. The Media properties option on a media The segment length shown in Media properties #### Set the media duration to 0 You can set the duration of an image or video to 0. The AI then keeps the best length for the video and changes the duration of the other media in the same segment. A media duration set to 0 #### A segment with only one media A segment with only one media has gray lines on each side. Gray lines between segments that each hold one media To make it longer, replace it with a longer stock clip. You can also generate a new image or video with the generative media option. This uses credits. The options to replace a media with stock or generative media To learn how generative media uses credits, see how credits work. ### How can I change the video quality of my preview? Source: https://docs.invideo.io/invideo-ai/how-can-i-change-the-video-quality-of-my-preview.md Change the resolution of the video preview in invideo AI with the settings icon on the player. Your generated video previews at a reduced resolution by default, so it loads fast. You can change the preview quality to a higher or a lower resolution. 1. Click the settings icon at the bottom right of the preview. 2. Choose another resolution. The settings icon on the preview player with the resolution options ### How can I create a video using my script? Source: https://docs.invideo.io/invideo-ai/how-can-i-create-a-video-using-my-script.md Turn your own script into a video in invideo AI with the Use my script flow or a line in your prompt. To make a video from your own script, select **Use my script** on the prompt page. The Use my script option on the prompt page 1. Select **Use my script**. 2. Paste your script. 3. Set your preferences for media type, background music, subtitle style, language and other details. 4. Click **proceed** to finish your prompt. The Use my script form with options for media, music, subtitles and language 5. Click the **arrow button** to generate the video. The arrow button that generates the video #### How this works in each mode On the Agent Two prompt page, workflows like **Explainer** or **Script to Video** run in the conversational Agent flow. The agent chats with you while it builds the video. It does not generate the video in one shot. To generate the video in one shot with no back and forth, switch to **Autopilot** in the Agent Two dropdown first. Then select your template. The Agent Two prompt page. The mode dropdown reads Agent Two Ultra, and an arrow points at the Older versions button #### Use a line in any prompt You can also add this line to any prompt, followed by your script: ```text Create a video using exactly this script: ``` invideo AI then makes a video from that exact script. ### How can I delete media from my video? Source: https://docs.invideo.io/invideo-ai/how-can-i-delete-media-from-my-video.md Delete a clip from your invideo AI video and choose what fills its place, a blank, AI media or nothing. You delete media from the **Media** section. When you delete, you choose what happens to the space it leaves. 1. Click **Edit**, then **Media**. Opening the Media section from the Edit menu 2. Select the trash icon on the media. 3. Choose an option from the menu. Each option is explained below. The delete menu with its three options 4. Click **save changes**, then preview the video. #### Delete and add blank media This option replaces the media with a blank placeholder. A blank placeholder in place of the deleted media #### Delete and let AI decide With this option, the AI fills the space so the video shows no blank screen. What it does depends on the segment. Gray lines show where one segment ends and the next starts. ##### One media in the segment The AI changes the duration of the media before or after the segment to cover the gap. A segment with one media between gray lines ##### Several media, all with auto-trim disabled You can disable auto-trim to give a media a fixed duration. If every media left in the segment has a fixed duration, the AI adds new media to fill the full length of the segment. A segment where the media have auto-trim disabled ##### Several media, at least one with auto-trim enabled The AI stretches the media that have auto-trim enabled to fill the segment. If it cannot, it adds new media to fill the segment. A segment where one media has auto-trim enabled #### Delete along with the script This option removes the script and the media together. The whole segment goes. The segment removed with its script ### How can I delete uploaded media? Source: https://docs.invideo.io/invideo-ai/how-can-i-delete-uploaded-media.md Delete images and videos you uploaded to invideo AI from the Library page. You delete the images and videos you uploaded from the **Library** page. 1. Click the menu button at the top left, then go to **Library**. The Library item in the menu at the top left 2. Select the images or videos you want to delete. You can select one or many. 3. Click **Delete** at the top. Selected media in the Library with the Delete option at the top ### How can I download the subtitles? Source: https://docs.invideo.io/invideo-ai/how-can-i-download-the-subtitles.md Download the subtitles of your invideo AI video as an SRT file after you export the video. You can download the subtitles as an **.srt** file after you export your video. The recording below shows where to find the download. Downloading the subtitles as an SRT file from an exported video ### How can I edit or replace the existing audio in a media file or add custom SFX? Source: https://docs.invideo.io/invideo-ai/how-can-i-edit-or-replace-the-existing-audio-in-a-media-file-or-add-custom-sfx.md Replace the sound of a clip in invideo AI with an uploaded file, a stock sound effect or a generated one. You replace the sound of a clip in the **Audio & SFX** section of **Media properties**. SFX means sound effects. 1. Click **Edit**, then **Media**. Opening the Media section from the Edit menu 2. Select the clip whose sound you want to change, then click **Media properties**. The Media properties option on a clip 3. Go to the **Audio & SFX** section. It has three options: - **Upload audio** uses your own audio file. - **Stock SFX** picks a sound effect from the stock library. - **Generate SFX** makes a custom sound effect. The Audio & SFX section with Upload audio, Stock SFX and Generate SFX #### Use a stock sound effect 1. Select **Stock SFX**. 2. Type the sound you want and press Enter. A search for a sound in Stock SFX 3. Play each sound to hear it. Each sound shows its duration. Stock sound effects with play buttons and durations 4. Click the name of the sound you want. It shows at the top, next to the SFX or media audio. 5. Click **Proceed**, then save changes. The chosen sound effect shown at the top with the Proceed button #### Generate your own sound effect 1. Click **Back**, then choose **Generate SFX**. The Generate SFX option 2. Describe the sound and set its duration. 3. Click **Generate**. 4. Click the new sound to replace the audio, then click **Proceed** and save changes. A generated sound effect ready to use Preview the video after you save to check the sound. #### Use your own audio file 1. Select **Upload audio** and upload your MP3 file. 2. Click the file to replace the original audio. 3. Set the audio offset if you want the audio to start at a later point. An uploaded audio file with the audio offset setting #### Restore the original audio Click **Back to default**. The Back to default button in the Audio & SFX section You can keep the SFX or the media audio, but not both at the same time. The audio offset works only for uploaded audio. For clearer playback, you can [mute the voiceover](/invideo-ai/how-do-i-remove-the-voiceover-from-my-video), [remove the background music](/invideo-ai/how-do-i-remove-the-music-from-my-video) or change the SFX volume. ### How can I edit the script? Source: https://docs.invideo.io/invideo-ai/how-can-i-edit-the-script.md Edit the script of your invideo AI video: split, merge, add or delete segments and add gaps from the Script panel. You edit the script from the **Script** panel. Each sentence is a segment, and you change it with a right-click. 1. Click **Edit**, then **Script**. Clicking Edit, then Script, to open the Script panel 2. Find the sentence you want to edit in the list of chapters. 3. Right-click the sentence to see the options. The right-click menu on a script sentence with the segment options #### What each option does - **Split segment here**: Splits the sentence into two. You can add a new media keyword for the new segment. A sentence split into two segments, with a box for the new media keyword - **Merge with previous**: Joins the sentence with the one above and removes its media keyword. - **Merge with next**: Joins the sentence with the one below and removes its media keyword. - **Add segment before/after**: Adds a new box above or below the selected sentence. - **Delete segment**: Deletes the sentence and its media keyword. - **Add gap here**: Adds a pause in the voiceover and makes the media play longer. To undo your changes, click **Reset**. The Reset button in the Script panel ### How can I generate AI-generated media without creating a video? Source: https://docs.invideo.io/invideo-ai/how-can-i-generate-ai-generated-media-without-creating-a-video.md Generate new AI images and clips from the Media panel of a video you already made, then use them in your scenes. If you already made a video with generative media, you can generate more media from the **Media** panel. You do not need to create a new video. 1. Click **Edit**, then **Media**. Clicking Edit, then Media, to open the Media panel 2. Go to **Generative Media** and click **+ Generate new media**. The Generative Media tab with the Generate new media button Opening the Generate new media window from Generative Media 3. Choose **Text to clip** or **Text to image**. 4. Type your text and choose the aspect ratio. For a clip, also choose its length. The generate window with Text to clip and Text to image, a text box and aspect ratio options The window suggests keywords that match the theme of your video. Use them to get media that fits. Suggested keywords under the text box in the generate window Generating images and clips uses credits. A clip costs more the longer it is. See how credits work. 5. Click the new media to preview it. A preview of a generated image #### Use the new media in your video 1. Click the back arrow. 2. Select the media in your video that you want to replace. The back arrow in the generative media preview Selecting a scene's media to replace it with the generated media 3. Click **Proceed**, then **Save changes**, and preview the video. ### How can I replace the media in my video with another media or my own? Source: https://docs.invideo.io/invideo-ai/how-can-i-replace-the-media-in-my-video-with-another-media-or-my-own.md Replace a scene's media in invideo AI with the Magic Box, new generated media, stock media or your own uploads. You can replace the media in a scene in four ways: - Ask the Magic Box. - Generate new media. - Shuffle or search the stock media library. - Upload your own media. #### Ask the Magic Box Type a command in the Magic Box to replace the media in a scene. For example: - Change the 2nd media to _____ - Replace the media in scene 2 with _____ A video opens in Theatre mode. Click **Edit & Download** to leave Theatre mode and show the Magic Box under the video. Clicking Edit & Download to leave Theatre mode and show the Magic Box #### Generate new media 1. Click **Edit**, then **Media**. The Edit menu with the Media option 2. Go to **Generative Media** and click **+ Generate new media**. The Generative Media tab with the Generate new media button 3. Choose **Text to clip** or **Text to image**. 4. Type your text and choose the aspect ratio. For a clip, also choose its length. The window suggests keywords that match the theme of your video. The generate window with a text box, aspect ratio options and suggested keywords Generating images and clips uses credits. A clip costs more the longer it is. See how credits work. 5. Click the new media to preview it. A preview of a generated image #### Shuffle or search the stock media library 1. Click the **rotate** icon to see a new stock media option with each click. The rotate icon on a scene's media 2. Click the **shuffle** button to see all the options. This view also shows the media history, so you can see the media you saw before. The shuffle button on a scene's media All suggested media options and the media history 3. To see more choices, search the stock media library. You can browse a large set of images and videos. Search results in the stock media library 4. Click **all** to switch between images and videos. 5. Click the settings button to choose the media libraries you want to see media from. The settings button in the stock media library The list of media libraries to choose from #### Upload your own media 1. Click **Uploaded media**, then **Upload media**. The Uploaded media tab with the Upload media button Uploaded media ready to use in a scene 2. Click **Proceed**, then **Save changes**, and preview the video. ### How can I rotate my media? Source: https://docs.invideo.io/invideo-ai/how-can-i-rotate-my-media.md Rotate an image or clip in your invideo AI video from Media properties in the Media panel. You rotate media from **Media properties** in the **Media** panel. 1. Click **Edit**, then **Media**. Clicking Edit, then Media, to open the Media panel 2. Select the media you want to rotate, then click **Media properties**. The Media properties option on a selected media 3. Set the rotation angle you want. You can turn the media all the way around. The rotation control in Media properties 4. Click **Proceed**, then **Save changes**. ### How can I split a line, add a new line, or merge 2 lines in my script? Source: https://docs.invideo.io/invideo-ai/how-can-i-split-a-line-add-a-new-line-or-merge-2-lines-in-my-script.md Split, add, merge or delete lines in your invideo AI script with the right-click menu in the Script panel. Right-click the sentence you want to change in the **Script** panel. The menu shows the options for that sentence. The right-click menu on a script sentence with the segment options #### What each option does - **Split segment here**: Splits the sentence into two. Add a new media keyword for the new segment. If you do not add one, that part of the video is blank. A sentence split into two segments, with a box for the new media keyword - **Merge with previous**: Joins the sentence with the one above and removes its media keyword. - **Merge with next**: Joins the sentence with the one below and removes its media keyword. - **Add segment before/after**: Adds a new box above or below the selected sentence. - **Delete segment**: Deletes the sentence and its media keyword. - **Add gap here**: Adds a pause in the voiceover and makes the media play longer. ### How can I stop my video from looping? Source: https://docs.invideo.io/invideo-ai/how-can-i-stop-my-video-from-looping.md Stop media from looping in invideo AI by shortening the script segment or adding a new media keyword. Media loops when its script segment is longer than the media. The media repeats until the segment ends. Media also loops when you make it shorter than its segment. For example, if you cut a clip short, it repeats until the segment it belongs to ends. A media in the Media panel that is shorter than its script segment You can fix this in two ways. #### Make the segment shorter 1. Click **Edit**, then **Script**. Clicking Edit, then Script, to open the Script panel 2. Find the sentence. To find it fast, copy the sentence from the Media panel and search for it in the Script panel. 3. Shorten or rephrase the sentence. A sentence being shortened in the Script panel The segment now fits the media, and the media stops looping. The shorter segment with media that no longer loops #### Add a new media keyword 1. In the Script panel, click **+ add media**. 2. Type keywords or phrases for the media you want. 3. Click **apply**. The AI finds or makes media for the new keyword. The add media box in the Script panel with a keyword typed in You can also choose where the media comes from: - **Switch to stock**: invideo picks the media from the stock library. - **Switch to generative**: AI generates the media. This uses credits. See how credits work. The Switch to stock and Switch to generative options ### How can I undo or redo my edits? Source: https://docs.invideo.io/invideo-ai/how-can-i-undo-or-redo-my-edits.md Undo or redo changes to your invideo AI video with the undo and redo icons in the bottom panel. To undo a change, click the **undo** icon in the bottom panel of the page. The undo icon in the bottom panel A video opens in Theatre mode. Click **Edit & Download** to leave Theatre mode and show the bottom panel. Clicking Edit & Download to leave Theatre mode To bring back a change you undid, click the **redo** icon. The redo icon next to the undo icon in the bottom panel ### How can I upload and use my media with audio? Source: https://docs.invideo.io/invideo-ai/how-can-i-upload-and-use-my-media-with-audio.md Upload your own clip with its audio to invideo AI, use it in a scene and set its volume in Media properties. You can upload your own clip and keep its audio. You set the audio volume in **Media properties**. 1. Click **Edit**, then **Media**. Clicking Edit, then Media, to open the Media panel 2. Click **Uploaded Media**. The Uploaded Media tab in the Media panel 3. Click **Upload media** and add your video or image. You can now use it to replace any media in the video. The Upload media button in the Uploaded Media tab An uploaded video in the Uploaded Media tab 4. Open **Media properties** and set the audio volume. The Media properties option on the uploaded video The audio volume control in Media properties 5. Click **Proceed**, then **Save changes**. ### How can I upload images and videos? Source: https://docs.invideo.io/invideo-ai/how-can-i-upload-images-and-videos.md Upload your own images and videos to invideo AI from the Magic Box, the Media panel or the Media Library page. You can upload your own images and videos and use them in your generated video. Upload them when you create the video, from the **Media** panel, or from the **Media Library** page. Each file must be within the size the uploader accepts and in one of these formats: - Images: .png, .jpg, .jpeg, .webp - Videos: .mp4, .mov, .webm #### When you create the video Click **Add files** in the box where you type your prompt. You can add images, videos or audio. The Add files button in the prompt box #### From the Media panel 1. Click **Edit**, then **Media**. Clicking Edit, then Media, to open the Media panel 2. Click **Uploaded media**, then **Upload media**. The Uploaded media tab with the Upload media button Choosing files to upload from your device 3. Click **Proceed**, then **Save changes**, and preview the video. #### From the Media Library page 1. Click the menu button at the top left and go to **Media Library**. The menu at the top left with the Media Library option 2. Click **upload** and choose images and videos from your device. The upload button on the Media Library page invideo saves all your uploads in the Media Library. You can use them again in any project. ### How can I upload/replace my music and use it? Source: https://docs.invideo.io/invideo-ai/how-can-i-upload-replace-my-music-and-use-it.md Upload your own MP3 music to invideo AI, use it in a chapter and set loop, trim, fades and volume in Music properties. You can upload your own music and use it in place of the default music. The file must be an **MP3**. 1. Click **Edit**, then **Music**. Clicking Edit, then Music, to open the Music panel A video opens in Theatre mode. Click **Continue** to leave Theatre mode and show the **Edit** button at the bottom of the page. Leaving Theatre mode to show the Edit button 2. Click **Uploaded music**, then **Upload**, and add your audio file. The Uploaded music tab with the Upload button An uploaded music file in the Uploaded music tab 3. Select the chapter where you want to change the music, then click the music title. Selecting a chapter and a music title to use in it 4. Click **Apply**, then **Save changes**. #### Music properties Open **Music properties** for more options. The Music properties option on a music track You can loop the music, set its volume, add a fade-in and a fade-out, and choose where it starts and how long it plays. The Music properties panel with loop, trim, fade and volume controls - **Loop music**: The AI makes the music as long as each scene. If you set **Trim to** shorter than the scene, the music stops early and the rest of the scene is quiet. Turn on the loop to keep the music playing to the end of the scene. - **Trim from**: Sets the point in the track where the music starts. This cuts off the start of the track. - **Fade-in**: Sets when the music fades in. - **Fade-out**: Sets when the music starts to fade out. Turn off the loop for the fade-out to work. - **Music Volume**: Sets the music volume. To mute the music in a chapter, click the volume button. ### How can I use my previously generated media? Source: https://docs.invideo.io/invideo-ai/how-can-i-use-my-previously-generated-media.md Reuse images and clips you generated before in invideo AI from the Generative media tab of the Media panel. All the images and clips you generated are in the **Generative media** tab. You can use them in your current video. 1. Click **Edit**, then **Media**. Clicking Edit, then Media, to open the Media panel 2. Click **Generative media** to see all your generated images and clips. The Generative media tab in the Media panel A list of previously generated images and clips 3. Select the image or clip in your video that you want to replace. 4. Hover over the generated media in the library and click **replace**. The replace option on a generated media in the library 5. Click **Proceed**, then **Save changes**, and preview the video. ### How can I zoom in on the media? Source: https://docs.invideo.io/invideo-ai/how-can-i-zoom-in-on-the-media.md Zoom in on an image or clip in your invideo AI video from Media properties in the Media panel. You zoom in on media from **Media properties** in the **Media** panel. 1. Click **Edit**, then **Media**. Clicking Edit, then Media, to open the Media panel 2. Select the media you want to zoom in on, then click **Media properties**. The Media properties option on a selected media 3. Set the zoom level. A low value makes a small change and a high value gives a close-up. Pick the level that looks best. The zoom control in Media properties 4. Click **Proceed**, then **Save changes**. 5. Play the video to see the zoom. ### How can to add, remove, and change the position/size of subtitles? Source: https://docs.invideo.io/invideo-ai/how-can-to-add-remove-and-change-the-position-size-of-subtitles.md Add, remove, move or resize subtitles in your invideo AI video with commands in the Magic Box. You change subtitles with commands in the Magic Box. Type the command and click the arrow button to send it. A video opens in Theatre mode. Click **Edit & Download** to leave Theatre mode and show the Magic Box under the video. Clicking Edit & Download to leave Theatre mode and show the Magic Box #### Add or remove subtitles For example: - Add subtitles - Remove subtitles #### Move subtitles You can move the subtitles to the top, center or bottom of the screen. You can also ask for a set distance from the top or bottom. For example: - Change the subtitle position to 30% from the top - Change the subtitle position to 10% from the bottom A Magic Box command that moves the subtitles #### Change the subtitle size Ask for a size within the range the product shows. For example: - Change subtitle size to 100 - Make subtitles 70 A Magic Box command that changes the subtitle size Preview the video after the changes. To change the look of your subtitles, see [How to change the style of my subtitles](/invideo-ai/how-to-change-the-style-of-my-subtitles). ### How do I adjust the speed of the voiceover in my video? Source: https://docs.invideo.io/invideo-ai/how-do-i-adjust-the-speed-of-the-voiceover-in-my-video.md Make the voiceover in your invideo AI video faster or slower with the Magic Box or the Script panel. You can change the voiceover speed with the Magic Box or in the **Script** panel. The speed must be within the range the product shows. #### With the Magic Box Type a command in the Magic Box. For example: - Change the voiceover speed to 1.50 - Increase the voiceover speed A Magic Box command that changes the voiceover speed #### In the Script panel 1. Click **Edit**, then **Script**. Clicking Edit, then Script, to open the Script panel 2. Click the name of the voiceover or narrator. A window opens. 3. Set the voice speed in the window. The voice window with the speed control ### How do I remove the music from my video? Source: https://docs.invideo.io/invideo-ai/how-do-i-remove-the-music-from-my-video.md Remove or mute the music in your invideo AI video with the Magic Box, the Settings panel or the Music panel. You can remove the music in three ways: with a Magic Box command, in **Settings**, or per chapter in the **Music** panel. #### With the Magic Box Type a command in the Magic Box. For example: - **Mute the background music** - **Decrease music volume to 0** A Magic Box command that mutes the background music #### In Settings Move the music volume slider to set the music volume for the whole video. The music volume slider in Settings #### In the Music panel You can delete the music in one chapter or in more than one. Choose one of these options: - **Delete and add silence** - **Delete and play the previous music** The delete options for music in the Music panel Click **Save changes** after the changes. ### How do I remove the voiceover from my video? Source: https://docs.invideo.io/invideo-ai/how-do-i-remove-the-voiceover-from-my-video.md Mute the voiceover in your invideo AI video with the Magic Box or the Voiceover Master Volume in Settings. You can mute the voiceover with a Magic Box command or in **Settings**. #### With the Magic Box Type a command in the Magic Box. For example: - Decrease voiceover volume to 0 - Mute the voiceover A Magic Box command that mutes the voiceover #### In Settings 1. Click **Edit**, then **Settings**. Clicking Edit, then Settings, to open the Settings panel 2. Set the **Voiceover Master Volume**. The Voiceover Master Volume slider in Settings The Magic Box cannot mute the voiceover in only one part of the video. Instead, add pauses to the voiceover in the Script panel. See [How can I add a delay to the voiceover?](/invideo-ai/how-can-i-add-a-delay-to-the-voiceover) ### How to adjust/fit the media in the video? Source: https://docs.invideo.io/invideo-ai/how-to-adjust-fit-the-media-in-the-video.md Move an image or clip side to side or up and down in your invideo AI video with the X-Axis and Y-Axis in Media properties. You move an image or clip inside the frame with the X and Y center points in **Media properties**. 1. Click **Edit**, then **Media**. Clicking Edit, then Media, to open the Media panel 2. Select the media and open **Media properties**. Media properties with the X-Axis and Y-Axis controls 3. Set the axis you need: - **X-Axis**: Moves the media side to side in a vertical 9:16 video. - **Y-Axis**: Moves the media up or down in a wide 16:9 video. The media moved inside the frame with the axis controls In a wide 16:9 video, you can move the media up or down only if there is space around it. ### How to change or edit the background music? Source: https://docs.invideo.io/invideo-ai/how-to-change-or-edit-the-background-music.md Change the background music of an invideo AI video with your prompt, the Magic Box or the Music section, and set loop, trim, fade and volume. You can add, change or adjust the background music in three places: in your first prompt, in the workflow, or in the **Music** section after the video is generated. The workflow screen with the background music options #### Use the Magic Box When you open a video in invideo AI, it opens in Theatre mode. To show the Magic Box: 1. Click **Edit & Download** to leave Theatre mode. 2. Find the Magic Box below the video. Clicking Edit and Download to leave Theatre mode and show the Magic Box After the video is generated, type a command in the Magic Box to edit the music. For example: - Turn the background music up to full volume - Mute the background music - Change the music to be more upbeat and energetic #### Use the Music section You can also make the changes in the **Music** section. Opening the Music section of a generated video From the **Music** section, you can open the stock library. Browse it and replace the music with tracks from the YouTube library or Storyblocks. The stock music library in the Music section A list of music tracks to pick from in the stock library To change the music of one chapter: 1. Select the chapter where you want to change the default music. 2. Click the music title. A chapter selected in the Music section with its music title 3. Click **Apply**, then save your changes. #### Use Music properties For more manual control, click **Music properties**. The Music properties button in the Music section In **Music properties**, you can loop the music, change its volume, set fade-in and fade-out points, choose where the music starts, and set how long it plays. The Music properties panel with loop, trim, fade and volume settings - **Loop music:** The AI makes the music fit the length of each scene. If you set **Trim to** shorter than the scene, the music stops early and the end of the scene is silent. Turn on looping to keep the music playing to the end of the scene. - **Trim from:** Choose the point in the track where the music starts. This trims the start of the track. - **Fade-in:** Choose the point in the video where the music fades in. - **Fade-out:** Choose the point where the music starts to fade out. For fade-out to work, turn off the loop. - **Music Volume:** Set the music volume up to the limit the product shows. To mute the music for a chapter, click the volume button. ### How to change the accent once the video is generated? Source: https://docs.invideo.io/invideo-ai/how-to-change-the-accent-once-the-video-is-generated.md Change the narrator's or a speaker's accent in a generated invideo AI video with the Magic Box or the Script section. You can change the accent in a generated video in two ways: with the Magic Box, or in the **Script** section. #### Use the Magic Box Type a command in the Magic Box to change the narrator's accent. Use the same kind of command to change the voice of one speaker. For example: - Change the narrator to a female American Young Kid's voice. - Change the voice for Speaker 1 to a male British Husky voice. A command in the Magic Box that changes a speaker's voice Repeat the command for Speaker 2, Speaker 3 and the other speakers as needed. #### Use the Script section In the **Script** section, you can pick a different speaker for each sentence or chapter. Picking a speaker for a sentence in the Script section 1. Click the avatar name. 2. Click **Change character to**, then pick the new character. The Change character to option after clicking the avatar name For the voices you can pick from, see [How can I add or change the voice of the voiceover?](/invideo-ai/how-can-i-add-or-change-the-voice-of-the-voiceover). ### How to change the chapter text style? Source: https://docs.invideo.io/invideo-ai/how-to-change-the-chapter-text-style.md Change the style of chapter titles, listicles and on-screen text in invideo AI with the Magic Box or the text preset setting. You can make your chapter titles, listicles and on-screen text stand out. Type a command in the Magic Box to change the style of the text elements. These are the commands: - **Change text element style to Simple** A chapter title in the Simple text style - **Change text element style to Sleek** A chapter title in the Sleek text style - **Change text element style to Intense** A chapter title in the Intense text style - **Change text element style to Bold** A chapter title in the Bold text style #### Use the text preset setting You can also change the style in **Settings**, then **Text preset**. The Text preset option in Settings This feature works best when the video has no subtitles, because it is made mainly for chapter titles. Titles also look different from listicles and lower thirds. ### How to change the style of my subtitles? Source: https://docs.invideo.io/invideo-ai/how-to-change-the-style-of-my-subtitles.md Pick a subtitle style in your prompt or the workflow, then change style, color, highlight and text box with the Magic Box or Settings. When you start your video, you can add a line about subtitles to your prompt. You can also pick a caption style in the workflow panel. The caption style options in the workflow panel A prompt with a line that asks for a subtitle style #### Subtitle styles you can ask for - Add bold subtitles with popping effect - Add clean subtitles with no outline - Add clean subtitles with outline - Add karaoke style subtitle - Add classic hormozi subtitle - Add word by word subtitle - Add the comica subtitle - Add subtitles with comic font and the shake effect - Add all caps subtitles - Add subtitles with a banger effect - Add subtitles with the yellow comic box style - Add subtitle style with radical blur effect #### Change the style after the video is generated After the video is generated, you can change the subtitle style with the Magic Box: The video shows a subtitle style command typed in the Magic Box and the subtitles changing to the new style. You can also change it in **Settings**, then **Subtitle Preset**. The Subtitle Preset option in Settings #### Change the color, text box and highlight Use the Magic Box to change the color, the highlight and the text box of the subtitles. For example: - Change **subtitle** style color to red Subtitles in red after the color command - Change subtitle style **highlight** color to white - Change the subtitle style with white highlight Subtitles with a white highlight on the spoken word - Change subtitle style text **box** color to LightSalmon Subtitles in a LightSalmon text box - **Remove** subtitle-style text box background. Subtitles with no text box background You can use any of the common color names that modern browsers support. See this list of color names. Hex codes for colors and text box opacity do not always work, so use color names in commands like the ones above. ### How to make the pace of my video slower or faster? Source: https://docs.invideo.io/invideo-ai/how-to-make-the-pace-of-my-video-slower-or-faster.md Use the Magic Box in invideo AI to make the pace of a generated video slower or faster. Type a command in the Magic Box to make the pace of the video slower or faster. When you open a video in invideo AI, it opens in Theatre mode. To show the Magic Box: 1. Click **Edit & Download** to leave Theatre mode. 2. Find the Magic Box below the video. Clicking Edit and Download to leave Theatre mode and show the Magic Box 3. Type one of these commands: - **Make the pace of the video slower.** This adds less media to the video. - **Make the pace of the video faster.** This adds more media to the video. A pace command typed in the Magic Box 4. Click the arrow to apply the change. ### Text to title clip Source: https://docs.invideo.io/invideo-ai/text-to-title-clip.md Generate a short title clip from a text prompt with the Text to title clip feature in invideo AI, then preview and download it. Text to title clip turns a text prompt into a short title scene that you can download. 1. Click **Menu** in the top left corner. 2. Click **Text to title clip**. The Menu with the Text to title clip option 3. Type your prompt in the text box and describe your title scene. The duration has a default value. 4. Select the dimension you want. For example: "Grand Opening", a cinematic-style title with dramatic lighting. The Text to title clip prompt box with a sample title prompt 5. After the clip is generated, click the media to preview it. 6. Download the clip and use it as you need. A generated title clip ready to preview and download The credits a title clip uses depend on the length of the clip and the model version. Newer model versions use more credits because they give higher quality. See video model pricing. To track your remaining credits, see [Where can I check my current usage](/credits-and-plans/where-can-i-check-my-current-usage). --- ### Am I allowed to monetize YouTube videos that feature invideo's avatars? Source: https://docs.invideo.io/avatars/am-i-allowed-to-monetise-youtube-videos-that-feature-invideo-s-avatars.md Yes. You can monetize videos you make with invideo AI avatars on any platform. Yes. You can monetize the videos you make with invideo AI avatars on any platform. ### Can avatars be used in different workflows? Source: https://docs.invideo.io/avatars/can-avatars-be-used-in-different-workflows.md Use your AI twin or a library avatar in any workflow on the invideo AI prompt page. Yes. You can use your AI twin or any avatar from the library in different workflows. 1. On the prompt page, click **Workflow**. The prompt page with the Workflow option 2. Search for the workflow you want to use. 3. Enter your prompt and change the settings as you need. 4. Click **Proceed**. 5. In the prompt box, click **AI twins**, then select the avatar that fits your video. The prompt box with the AI twins menu open and a list of avatars ### Can I change the avatar’s clothing? Source: https://docs.invideo.io/avatars/can-i-change-the-avatar-s-clothing.md invideo AI does not let you change an avatar's outfit. No. You cannot change an avatar's outfit in invideo AI. invideo uses your feedback to improve the product. ### Can I change the speed or tone of the avatar’s voice? Source: https://docs.invideo.io/avatars/can-i-change-the-speed-or-tone-of-the-avatar-s-voice.md Change the speed of an avatar's voice from the Script panel. The tone of the voice does not change. You can change the speed of the avatar's voice. You cannot change its tone. 1. Click **Edit**, then **Script**. Opening the Script panel from the Edit menu 2. Click the avatar's name. The **Change speed to** option appears. Clicking the avatar's name in the script to show the Change speed to option 3. Pick a speed from the range the product shows. The Change speed to menu with the speed options for the avatar's voice A change to the speed changes the length of the video, and that affects your credits. When the video gets longer, invideo AI adds more media so no scene is blank. This media uses credits. See how credits work. ### Can I control the avatar’s emotions? Source: https://docs.invideo.io/avatars/can-i-control-the-avatar-s-emotions.md invideo AI does not let you change an avatar's emotions. No. You cannot change an avatar's emotions in invideo AI. ### Can I have two avatars interacting in one video? Source: https://docs.invideo.io/avatars/can-i-have-two-avatars-interacting-in-one-video.md Put more than one avatar in a video with the multi-actor options in the Human actors library. Yes. You can put more than one avatar in your video. Pick a multi-actor option in the **Human actors** section. 1. In the prompt box, click **AI twins**. The prompt box with the AI twins button 2. Select **Pro actors library**, then **Human actors**. 3. Click **Looks** in the bottom right corner to preview how each actor looks and sounds. The Human actors library with the Looks button on an actor 4. Click the label that shows the number of actors. Actor cards in the Human actors library with labels for the number of actors A popup opens. It shows the types of videos these actors work best for. ### Can I retain access to my avatar even after canceling my plan? Source: https://docs.invideo.io/avatars/can-i-retain-access-to-my-avatar-even-after-cancelling-my-plan.md Your cloned avatar stays in your account after you cancel your plan. Yes. Your cloned avatar stays available after you cancel your plan. ### Can I use the avatar to create videos in different languages? Source: https://docs.invideo.io/avatars/can-i-use-the-avatar-to-create-videos-in-different-languages.md Use your AI twin or a library avatar in any language that invideo AI supports. Yes. You can use your own AI twin or an avatar from the library to make videos in any language that invideo AI supports. ### How can I change the avatar after my video is created? Source: https://docs.invideo.io/avatars/how-can-i-change-the-avatar-after-my-video-is-created.md invideo AI does not let you change the avatar after the video is generated. You cannot change the avatar after invideo AI generates the video. Pick the avatar you want before you generate. ### How can I change the placement of the avatar? Source: https://docs.invideo.io/avatars/how-can-i-change-the-placement-of-the-avatar.md Change where the avatar appears with the Mode dropdown in the Script panel. You change the avatar's placement in the **Script** panel. 1. Click **Edit**, then **Script**. Opening the Script panel from the Edit menu 2. Click the avatar's name. 3. Open the **Mode** dropdown and pick a placement: - **Full Screen** - **Picture in Picture** - **Split screen** The Mode dropdown with the Full Screen, Picture in Picture and Split screen options ### How can I create a video using an actor from invideo library? Source: https://docs.invideo.io/avatars/how-can-i-create-a-video-using-an-actor-from-invideo-library.md Pick an actor from the Free or Pro actors library in AI twins and generate your video. You pick an actor from the avatar library in the prompt box, then generate the video. 1. In the prompt box, click **Older versions** to open the avatar library. The prompt box with the Older versions option 2. Click **AI twins**. The AI twins menu with the Pro and Free actors libraries 3. Pick an avatar from the **Free** or **Pro** actors library. Pro avatars use credits for each minute of video. Picking an actor from the Pro actors library 4. Click **Generate my video**. invideo AI shows the [credits the video needs](/credits-and-plans/where-can-i-see-the-credits-calculated-for-my-video-media-before-creating-it). When the video is ready, you can preview it. To learn how credits are counted, see [invideo plans and credits](/credits-and-plans/invideo-plans-and-credits-everything-you-need-to-know) and how credits work. ### How can I remove the background from an avatar? Source: https://docs.invideo.io/avatars/how-can-i-remove-the-background-from-an-avatar.md Default avatars keep their background in full screen. Switch the avatar to PIP mode for a look without a background. The default avatars, human and virtual, come with a full-screen background that you cannot remove. To get a look without a background, switch the avatar to Picture in Picture (PIP) placement. 1. In the video, click **Edit**, then **Script**. The Edit menu with the Script option 2. Click the avatar's name in the script. A popup menu opens. 3. Find the **Mode** setting and change it from **Full screen** to **PIP**. The avatar popup menu with the Mode setting set to PIP The avatar now shows without its background. **Before:** The avatar in Full screen mode with its background **After:** The avatar in PIP mode without its background ### How do I apply my cloned voice to an existing video? Source: https://docs.invideo.io/avatars/how-do-i-apply-my-cloned-voice-to-an-existing-video.md Tell the Magic Box to change the narrator voice to your cloned voice. To change the voiceover of a generated video to your cloned voice, give this command in the Magic Box: ``` Change narrator voice to [name of your voice] ``` Use the name your voice has in the **AI twins** section of the prompt page. The Magic Box with a command to change the narrator voice to a cloned voice ### How to clone your voice? Source: https://docs.invideo.io/avatars/how-to-clone-your-voice.md Upload a recording of your voice in AI twins to make a voice clone for your invideo AI videos. You clone your voice from the **AI twins** menu in the prompt box. The homepage opens the newest agent flow by default. To use AI twins, click **Older versions** to switch to the previous flow. The homepage with the Older versions option 1. In the prompt box, click **AI twins**. The prompt box with the AI twins button 2. Click **Create voice clone**. The AI twins menu with the Create voice clone option 3. Upload a voice file in one of the formats the uploader accepts, such as MP3, WAV or M4A. 4. Follow the instructions on screen. Read the permission statement at the start of the recording. invideo requires explicit consent from the person in the recording. The voice clone upload screen with the recording instructions 5. Click **Looks good**, then tick all the checkboxes. The consent checkboxes for the voice clone 6. Click **Finalize** to keep the take, or **Redo** to record it again. Finalizing takes a few minutes. The take review screen with the Finalize and Redo buttons Your cloned voice now shows under **Your voice only clones** in AI twins. You can use it in your videos. ### How to create my avatar? Source: https://docs.invideo.io/avatars/how-to-create-my-avatar.md Create your own avatar in AI twins from a photo or a video of yourself. You create your own avatar from a photo or a video of yourself. Click **Older versions** to open the avatar library. The homepage with the Older versions option 1. In the prompt box, click **AI twins**. The prompt box with the AI twins menu open 2. Choose to create a **Free** or a **Pro** avatar of yourself. A Pro avatar uses credits. See how credits work and [invideo plans and credits](/credits-and-plans/invideo-plans-and-credits-everything-you-need-to-know). The options to create a Free or a Pro avatar 3. Follow the steps on screen. invideo requires explicit consent from the person in the recording. If you use the Free avatar option and do not give consent in the recording, a message asks you to record again with consent. The message that asks you to record again with consent 4. Click **Looks good** and make sure all the boxes are ticked. The confirmation checkboxes, all ticked, with the Looks good button invideo AI analyzes your video and creates your AI twin. You can then use it in your videos. ### How to create your AI twin? Source: https://docs.invideo.io/avatars/how-to-create-your-ai-twin.md What an AI twin is in invideo AI, with a video that shows how to create one. An AI twin is a realistic digital version of you. It speaks, gestures and presents content like you do, so you do not need to stand in front of a camera. Type a prompt, and your AI twin delivers it with a natural voice and facial expressions. Use it for training, marketing, support and other videos. To see the other types of avatars, read [What types of avatars does invideo offer?](/avatars/what-types-of-avatars-does-invideo-offer) ### How to delete, rename or make the voice clone default? Source: https://docs.invideo.io/avatars/how-to-delete-rename-or-make-the-voice-clone-default.md Pick a voice clone for your videos, and delete or rename a voice clone, from AI twins. To use your voice clone in your videos: 1. In the prompt box, click **AI twins**. The prompt box with the AI twins button A list of your cloned voices appears. The AI twins menu with a list of cloned voices 2. Hover over the voice you want to use and click it. 3. Click **Continue** in the popup. 4. Type your prompt. invideo AI generates your video with the selected voice clone. The prompt box with a voice clone selected To delete or rename a voice, click the three dots next to it. Then pick **Delete** or **Rename**. The three-dot menu next to a voice clone with the delete and rename options ### How to enable the avatar for a certain segment in my video? Source: https://docs.invideo.io/avatars/how-to-enable-the-avatar-for-a-certain-segment-in-my-video.md Show the avatar in a segment of a generated video with Enable avatar in the Script panel. After invideo AI generates your video, you can show the avatar in segments where it does not appear. 1. Click **Edit**, then **Script**. Opening the Script panel from the Edit menu 2. Click the avatar's name in the segment. 3. Click **Enable avatar**. The avatar popup with the Enable avatar option Turning on the avatar for a segment in the script 4. Change how the avatar appears. You can switch the take, or choose **full screen** or **picture-in-picture** mode. The avatar settings with the take and the full screen and picture-in-picture modes 5. Click **Apply** to save the changes. ### What if you remove any avatar, and I have posted a video on YouTube? Source: https://docs.invideo.io/avatars/what-if-you-remove-any-avatar-and-i-have-posted-a-video-on-youtube.md Videos you already published stay as they are if an avatar leaves the invideo library. Nothing changes for your published videos. A published video stays as it is. If invideo removes an avatar from the library later, the videos you already shared on YouTube or social media are not affected. ### What types of avatars does invideo offer? Source: https://docs.invideo.io/avatars/what-types-of-avatars-does-invideo-offer.md invideo AI offers avatar clones of yourself, human actors and virtual actors. invideo offers different types of avatars for different videos. #### Avatar clones Create a digital version of yourself with one of these options: - **Create pro avatar** - **Create free avatar** The AI twins menu with the Create pro avatar and Create free avatar options #### Human actors Human actors are based on real people. Their digital clones are in the library. They make your videos feel more authentic. Use them when you want a real human face to promote or advertise your product. Browsing the Human actors library #### Virtual actors Virtual actors are AI-generated. They are not based on real people. Like human actors, they work best in the UGC ad workflow. They give you more freedom in style and customization. - **Free virtual actors:** The Free virtual actors library - **Pro virtual actors**, with an active plan: The Pro virtual actors library Videos with Pro human or virtual actors use credits. See [invideo plans and credits](/credits-and-plans/invideo-plans-and-credits-everything-you-need-to-know) and how credits work. Some content is not allowed with any actor, your own or one from the library. See the [avatar content policy](/rights/what-content-topics-are-blacklisted-for-all-avatar-actors). ### Who has access to my cloned avatar? Source: https://docs.invideo.io/avatars/who-has-access-to-my-cloned-avatar.md Only you can use your cloned avatar. It is not added to the shared avatar library. Only you. Your custom avatar is **available only to you**. It is not added to the avatars that all customers can use. --- ### Can I create an avatar of a celebrity? Source: https://docs.invideo.io/rights/can-i-create-an-avatar-of-a-celebrity.md You cannot create an avatar of a celebrity or politician, because invideo requires explicit consent from the person in the recording. No. invideo requires **explicit consent** from the person in the recording. So you cannot clone or impersonate public figures, such as celebrities or politicians. The same rule applies to a real person's likeness or voice in generated media. See [Licensing and commercial use](/account/commercial-use). ### Can I download and use the AI-generated media? Source: https://docs.invideo.io/rights/can-i-download-and-use-the-ai-generated-media.md Yes. Download the media invideo AI generates for your projects from Generative Media, also after you cancel your subscription. Yes, you can download and use AI-generated media. All media that invideo AI generates for your projects stays available to you, also after you cancel your subscription. For what you may do with it, see [Licensing and commercial use](/account/commercial-use). To download a piece of generated media: 1. Open your video. 2. Click **Edit**, then **Generative Media**. 3. Right-click the media you want, then click **Download**. The Generative Media panel with the right-click menu and the Download option 4. In the new window, click **Download** again to save the media to your computer. The media preview window with the Download button ### Do I have reseller rights? Source: https://docs.invideo.io/rights/do-i-have-reseller-rights.md Yes. You have full rights to the videos you make with invideo, and you can use them anywhere and for any purpose. Yes. You have complete rights to all the videos that you make with invideo. You can use the videos you create anywhere, at any time and for any purpose. The videos you create are your property. You take full responsibility for how you use them. Stock media inside a video stays under its own license. See [Licensing and commercial use](/account/commercial-use). ### Do I still have rights over the videos which I created when I was on an active plan? Source: https://docs.invideo.io/rights/do-i-still-have-rights-over-the-videos-which-i-created-when-i-was-on-a-paid-subscription.md Yes. After your plan ends, you can still use the videos you made while you had an active plan. Yes. After your plan ends, you can still use the videos you made while you had an active plan. The videos you created stay with you, the same as before. For what you own in a video and how stock and generated media are licensed, see [Licensing and commercial use](/account/commercial-use). ### What content topics are blacklisted for all avatar actors? Source: https://docs.invideo.io/rights/what-content-topics-are-blacklisted-for-all-avatar-actors.md The content topics that no human avatar actor creates content for, whatever the request or context. invideo's human avatar actors do **not** create content in the restricted categories below. This list keeps ethical standards, follows regulations and keeps the experience safe for all users. The list applies to all actors, whatever the individual request or context. #### Substance-related businesses - Cannabis and marijuana products, such as CBD and THC items, vaping devices and dispensaries. Many regions still regulate these products by law. - Alcohol, tobacco and nicotine products, such as cigarettes, vapes and nicotine pouches. This is for public health reasons. #### Adult content and services - Escort services, prostitution, human trafficking, or any adult platform, such as OnlyFans, AdultFriendFinder and similar services. - Brands that promote adult toys, provocative lingerie or other intimate products. This follows invideo's family-friendly policy. - Intimate hygiene products, sexual wellness supplements, menstrual products, fake medical claims such as unapproved cures or organ enhancement treatments, and condoms, contraceptives or lubricants that the FDA or the relevant authority has not approved. #### Gambling and financial risk - Gambling services, such as casinos, sports betting and online gambling platforms. - Cryptocurrency and blockchain businesses, such as crypto exchanges, NFTs and mining. This is because the regulations for them are uncertain. - Multi-level marketing (MLM) schemes, unregulated investment pitches, financial services that the SEC has not approved, Ponzi schemes, and any form of financial fraud or identity theft. #### Political and government topics - Political endorsements, criticism or commentary on any candidate or political party in any country. - Hate speech, misinformation or propaganda about political events or political figures. #### Violence, terrorism and weapons - Support for or opposition to any current or historical war. - Mentions of terrorism or known terrorist organizations, and promotion of weapons, firearms or gun laws. #### Discrimination and hate speech - Any form of hate speech. This includes racism, sexism, homophobia, transphobia, ableism and discrimination against the LGBTQ+ community. #### Religion - Support for or criticism of any religion, deity or religious practice from any culture. - Religious hate speech, misinformation or disrespectful commentary. #### When a topic does not match the actor If the topic of your video does not match the actor's preferences, a message like this one appears: The message that appears when the video topic does not match the avatar actor's preferences For the rules on real people and likeness in generated media, see [Licensing and commercial use](/account/commercial-use). ## Guides ### Get started with AI filmmaking Source: https://docs.invideo.io/guides/get-started-with-ai-filmmaking.md invideo puts the leading video, image, voice and music models next to a timeline editor. Start your first film with Agent Two. #### Introduction invideo puts the leading video, image, voice and music models next to a professional timeline editor, in the cloud. Tell it what you want to make, a film, a brand campaign, a microdrama series, a performance ad, and Agent Two, invideo's own agent, takes it from script to final cut, using those models to write, storyboard, generate and edit every shot. You describe what you want and Agent Two works out the rest. It's not a template tool. It's not a one-shot generator. It's a back-and-forth creative process where Agent Two learns your vision, your tone, your style, your audience, and gets sharper with every exchange. The more context you give it, the better it gets. #### How do I get started? Go to the prompt page, where Agent mode is selected by default. Type your idea, whether it’s a script, concept, or scene, and Agent Two takes it from there. Start at invideo. To use an outside agent, such as Claude or ChatGPT, see [invideo for AI agents](/agents). ### How do I turn review comments into clear instructions for Agent Two? Source: https://docs.invideo.io/guides/how-do-i-turn-review-comments-into-clear-instructions-for-the-editing-agent.md Use the timecode, requested change and creative intent to guide a revision. Use each review note to identify where the change belongs, what should change and what should stay. invideo Editor supports timestamped review feedback. Agent Two reads the review comments on the timeline itself. Ask it to work through them, or copy a note with its timecode into your prompt when you want to change only that one. Agent Two, invideo's own agent, then changes that part of the timeline. A review page comparing two cuts, with a comment at 00:00:05:20 saying 'Need the background to be darker' Resolve conflicting feedback before briefing the revision. For example, decide which pacing request takes priority if two reviewers disagree about the same passage. After Agent Two makes changes, check the affected section in context. Reviewers need an invideo account to leave comments. A public review link lets people watch and comment. It does not let them edit. See [Security and data](/account/security-and-data). ### How to create a first cut from raw footage in invideo Editor Source: https://docs.invideo.io/guides/how-to-create-a-first-cut-from-raw-footage-in-invideo-editor.md Ask Agent Two to assemble your footage into an editable first cut, then refine it on the timeline. Agent Two, the agent in invideo Editor, reviews your footage and assembles a first cut. You can provide a script or describe the sequence you want, then adjust the resulting clips yourself. 1. Open invideo Editor and upload your footage through **Media**. 2. Give the agent your brief and any script or references. 3. Describe the desired length, opening, ending and details to preserve. 4. Review the cut in the **Monitor** and on the timeline. 5. Trim or rearrange clips manually, or request a specific revision. **Example:** *“Create a 60-second first cut from these interview clips. Keep the answers in order, remove false starts and finish with the product demonstration.”* Your own trims and edits on the timeline are free. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. An outside agent's own chat, such as Claude or ChatGPT, runs on that app's plan. See [Credits](/account/credits). ### How to make AI fashion ads using AI agents (full guide and cost) Source: https://docs.invideo.io/guides/how-to-make-ai-fashion-ads-using-ai-agents-full-guide-cost.md A video walkthrough of making AI fashion ads with invideo agents: product films, UGC ads and behind-the-scenes studio shoots. ### Masterclass: how to use AI agents to make brand films Source: https://docs.invideo.io/guides/masterclass-how-to-use-ai-agents-to-make-brand-films.md A video masterclass on making a consistent brand film on invideo with an agent, from the first concept to the final cut. Most AI brand films have inconsistent characters, drifting environments, generic shots stitched together. The fix for that is an AI agent that holds your entire film in memory and collaborates with you the way a real DP would. This masterclass breaks down the step-by-step process behind a short brand film made on invideo, from the initial concept to the final cut. The video shows how to direct an AI agent like a filmmaker, lock characters and environments, generate consistent shots across an entire film, and review your cut with the agent acting as your collaborator. #### Reference video ### How can I make uneven dialogue levels more consistent? Source: https://docs.invideo.io/guides/how-can-i-make-uneven-dialogue-levels-more-consistent.md Use compression to manage changes between louder and quieter speech. A compressor reduces the difference between louder and quieter parts of an audio signal. invideo Editor includes **Compressor** (`compressor`) in **Effects**, under **Audio**. Use it when a speaker’s level varies and moving the track fader does not solve the variation. The Compressor effect with the Voice Natural preset and Threshold, Ratio, Attack and Release sliders Start with a sensible overall dialogue level, then listen to both soft and emphatic lines as you adjust the compression. Aim for speech that remains expressive and easy to follow. Check it with the music and effects playing too. Heavy compression can make breathing or background sound more noticeable. ### How can I use EQ to reduce muddy or harsh dialogue? Source: https://docs.invideo.io/guides/how-can-i-use-eq-to-reduce-muddy-or-harsh-dialogue.md Make targeted tonal adjustments with Parametric EQ 8. Use **Parametric EQ 8** (`eq`) in invideo Editor, in **Effects**, under **Audio**, to change set frequency ranges in the sound. For a quick voice fix, try **Voice EQ** (`voice_eq`) first. It cuts rumble and adds clarity. EQ changes tonal balance, so it can help when a recording sounds boomy, boxy or overly sharp. The Parametric EQ 8 effect showing its frequency curve and a table of bands with Freq, Gain and Q values Identify what you hear, make a small adjustment and listen again. Avoid using one fixed setting for every speaker or microphone. Keep the voice recognizable and check it against the music. If the problem is uneven volume across words, compression may be more relevant than further EQ. ### How do I reduce harsh “s” sounds in dialogue? Source: https://docs.invideo.io/guides/how-do-i-reduce-harsh-s-sounds-in-dialogue.md Use the De-Esser to target excessive sibilance while preserving clear speech. Try the **De-Esser** (`de_esser`) in invideo Editor, in **Effects**, under **Audio**. De-essing targets excessive sibilance: the sharp “s” and similar sounds that can stand out in speech. The De-Esser effect with the Voiceover Natural preset and Threshold, Frequency and Max reduction sliders The Advanced section of the De-Esser with Ratio, Knee, Attack, Hold and Release sliders and Stereo link Listen to a passage containing both sibilant words and ordinary dialogue while adjusting the treatment. Reduce the harshness without making speech dull or altering the speaker’s articulation. Check the result at a comparable listening level and in the full mix. The useful amount depends on the voice and recording. ### How do I reduce unwanted clicks in an audio recording? Source: https://docs.invideo.io/guides/how-do-i-reduce-unwanted-clicks-in-an-audio-recording.md Try Click Remover on brief clicks and review the effect on the surrounding sound. invideo Editor has **Click Remover** (`click_remover`) in **Effects**, under **Audio**. It removes lip smacks and mouth clicks from a voice. Listen closely to the words around each click after you apply it. The Click Remover effect set to Normal, with the Amount slider and the message 'No clicks found.' Use only as much treatment as the recording needs. Sounds with sharp attacks can resemble clicks, so check that the processing has not softened intentional detail. If a recording remains distracting, compare an alternate take when one is available. Click removal is a different task from reducing a continuous background hum or room ambience. For hum, hiss or room noise, see [Clean up the dialogue and keep the original](/how-to/film/dialogue-cleanup). ### How is export loudness different from track volume and peak level? Source: https://docs.invideo.io/guides/how-is-export-loudness-different-from-track-volume-and-peak-level.md Separate the balance of the mix from the level of the delivered audio. Track volume controls how elements sit against one another in the mix. Peak level concerns the highest signal levels, while loudness describes the level over time in a way intended to relate more closely to perception. The Audio only export settings with an arrow pointing at the Loudness target of -14 LUFS invideo Editor includes mixer metering and a Loudness target in Export (`target_lufs` on `export`). Balance dialogue, music and effects first, then choose delivery settings for your destination. A loudness target cannot by itself fix dialogue that is masked by music. Listen to the exported file as a final check. ### How to add AI sound design to a video in invideo Editor Source: https://docs.invideo.io/guides/how-to-add-ai-sound-design-to-a-video-in-invideo-editor.md Describe the sound you want, review the agent’s work and refine it on your timeline. In invideo Editor, you can ask Agent Two, invideo's own agent, to find or generate sounds and arrange them around your video. The resulting sound layers remain editable, so you can refine them through conversation or make manual adjustments. To make a sound, the agent uses a sound model. A good pick is `elevenlabs_sfx` for a sound from words, or `pixverse_sfx` for a sound that matches a clip. The agent can search for others with `find_models`, and it prices each sound with a dry run first. Models retire. If a model is not found, your agent runs `find_models` with the job in words, uses the best match, and tells you. See [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects). #### 1. Start with your video Open the timeline you want to work on. You can use your own footage or a video you have already edited. #### 2. Describe the result you want Use the agent panel to explain the mood, the moments that need sound and anything you want preserved. **Suggested example prompt**: *'Add restrained sound design to this product video. Use soft clicks for the interface movements and a stronger impact when the logo appears. Keep the existing visual edit unchanged.'* The agent chat box with the example sound design prompt typed in #### 3. Listen and review Play the timeline and inspect the sounds added to the timeline. Check whether effects land at the intended moments and whether dialogue remains clear. #### 4. Ask for a specific change Describe the sound and the adjustment you want: “*Make the clicks quieter and shorten the impact on the logo.*” You can also upload your own sound effects and direct the agent to use them. #### 5. Refine the mix manually Select **Audio** and use the **Audio Track Mixer** to adjust track levels. Use solo (`set_audio_solo`) to hear a track separately, then listen to everything together again. #### Does AI sound design use credits? Your own edits and mixing on the timeline are free. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. An outside agent's own chat, such as Claude or ChatGPT, runs on that app's plan. See [Credits](/account/credits). ### What is audio ducking and when would I use Ducker? Source: https://docs.invideo.io/guides/what-is-audio-ducking-and-when-would-i-use-ducker.md Create space for dialogue by reducing competing audio during speech. Ducking reduces one sound while another needs attention, commonly lowering background music during dialogue. invideo Editor includes an effect named **Ducker** (`ducker`) in **Effects**, under **Audio**. The ducker reacts to the track set by `set_sidechain_source`. On a new timeline that is `A1`, the voice track. If your voice is on another track, your agent points `set_sidechain_source` at it, then adds `ducker` to the music track with `add_audio_effect`. Set how far the music drops with the ducker's `reduction`. The Ducker effect with the Normal preset, a gain reduction curve and Reduction, Attack, Hold and Release sliders The creative goal is clear speech with a musical bed that still feels continuous. You can also ask your agent to lower music under dialogue and review the result on the timeline. Listen to the start and end of sentences so changes in level do not feel abrupt. ### When should I add reverb to a sound in my edit? Source: https://docs.invideo.io/guides/when-should-i-add-reverb-to-a-sound-in-my-edit.md Use reverb to suggest space without hiding the timing or clarity of the sound. Reverb adds a sense of reflections and space around a sound. invideo Editor’s audio-effect list includes **Plate Reverb** (`plate_reverb`) and **Verb One** (`voice_reverb`), a one-knob plate reverb for voice. Consider reverb when a sound feels too dry or disconnected from the environment or creative treatment. The Plate Reverb effect showing a 3.7 second tail with Regen, Input Pad and Wetness sliders The Verb One effect showing a 3 second tail and a single Amount slider Listen to the tail after the sound ends and how it overlaps with the next moment. Keep dialogue understandable and avoid allowing a large tail to obscure a cut or musical accent. Adding reverb is not a way to remove room echo already present in a recording. To reduce room echo, see [Clean up the dialogue and keep the original](/how-to/film/dialogue-cleanup). ### When should I use a limiter rather than a compressor? Source: https://docs.invideo.io/guides/when-should-i-use-a-limiter-rather-than-a-compressor.md Distinguish peak control from shaping the dynamics of a performance. Use compression to manage the range between louder and quieter passages. Use limiting when you need to constrain peaks. invideo Editor includes both **Compressor** (`compressor`) and **Limiter** (`limiter`) in **Effects**, under **Audio**. Set the limiter's `ceiling` for delivery. The Limiter effect with the Master Safety preset and the Ceiling slider set to -1.0 dBTP Set the mix balance first, then listen to its loudest moments. A limiter can control peaks, but excessive limiting can reduce impact or introduce audible distortion. It cannot restore detail that was already lost in a clipped source recording. Check the delivered file as well as the timeline mix. ### How do I choose a transition that fits the cut in invideo Editor? Source: https://docs.invideo.io/guides/how-do-i-choose-a-transition-that-fits-the-cut-in-invideo-editor.md Pick a transition for the reason of the cut, then judge it against the rhythm of your edit. Start with the reason for the transition: connecting two moments, signaling a change or adding emphasis. invideo Editor has a library of transitions, and your agent adds one to a cut with `add_transition`. Preview a candidate with the outgoing shot, incoming shot and audio together. The Transitions tab with an arrow pointing at it, showing transition previews grouped into categories A fast treatment can overwhelm a quiet scene, while a long transition can slow down an otherwise tight sequence. Keep recurring transitions consistent when they serve the same purpose. If you brief the agent, identify the two shots and the feeling you want at their join, then review the result on the timeline. ### How do I keep typography consistent across a video in invideo Editor? Source: https://docs.invideo.io/guides/how-do-i-keep-typography-consistent-across-a-video-in-invideo-editor.md Build a clear text hierarchy with a small set of fonts. Choose a small, consistent set of type treatments for titles, supporting text and captions. invideo Editor has a large font library, and you can bring your own font file. A clear hierarchy matters more than the number of fonts. The Fonts tab with an arrow pointing at it, showing a grid of font samples Decide which treatment belongs to each role and apply that choice throughout the edit. Check letter shapes at the intended viewing size, particularly for names, numbers and short captions. When you brief your agent, specify the font and the text role you want it used for. Review the resulting text on the timeline for consistency. ### How do I make titles readable over busy footage? Source: https://docs.invideo.io/guides/how-do-i-make-titles-readable-over-busy-footage.md Balance contrast, placement and screen time so viewers can read the message. Review the title over the busiest and brightest moments of the shot, not only one still frame. Choose a clear font, give the text enough contrast and place it where it does not compete with the main subject. Allow enough screen time for the full message to be read. If you animate the text in invideo Editor, keep the entry and exit brief enough to leave a useful reading interval. Check the result at the size your audience will actually watch, especially for mobile delivery. ### How to create the Hail Mary effect in invideo Editor Source: https://docs.invideo.io/guides/how-to-create-the-hail-mary-effect-in-invideo-editor.md Create directional light trails on your footage with help from Agent Two. The Hail Mary effect stretches bright areas of a video into soft trails. You can work with Agent Two, the agent in invideo Editor, to create this look on your footage and refine the result. The effect library has no preset for this look. Your agent can write it as a custom effect with `add_custom_effect`, after it reads the `custom_shader` guide in `timeline_catalog`. You then change its settings like any effect. The Monitor playing the effect, moving from a hand out of a car window to a car on a road under bright light streaks #### 1. Open your footage Open your project and choose the clip you want to work on. #### 2. Provide a visual reference Attach a video showing the effect you want. Explain which part of the reference you want applied to your clip. #### 3. Describe the look you want Tell the agent how pronounced the trails should be and which direction they should follow. Mention anything you want to preserve, such as your existing color treatment. **Suggested prompt:** '*Use this reference video to add a Hail Mary effect to my clip. Create soft light trails from the brightest areas, extending in one direction. Keep my existing color treatment and make the effect subtle.*' #### 4. Review and refine Play the edited clip and check how the effect looks across the shot. Ask for adjustments to the trails, or use the available effect controls to refine the result. #### Does this generate a new video? This workflow applies a visual effect to your existing footage. It does not require generating replacement footage. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. An outside agent's own chat, such as Claude or ChatGPT, runs on that app's plan. See [Credits](/account/credits). ### When should I use a title instead of word-by-word captions? Source: https://docs.invideo.io/guides/when-should-i-use-a-title-instead-of-dynamic-captions.md Give editorial labels and spoken words different jobs in the edit. Use titles for information such as a person’s name, a section heading, a key point or a call to action. Use captions to represent speech. Word-by-word captions add visual movement or emphasis to that text. invideo Editor supports titles and word-by-word captions on the timeline. See [Add word-by-word captions](/how-to/creators/word-by-word-captions). Keep their roles distinct so viewers can follow the speaker while understanding the extra information. Check wording, timing and spelling, and avoid placing a title where it competes with the captions. Use restrained animation when the audience needs to read several things at once. ### When should I use a video effect instead of generating a new shot? Source: https://docs.invideo.io/guides/when-should-i-use-a-video-effect-instead-of-generating-a-new-shot.md Choose a timeline treatment when you want to change the look of footage you already have. Use a timeline effect when the existing shot already contains the action you need and you want to change how it looks. Generate a new shot when you need new visual content. invideo Editor has a library of video effects, and your agent adds one to a clip with `add_effect`. The Effects tab scrolling through effect previews grouped into Blur and Sharpen, Color Correction and Distort Start with the intended result: a visual treatment on the same performance, or a different shot altogether. You can animate supported effect parameters with keyframes. Adding and changing an effect yourself is free. Agent Two's work and the media it makes use credits. An outside agent edits for free and pays only for generation, transcripts and paid stock. An outside agent's own chat, such as Claude or ChatGPT, runs on that app's plan. Before a paid call, the agent runs a dry run and tells you the price. See [Credits](/account/credits). ### How should I choose a LUT for my footage in invideo Editor? Source: https://docs.invideo.io/guides/how-should-i-choose-a-lut-for-my-footage-in-invideo-editor.md Use a LUT as a starting point, then judge the result shot by shot. A LUT maps input color values to output values. invideo Editor has LUTs next to manual color controls, and you can bring your own .cube file. Your agent applies one with `apply_lut`. Choose a look that supports your scene and review it on representative shots before applying it widely. The LUTs tab with an arrow pointing at it, showing Add LUT and a grid of LUT previews A LUT does not remove the need to assess exposure, color balance and continuity. Footage recorded under different lighting may still need individual corrections. Compare faces, neutral objects and important product colors across the sequence, and refine the grade until the shots work together. ### What should I adjust when a LUT makes my shot look too strong? Source: https://docs.invideo.io/guides/what-should-i-adjust-when-a-lut-makes-my-shot-look-too-strong.md Reduce the LUT’s strength and reassess the underlying color balance. Reduce the LUT strength in invideo Editor (`strength` on `apply_lut`, from 0 to 1), then review exposure, contrast and color balance. Compare several moments in the shot. If the look works on one clip but overwhelms another, refine that shot individually. Check faces and important product colors before deciding that the grade is finished.