---
name: eggapi-short-film
description: Make 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 视频、故事视频).
---

# Short film from idea to cut

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 into `eggapi-output/<project>/` under the current directory with `curl -sSL -o <file> <url>`, keeping the extension from the URL and using 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.
