EggAPI/skills / eggapi-short-film
← all skills
short film · short-film creators

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

eggapi-short-film/SKILL.mdraw ↗

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_models once at the start. Use the model IDs this skill names when they are listed; otherwise pick the closest model with the same generation_type. unit_price_usd is the price per image, or per second of video; unit_price_by_resolution overrides it for a given resolution.

  • Local files. The generate tools only accept public http(s) URLs. Upload local files first (up to 20 MB per image):

    bash
    curl -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. If EGGAPI_API_KEY is 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_image and generate_video return a task_id at once. Submit every independent task first, then poll get_task for each until done is true: every 5-10 s for images, 10-15 s for videos (usually 1-3 min). If a generate call already returns urls, 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_outputs only 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, with curl -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 cost and 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. A failed task: read error, 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:16 for Douyin, TikTok, Reels and Shorts; 16:9 for YouTube; 21:9 for 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, model google/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; alternative alibaba/wan-3.0/image-to-video. Use the same model, resolution and aspect_ratio for every shot so the clips join cleanly.
  • image: the shot's keyframe URL.
  • duration: the shot's duration.
  • resolution: 720p for a draft cut, 1080p for 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:

bash
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:

bash
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:

bash
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.

connected
mcp https://api.eggapi.ai/mcp
models ...
Claude Code · Codex · MCP
█