Seedance CLI — ByteDance Seedance 2.0 from Your Terminal
Generate AI video with text, images, and reference footage. One Rust binary. No MCP server required.
Pay-per-second video generation from ByteDance, wrapped in a tool agents can actually drive. JSON on pipe, human-readable on TTY, semantic exit codes, one static binary.
Install · API Key Setup · Quick Start · Reference Inputs · Companion Tools · Known Quirks · Commands
Why this exists
Seedance 2.0 produces strong 480p and 720p output at a low per-second price. The ModelArk API that serves it wasn't built for scripts — auth is awkward, responses are verbose, and there is no single step from prompt to mp4 on disk. This CLI gives you that step, and keeps the output shape stable whether you're piping into jq or watching a progress bar.
Install
# Cargo (works everywhere Rust does)
# Homebrew (macOS + Linux)
# Prebuilt binary
# https://github.com/paperfoot/seedance-cli/releases/latest
API Key Setup
BytePlus is ByteDance's official international cloud. The model platform is ModelArk. Three minutes, start to finish:
- Go to console.byteplus.com/ark and sign in (free account, credit card needed for paid generation).
- Open the API Keys page from the left sidebar.
- Click Create API Key — copy the
ark-…string it shows you (it won't show again). - Hand it to the CLI in one of three ways, pick whatever fits:
# (a) Environment variable — best for CI
# ARK_API_KEY is also accepted
# (b) Config file — stored locally at chmod 600, never echoed back
# (c) Per-command flag — overrides everything else
Verify:
If anything's wrong, doctor tells you which step to revisit.
Quick Start
# -> ~/Documents/seedance/20260420T023015Z-abc12345.mp4
# -> ~/Documents/seedance/20260420T023015Z-abc12345.seedance.json # sidecar manifest
Default output is ~/Documents/seedance/. Override with -o /path/to/file.mp4 or -o /some/dir/, or use --label / --project to drive the default naming.
# -> ~/Documents/seedance/cafe-scene/20260420T023015Z-alice-walk-abc12345.mp4
# -> ~/Documents/seedance/cafe-scene/20260420T023015Z-alice-walk-abc12345.seedance.json
Every .seedance.json sidecar carries the full prompt, references, model, seed, duration, and task id — so agents can read the directory and know exactly which prompt produced which mp4 without guessing.
How it works
prompt + refs ModelArk queue mp4
| | ^
v v |
seedance gen -> task id returned -> seedance download
|
v
seedance status <id>
One task id from start to finish. Fire and forget, or pass --wait to block until the file lands on disk.
Reference Inputs
Seedance 2.0 accepts a free mix of references in a single content array:
| Flag | Kind | Limit | Notes |
|---|---|---|---|
--image / -i |
Image | 0–9 | Path (base64'd inline) or URL. Role: reference_image |
--first-frame |
Image | 1 | Role: first_frame |
--last-frame |
Image | 1 | Role: last_frame (requires --first-frame) |
--video / -v |
Video | 0–3 | URL only (API restriction). Total ≤ 15s |
--audio / -a |
Audio | 0–3 | wav/mp3. Path (base64'd) or URL. Total ≤ 15s. Needs an image or video alongside. |
Address references inside the prompt:
[Image 1] the boy waves; [Video 1] camera style; [Audio 1] background music
Use time codes for multi-shot: [0-4s]: wide establishing shot; [4-8s]: push in.
Supported resolutions: 480p, 720p. Supported ratios: 16:9, 4:3, 1:1, 3:4, 9:16, 21:9, adaptive. Duration: 4–15s or -1 for auto.
Examples
# Text-to-video, wait and download
# Multimodal reference-to-video with the fast tier
# Fire and forget, poll later
TASK=
Companion Tools
Four helpers ship in the same binary, built to work around specific Seedance limits. Each one chains cleanly into generate.
| Tool | What it does |
|---|---|
seedance character-sheet --character N |
Builds a 9-angle (or 4-angle) sheet from a single photo via Nano Banana Pro. Pass the resulting PNG to --image to keep one person consistent across shots. For multi-character scenes, run this once per person with distinct --character names and pass every sheet as a separate --image. |
seedance audio-to-video |
Wraps an audio file in a silent mp4 (ffmpeg under the hood) so you can pass it as --video instead of --audio. Preserves lyrics exactly. --upload hosts the file on tmpfiles.org and prints the URL. |
seedance prep-face |
Applies an empirically verified grain + desaturation recipe so a real portrait clears ModelArk's face filter. --bw swaps to the pure grayscale variant. |
seedance upload <file> |
Uploads a local file to tmpfiles.org and prints a direct-download URL, ready to paste into --video. |
Multi-character scenes
Cap scenes at two characters. Three or more in the same shot breaks identity lock — Seedance starts morphing faces across frames. For three-person scenes, split into two shots and intercut in post.
# One sheet per character, shared project folder
# Generate with both sheets; each gets an explicit job in the prompt
Prompting principles
Seedance reads prompts literally. Do not rely on logic or genre shorthand — describe everything you need to see.
- Every reference must have an explicit job in the prompt. Unnamed refs are silently dropped.
- One verb per shot. Split multi-action scenes with time codes:
[0-4s]: ...; [4-9s]: .... - Negative prompts do not work. Phrase positively: "eyes natural, soft eye contact, blinks occasionally" beats "no weird eyes".
- Early tokens dominate. Put camera language, subject, and style in the first half of the prompt.
- Prompt length: 30–200 words. Too short underspecifies; too long causes detail dropout.
- Describe wardrobe, lighting, and setting concretely even when it's visible in a reference — these drift more than faces do.
For deeper prompt recipes (UGC vs marketing vs cinematic templates, chaining scenes into longer films, voice cloning workflows), see the seedance-prompting skill.
Known Quirks
Hard-won notes from real users, saved so you don't hit the same walls:
- Audio upload mutates lyrics. Reported by @MrDavids1 and @simeonnz: uploading audio directly alters the song. Workaround —
seedance audio-to-video song.mp3 --upload, then pass the printed URL as--video. The API trusts reference videos for audio content but post-processes raw audio. - No real human faces in references. ModelArk blocks direct upload of real human portraits. Either run the photo through
seedance prep-facefirst, or build acharacter-sheetfrom one photo and use that. - Videos must be URLs. Host the file first (S3, Cloudinary, or
seedance upload→ tmpfiles.org) and pass the URL. Local files are rejected by the API. - No 1080p. Seedance 2.0 tops out at 720p. Use
--resolution 720p—1080preturns an error.
Commands
| Command | Purpose |
|---|---|
seedance generate / gen |
Create a video generation task |
seedance status <id> / get |
Poll a task |
seedance download <id> |
Download the mp4 for a completed task |
seedance cancel <id> / rm |
Cancel a queued task |
seedance character-sheet <photo> |
Build a consistent-character reference grid |
seedance audio-to-video <file> |
Wrap audio in silent mp4 (lyrics workaround) |
seedance prep-face <photo> |
Prepare a portrait to pass the face filter |
seedance upload <file> |
Host a local file and print a public URL |
seedance models / ls |
List available model ids |
seedance doctor |
Check API key, base URL, and deps |
seedance agent-info / info |
Machine-readable capability manifest |
seedance skill install |
Deploy SKILL.md to Claude, Codex, or Gemini |
seedance config show / path / set / unset |
Manage the TOML config |
seedance update [--check] |
Self-update from GitHub Releases |
Global flags: --json (force JSON), --quiet (suppress info), --help, --version.
Exit codes
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Transient (network, API, IO, update) — retry |
2 |
Config (missing API key, bad base URL) — fix setup |
3 |
Invalid input — fix arguments |
4 |
Rate limited — wait and retry |
Every error also prints a machine-readable error_code and a literal recovery suggestion when you're in --json mode.
Built with
- agent-cli-framework — the scaffolding every paperfoot CLI is built on.
Contributing
PRs and issues welcome. See CONTRIBUTING.md for the short version.
License
MIT — see LICENSE.
Built by Boris Djordjevic at Paperfoot AI
If this saved you time: