From script to final cut
A script and shot list, character sheets that keep faces consistent, one rendered clip per shot, and the final cut joined with ffmpeg.
Make a 40-second vertical film: a cat finds its way home through rainy Tokyo
when the agent picks itMake a short film with EggAPI, from an idea to a script and shot list, consistent characters and style frames, one rendered clip per shot, and a final cut assembled with ffmpeg. Use when the user wants a short film, AI film, story video, short drama episode, music video, trailer, animated short or any multi-shot video with consistent characters (短片、短剧、分镜、AI 视频、故事视频).
Video models render 4-15 seconds per clip, so a film is a sequence of shots. Work in stages and get approval at each one: images are cheap to redo, video is not. Reply in the user's language. Write model prompts in English; put any text that should appear in an image in quotes, in its target language.
EggAPI basics
This skill uses the EggAPI MCP server, usually added under the name eggapi: list_models, generate_image, generate_video and get_task (in Claude Code they show up as mcp__eggapi__*). If these tools are missing, stop and send the user to https://eggapi.ai/connect to add the server.
-
Models. Call
list_modelsonce at the start. Use the model IDs this skill names when they are listed; otherwise pick the closest model with the samegeneration_type.unit_price_usdis the price per image, or per second of video;unit_price_by_resolutionoverrides it for a givenresolution. -
Local files. The generate tools only accept public
http(s)URLs. Upload local files first (up to 20 MB per image):bashcurl -sS https://api.eggapi.ai/v1/uploads \ -H "Authorization: Bearer $EGGAPI_API_KEY" \ -F "files[]=@./photo-1.jpg" -F "files[]=@./photo-2.jpg"
The URLs are in
data.files[].url. IfEGGAPI_API_KEYis empty in the shell, ask the user to export it; never ask for the key in the chat. Uploaded files can be opened by anyone who has the URL, so say so before uploading anything private. -
Tasks are async.
generate_imageandgenerate_videoreturn atask_idat once. Submit every independent task first, then pollget_taskfor each untildoneis true: every 5-10 s for images, 10-15 s for videos (usually 1-3 min). If a generate call already returnsurls, no polling is needed. -
Always pass
aspect_ratio(the default is 16:9) and, for video,duration(4-15 s). Supported ratios:1:1,3:4,4:3,9:16,16:9,21:9. -
Edit models return one image per call. For more variants, call again;
num_outputsonly applies to text-to-image models. -
Output URLs work as inputs. Pass a finished image's URL straight into the next edit or video call; no re-upload needed.
-
Save everything. Download each output as soon as its task completes, into
eggapi-output/<project>/under the current directory, withcurl -sSL -o <file> <url>: some output links expire after 24 hours, and some file hosts reject other HTTP clients. Keep the extension from the URL and use descriptive file names. -
Cost. Show the plan with an estimated cost before generating and wait for a go-ahead, unless the user already said to go ahead. At the end, report each task's
costand the total. -
Errors.
insufficient balance: ask the user to top up at https://eggapi.ai/dashboard.temporarily unavailable: switch to another model of the same type. Afailedtask: readerror, adjust the prompt if it points at the content, and retry once.
1. Script and shot list
Ask only for what is missing:
- The story: an idea, a script, or a song for a music video.
- Length: default 30-60 seconds.
- Format:
9:16for Douyin, TikTok, Reels and Shorts;16:9for YouTube;21:9for a cinematic look. - Look: live action, anime, 3D animation, claymation, a specific era or film style.
- Sound: none, model-generated sound, or music the user adds later.
Write a short script, then a shot list table: shot number, duration (4-15 s), framing (wide, medium, close-up), what happens, camera movement, characters, sound or dialogue. Keep one action per shot; 6-8 shots of about 5 seconds make a 40-second film.
Estimate the cost: the total seconds x the video model's price per second at the chosen resolution, plus one image per character sheet, style frame and keyframe. Wait for approval of the shot list.
2. Characters and style
Consistency comes from reference images, not from repeating a description in every prompt.
- Character sheet for each main character, with
generate_image, modelgoogle/nano-banana-pro/text-to-image,aspect_ratio: "16:9": "Character reference sheet of {description}: front view, side view and full body, neutral grey background, {look}." If the user has photos or artwork of a character, upload those and use them instead. - Style frame: one image in the film's ratio that sets the lighting, color palette and era.
Show them and get approval. Keep the URLs: they are the references for every shot.
3. Keyframes
Create the first frame of every shot with an edit model, passing the character sheets of the characters in that shot and the style frame as images. Model google/nano-banana-pro/edit, alternative bytedance/seedream-v5.0-pro/edit (both up to 8 input images). Use the film's aspect_ratio and resolution: "2k".
{What the shot shows}. The characters look exactly like in the reference sheets. Same look as the style frame. {Framing}, {camera angle}.
Submit all keyframes together and review them with the user before any video is rendered; redo any frame where a character drifted.
4. Render the shots
For each shot, call generate_video with:
model:bytedance/seedance-2.5/image-to-video; alternativealibaba/wan-3.0/image-to-video. Use the same model,resolutionandaspect_ratiofor every shot so the clips join cleanly.image: the shot's keyframe URL.duration: the shot's duration.resolution:720pfor a draft cut,1080pfor the final.prompt: only the motion and the camera, not the whole scene again: "She turns toward the window as the wind lifts her hair, slow push-in."- To make a shot end on a chosen frame, for example to match the next shot, pass that image as
parameters: {"last_image": "<url>"}. - Sound: set
parameters: {"generate_audio": true}on every shot or on none, so the clips join cleanly.
Render one shot first as a test. Once the user likes it, submit all remaining shots together, then poll them.
5. Assemble the cut
Download the clips as shot-01.mp4, shot-02.mp4 and so on. If ffmpeg is installed, join them:
cd eggapi-output/<film-slug> printf "file '%s'\n" shot-*.mp4 > shots.txt ffmpeg -f concat -safe 0 -i shots.txt -c copy film.mp4
If that fails because the clips differ, re-encode instead:
ffmpeg -f concat -safe 0 -i shots.txt -c:v libx264 -crf 18 -pix_fmt yuv420p -c:a aac film.mp4
To lay the user's music under the cut:
ffmpeg -i film.mp4 -i music.mp3 -map 0:v -map 1:a -c:v copy -shortest film-music.mp4
Without ffmpeg, deliver the numbered clips and tell the user how to install it (brew install ffmpeg on macOS, sudo apt install ffmpeg on Debian or Ubuntu).
6. Revise and deliver
Re-render only the shots the user wants changed, reusing the approved keyframes, then assemble again. Deliver eggapi-output/<film-slug>/ with the script, the shot list, the keyframes, every clip and the final cut, and report each shot's cost and the total.
Edit your copy of this file to change the steps, defaults or models; the agent follows your version.