Docs
Images and clips
How to use your own pictures and AI-made images and clips, and how to put a presenter next to your product.
How do I use my own images?
Put the files in the project’s assets folder and draw them with s.image:
s.image("assets/dashboard.png", {
w: 1100,
frame: "browser",
url: "app.example.com",
at: "dashboard",
});
s.image("assets/phone.png", { h: 800, frame: "phone", at: 0.5 });
PNG, JPEG, WebP, GIF and SVG files work. The frames browser, window and phone put a screenshot inside a drawn browser, window or phone. card puts a white border around a picture. kenburns: true adds a slow zoom.
For a live website, capture can save screenshots and brand details for you. See product demos. For video files, use s.clip from the scene reference.
When do AI images help?
Icons and diagrams cover most technical topics. For everyday how-to topics, like cooking, cars or plants, a picture of the food, the car or the plant explains more. explainroo can make these pictures with AI image models through OpenRouter.
This is optional. It costs money on your OpenRouter account, about 7 to 13 cents per image at the time of writing.
How do I set it up?
You need an OpenRouter API key from openrouter.ai/keys. Then run this and paste the key when it asks:
npx --yes explainroo connect openrouter
connect tests the key and saves it in your settings folder, so every project can use it. Settings says where that is. The same key makes AI video clips. If you ask your agent for a video with images and there is no key, the agent runs connect and shows you what it prints.
How is an image made?
npx --yes explainroo image videos/jump-start cables "Two cars parked nose to nose with their hoods open, jumper cables between the batteries"
npx --yes explainroo images videos/jump-start
The first command saves assets/cables.png. The second lists all the images made for this project and what each one cost. The project’s history/ folder keeps a record of each purchase.
The same command again returns the same file and spends nothing. Changing the prompt or a setting makes a new image, and --new buys this one again. A purchase never deletes a file. The old assets/cables.png moves to history/replaced/, and asking for its request again brings it back for free.
| Option | What it does |
|---|---|
--model best |
OpenAI GPT Image 2, the default. It does what you ask. |
--model cheap |
Google Gemini 3.1 Flash Image. It costs about half, but often leaves out parts of the prompt. |
--aspect 16:9 |
the shape of the image: 16:9, 9:16, 1:1, 4:3, 3:4, 3:2 or 2:3. It follows the video by default. |
--ref assets/a.png |
sends an earlier image along, so a person or an object keeps the same look. Separate several files with commas. |
--no-style |
leaves out the default style |
Each image gets a default style. It is a flat illustration with soft colors, a plain light background and no text. You can set your own style for the whole video in video.json:
"images": { "model": "best", "style": "Watercolor illustration, warm colors, no text" }
Why does every image need a check?
Image models get details wrong. A hand gets six fingers, a cable goes on the wrong terminal, or a sign shows letters that look like words but are not. AGENTS.md tells the agent to open each image after making it. When something is wrong, the agent changes the prompt and makes the image again.
Two things help. Keep text out of images and put words on screen with s.text instead. And use one style for the whole video, so the pictures look like they belong together.
When do AI clips help?
explainroo clip buys a short video clip that an AI model makes from a sentence. It goes through OpenRouter on the same key as images, and the clip plays in a scene like your own footage. This is optional and costs money on your OpenRouter account.
Clips work for short shots of the real world, like a street or food. They can also set a mood between two ideas. They get readable text and numbers wrong. A diagram or a logo comes out close but wrong, and a viewer may believe it. Each clip is made on its own, so a person looks different in the next clip. Nothing inside a clip follows the voice. When the content must be right, use drawings and screenshots instead.
How do I make an AI video clip?
See the price first. This spends nothing and needs no key:
npx --yes explainroo clip videos/street "A busy street at dusk in the rain" --seconds 6 --dry-run
It prints the price, with the model and the size it priced. Its Takes: line lists the lengths the model takes. The dry run also works before you have a project, if you leave out the project folder. explainroo services clips shows the price per second of the cheap and the quality model on the day you run it. On November 8, 2026, six silent seconds at 720p on the default model were priced at about 18 cents.
To buy the clip, set the most it may cost in US dollars:
npx --yes explainroo clip videos/street "A busy street at dusk in the rain" --seconds 6 --max-cost 0.50
When the price is above that, or can’t be worked out, clip stops before anything is sent. The price is an estimate. The final cost goes in the project’s record after the job, and clip says so when it came out higher. A failed try may cost money too.
The file lands in assets/clips/, and clip prints two lines to paste into scenes.js. One fills the whole frame, edge to edge. The other fills the free area inside the safe margins. A clip shorter than its scene holds its last frame, and speed: "fit" plays it slower or faster so it ends with the scene. See video clips.
| Option | What it does |
|---|---|
--seconds |
the length, one that the model takes. Required |
--max-cost |
the most this clip may cost, in US dollars. A purchase needs it, unless there is a budget |
--budget |
the most all clips of the project may cost together |
--dry-run |
shows the price and spends nothing |
--model |
cheap, the default, or quality. A full OpenRouter model id works too |
--aspect |
16:9 or 9:16. It follows the project’s frame |
--audio |
asks for sound. Sound is off by default, because s.clip plays silent and sound often costs more |
--name |
the file name. By default it is a short name from the prompt |
How do I set a budget for clips?
When you have one amount for all the clips of a video, put it in video.json:
"clipBudget": 0.40
--budget 0.40 on clip does the same and wins over video.json. Before each purchase, explainroo adds the most this clip may cost to what the clips in the project’s record already cost. When the sum would go over the budget, clip stops before anything is sent and says how much is left. With a budget, --max-cost is optional. A clip’s final cost can come out a little above its price, so all clips together can come out a little above the budget. The next dry run counts what each clip cost. clip --dry-run shows what is left and whether the clip fits.
What if a clip purchase stops halfway?
The project’s record has the job before the request goes out. explainroo never sends the same request a second time on its own, so running the same command again is safe. It picks up the job that is running and downloads the file, and that costs nothing more. When the file is already there, the command returns it.
When a request went out and no answer was saved, nobody can tell whether it went through. Then clip stops and says so, and your OpenRouter activity page shows what was charged. --new buys the clip again. explainroo history lists every clip with its file and cost, and the command that continues an open job. OpenRouter keeps a finished file only for a short time, so fetch it soon.
Your prompt goes to OpenRouter and to the company that runs the video model. Video jobs are not covered by OpenRouter’s zero data retention, because the provider keeps the result for a short time so that you can fetch it.
Can a presenter talk next to my product?
A presenter is a person on screen who talks next to the product. The free way is to film yourself saying the narration of a scene, with a camera or a phone. Put the file in assets/ and play it with s.clip, with volume: 1 so its sound plays.
explainroo can also play an AI presenter from a presenter service, paid per second at that service. No presenter service is built in yet. explainroo services presenters lists both choices, the free one first.
explainroo never makes a real person’s face or voice without the consent flow of the presenter service. That rule has no setting to turn it off. An avatar with a real person’s face needs that person’s verified consent. Narration from a recording is a real person’s voice, so it needs consent for the voice too. presenter refuses anything else before a request goes out, so a refusal costs nothing.
With a service you picked, explainroo presenter videos/dns intro --avatar ava --dry-run shows what goes out and what the clip costs. The presenter speaks the narration of one scene, so run voice first. --max-cost is the most the clip may cost. When the service gives no price for an avatar, presenter buys nothing. The clip is saved in assets/presenters/, and the same command never buys it twice.
s.presenter("intro") plays the clip next to the content, at the right of a wide frame and at the bottom of a tall one. It carries a small “AI presenter” label under it, and every package of the video gets the AI label. See the AI label.