Generate a Storyboard Shot List Template
A useful storyboard starts with decisions, not empty boxes. This generator turns a scene description and your chosen number of shots into a practical shot list template that can guide planning, drawing, filming, or review.
Run — free
Every row includes a numbered shot, a suggested shot type, a duration estimate, and a description tied directly to the scene. The result is deterministic, so the same brief produces the same plan whenever a team needs to revisit or compare it.
Start with a scene description that contains visible beats
Describe what the audience can see, where the action happens, who or what matters, and how the scene changes. A useful brief might identify an entrance, a discovery, a reaction, and an exit rather than providing only a theme such as “a tense morning.” The generator normalizes spacing and divides the description into narrative beats using sentence boundaries. If the description is a single sentence, it can also use punctuation and transition words to find smaller clauses. Those beats anchor the descriptions in the resulting list, which means the tool rearranges and frames supplied material instead of inventing characters, props, or events. Choose the shot count according to the planning detail you need. A short insert may need three shots, while a scene with several actions may need eight or twelve. The count is exact: request six shots and the output contains six rows. At least one shot is required, and bounded inputs keep the result readable and safe to run in a browser or automated workflow.
Read each row as a production planning prompt
Every generated row has four operational fields. The shot number preserves order. The shot type suggests framing, beginning with an establishing wide view and moving through medium views, close-ups, over-the-shoulder coverage, detail inserts, reactions, and wider reorientation as the list grows. The duration estimate is expressed in whole seconds and is based on framing plus the length of the assigned beat. It is a starting point for pacing, not a promise about the final cut. The description combines a visual purpose with a beat taken from the scene, so an artist or camera team can understand why the shot exists as well as what it covers. When you request more rows than there are distinct beats, the algorithm cycles through those beats and marks later passes as alternate visual emphasis. That choice makes repetition visible and useful: the list asks for additional coverage without silently adding plot details that were never present in the brief. Review the suggestions, then adjust lens, movement, angle, and timing for your production style.
Use the template consistently across preproduction workflows
The structured result works as a neutral handoff between writing, storyboarding, cinematography, editing, animation, and client review. Paste the rows into a production document, convert each description into a storyboard panel, or map them into tasks for artists and camera crews. Because generation is deterministic and uses no model or network request, teams can regenerate a list during automated intake and receive exactly the same structure for the same input. That stability is helpful when comparing revisions: change the scene description or count intentionally, then inspect how the plan changes. The estimated total duration is the sum of all row estimates, making it easy to spot a plan that is broadly too long or too short before detailed timing begins. Treat that total as a conversation starter. Performance, dialogue, transitions, camera movement, and editorial rhythm can all change real screen time. The tool provides a disciplined first pass, while creative and safety decisions remain with the production team. API use costs $0.002 per request, and the browser version can run the same pure logic locally.
What you can do with it
Plan a short narrative scene
Convert a sequence of visible actions into an ordered coverage template before drawing panels or preparing a camera plan.
Brief an animation team
Give storyboard artists a consistent set of numbered frames, suggested framing, timing, and scene-linked intent.
Standardize video intake
Turn client scene briefs into predictable records that producers can review, edit, and transfer into production tools.
FAQ
What does one request cost?
An API request costs $0.002. The browser runner uses the same deterministic logic locally.
Does the generator create storyboard images?
No. It creates a textual shot list template that can guide storyboard drawings, camera planning, or animation layout.
Is the requested shot count exact?
Yes. The output contains exactly the requested number of shots. Counts below one or above the published limit are rejected.
How are duration estimates calculated?
Each estimate uses a stable base for the suggested shot type and a small adjustment for longer scene beats. It is intended for early planning.
Will it invent action that is missing from my scene?
No. Descriptions are anchored to text from your scene. Extra coverage repeats a beat with an explicit alternate-emphasis note.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/video/storyboard-shot-list \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"scene_description":"At dawn, a cyclist enters an empty town square. She notices a red scarf tied to the fountain, stops, and looks toward the bell tower as the first bell rings.","shot_count":5}'const res = await fetch("https://api.kit.forhosting.com/video/storyboard-shot-list", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"scene_description": "At dawn, a cyclist enters an empty town square. She notices a red scarf tied to the fountain, stops, and looks toward the bell tower as the first bell rings.",
"shot_count": 5
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/video/storyboard-shot-list",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"scene_description": "At dawn, a cyclist enters an empty town square. She notices a red scarf tied to the fountain, stops, and looks toward the bell tower as the first bell rings.",
"shot_count": 5
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/video/storyboard-shot-list", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"scene_description":"At dawn, a cyclist enters an empty town square. She notices a red scarf tied to the fountain, stops, and looks toward the bell tower as the first bell rings.","shot_count":5}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"scene_description":"At dawn, a cyclist enters an empty town square. She notices a red scarf tied to the fountain, stops, and looks toward the bell tower as the first bell rings.","shot_count":5}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/video/storyboard-shot-list", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"scene_description": "At dawn, a cyclist enters an empty town square. She notices a red scarf tied to the fountain, stops, and looks toward the bell tower as the first bell rings.",
"shot_count": 5
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "video.storyboard_shot_list",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_chars | 10000 |
max_shots | 100 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |