Six AI short-drama generators, read: the face is held by a reference sheet, and the bill is the video model
mdjsonmcp2026-10-11 · 28 min · video-generation · agents · multi-agent · image-generation · pricing · licensing
Why read this
Solidtop 85%Six short-drama repos read at source: how each holds a character's face, what a kept minute costs at list price, and the labels none of them write.
- Original analysis
- Widely used
- Concrete numbers to act on
Image & video generationAPI onlyMixed licencesPractitioner roundup
How this was scored
- Is it new?
- 1 of 3: An incremental tweak
- Can I trust it?
- 2 of 3: Measures key facts from files, code or configs
- Can I run it?
- 1 of 3: API-only, gated or restrictive licence
- Will I understand it?
- 2 of 3: Mechanism from first principles with figures
- Can I act on it?
- 2 of 3: A concrete recipe, numbers or comparison
- Will it last?
- 1 of 3: Relevant for months
- Does it affect many?
- 2 of 3: A widely used model, tool or lab release
- Only here?
- 2 of 3: A teardown or measurement few others did
Score 58 of 100, ranked 308 of 494 rated articles. Each question is answered 0–3 by hand, and a 3 is rare. How articles are scored
The post opens with its author topping up 100 yuan on a Douyin short drama, then lists six "high-star" GitHub projects that, it says, make a whole drama in one click, ready to post to short-video platforms and earn from. The replies are more useful than the post. One says they are all slop. One says the hard part is getting anyone to watch. And one asks the question I wanted answered: "这得要多少token" (how many tokens does this take?).
So I shallow-cloned all six and read them: the agents, the prompts, the provider adapters, the ffmpeg calls. I did not run any of them, and I called no paid API. I went in expecting six different inventions. What I found is one recipe, implemented six times with different amounts of care, and the recipe is mostly a way of steering ByteDance's Seedance.
- license
- CC-BY-NC-SA-4.0
- branch
- master
- tests
- 28 files
- source
- 1.0 MB
- commit date
- 2026-10-05
by size of tracked source at this commit, file counts in brackets; docs, data and vendored trees excluded
local clone, 2026-10-11 at 26de7df — branch, commit, commitDate, fileCount, hasTests, languages, license, licenseFile, shallow, testFileCount
shallow clone: counts describe the pinned tree, not the history
- license
- MIT
- branch
- master
- tests
- none found
- source
- 3.4 MB
- commit date
- 2026-10-09
by size of tracked source at this commit, file counts in brackets; docs, data and vendored trees excluded
local clone, 2026-10-11 at 2c7fb25 — branch, commit, commitDate, fileCount, hasTests, languages, license, licenseFile, shallow
shallow clone: counts describe the pinned tree, not the history
- license
- Apache-2.0
- branch
- main
- tests
- none found
- source
- 1.3 MB
- commit date
- 2026-06-14
by size of tracked source at this commit, file counts in brackets; docs, data and vendored trees excluded
local clone, 2026-10-11 at 848b054 — branch, commit, commitDate, fileCount, hasTests, languages, license, licenseFile, shallow
shallow clone: counts describe the pinned tree, not the history
- license
- Apache-2.0
- branch
- main
- tests
- 52 files
- source
- 2.8 MB
- commit date
- 2026-04-20
by size of tracked source at this commit, file counts in brackets; docs, data and vendored trees excluded
local clone, 2026-10-11 at a967819 — branch, commit, commitDate, fileCount, hasTests, languages, license, licenseFile, shallow, testFileCount
shallow clone: counts describe the pinned tree, not the history
- license
- custom
- branch
- main
- tests
- 109 files
- source
- 5.4 MB
- commit date
- 2026-09-21
by size of tracked source at this commit, file counts in brackets; docs, data and vendored trees excluded
local clone, 2026-10-11 at dfec20e — branch, commit, commitDate, fileCount, hasTests, languages, license, licenseFile, shallow, testFileCount
shallow clone: counts describe the pinned tree, not the history
- license
- MIT
- branch
- main
- tests
- 36 files
- source
- 919.8 kB
- commit date
- 2026-09-30
by size of tracked source at this commit, file counts in brackets; docs, data and vendored trees excluded
local clone, 2026-10-11 at fd4b72e — branch, commit, commitDate, fileCount, hasTests, languages, license, licenseFile, shallow, testFileCount
shallow clone: counts describe the pinned tree, not the history
Two of the links in the post now redirect. AIDC-AI/Pixelle-Video resolves to ATH-MaaS/Pixelle-Video,
and saturndec/waoowaoo to waooAI/waoowaoo. Star counts below are GitHub's on 11 October 2026.
Why there is a market to point these at
微短剧 (micro-drama) is vertical, one-to-two-minute episodes, sold by the episode or given away against ads. The China Netcasting Services Association's 2024 white paper projected the 2024 market at 50.44 billion yuan, up 34.90%, against a projected 47 billion for the whole mainland box office, with 576 million users by June 2024. Those are industry estimates the association reports, not audited revenue. Its 2025 findings add the two numbers that explain why these repos exist: animated micro-dramas, a category it credits to AIGC, reached 2,902 titles on the platforms in January to August 2025, and people using micro-drama apps spent 120.5 minutes a day in them. It also says about 66.3% of the 2025 market was free-to-watch and three apps (Hongguo, Hema and Fanhua) cover more than 95% of monthly active users. Distribution is concentrated; production is what got cheap.
Keep that in mind for everything below. These tools lower the cost of making episodes. They do nothing about the part one reply called the hard part.
A drama is a consistency problem, not a generation problem
A modern video model will give you eight good seconds from a prompt. A drama is a hundred of those cuts, and the viewer has to believe the woman in cut 40 is the woman in cut 3: same face, same hairpin, same robe, standing on the same side of the man she is arguing with. Each call to the video model is independent. Nothing carries over unless you carry it.
Every serious answer in these repos carries it the same way. Draw each character once, carefully, as a reference sheet. Plan the drama as a list of segments, each naming who is in it. For each segment, send the video model the text prompt plus the sheets of the people in it, and tell it which picture is which. The video model does the identity-preserving; the pipeline's job is bookkeeping.
That bookkeeping turns into seven stages, and the six repos differ mostly in which ones they implement and where each one runs.
- 1. Scriptvendor relay by defaultscript_rewriter agentdeepseek-v4-pro or Gemini via the firemux relay
- 2. Charactersvendor relay by defaultextractor agent + sheet promptgpt-image-2, Gemini 3 Pro Image or Seedream 5.0, text only
- 3. Storyboardvendor relay by defaultstoryboard_breaker agent8-15 s segments, 2-4 sub-shots, 500 characters per minute
- 4. Imagesvendor relay by defaultasset sheets onlyno per-shot keyframes
- 5. Videovendor relay by defaultreference-to-video, up to 9 refsdoubao-seedance-2-0-mini, 720p cap
- 6. VoicemissingTTS removedthe video model's native audio
- 7. Editlocalconcat demuxer, re-encodeffmpeg libx264 crf 23; no mix, no subtitles
- ConsistencyOne reference sheet per character (face close-up plus front, side and back views), passed to Seedance as reference_image; @name in the prompt is rewritten to @图片N.
The comparator above is the map. Five of the six are API-bound end to end: the only things that run on your machine are a database, a web app and ffmpeg. Pixelle-Video is the exception, because it was built on ComfyUI and can run FLUX, Qwen-Image, Wan 2.1 and Index-TTS2 locally. It is also the one that is not really a drama tool.
What actually holds a face still
I went looking for LoRAs, face swap, seed reuse or embedding tricks, because that is how the open-weights world did character consistency two years ago. None of the six trains a LoRA or swaps a face. A seed appears only as an optional passthrough. The mechanism is the reference sheet, and the sheets are specified with surprising care.
Huobao's character prompt skill states its priority in one line, "一致性 > 美观" (consistency over beauty), and then fixes the layout:
# backend/workspace/skills/prompt-generator/character-prompt/SKILL.md:18-22
角色设定参考图,左侧为正脸特写,右侧并列展示正面、90 度侧面、背面三张等高全身视图,
特写与全身视图都是同一角色,全身入镜,中性 A 字站姿,三张全身视图等高并排、头顶脚底对齐,
...
正脸特写与三个视图的脸、发型和服装完全一致,
纯白背景,柔和均匀的光线,电影质感A face close-up on the left, then front, 90-degree side and back views of equal height, feet aligned,
neutral A-pose, identical face and clothes in all four, plain white background. Toonflow's skill asks
for the same four panels ("头部特写、正面全身、右侧 90° 全身、背面全身",
packages/skills/workflow/references/assets.md:28). waoowaoo uses a two-panel version, face left and
full body right, on a 4:3 canvas (asset-development/SKILL.md:94), and adds a rule I liked: write the
skin, hair and eye colour out in words, because "不写就会被生成模型每次随机化" (if you don't, the model
randomises them every time; SKILL.md:44).

The white background is not taste. A reference image is evidence to the video model about what the person looks like; anything else in the frame is evidence too, and the model will happily put that furniture into your scene.
The second half is the wiring. Huobao gathers the segment's scene image, then each character's
sheet, then the props, caps the list at nine, and rewrites every @name in the prompt to the index
of the picture it refers to (frontend/app/views/drama/episode.vue:3165-3199). The adapter then sends
them all as one role:
// backend/src/services/adapters/volcengine-video.ts:60-65
const content: any[] = []
if (prompt) content.push({ type: 'text', text: prompt })
for (const url of refImages) {
content.push({ type: 'image_url', image_url: { url }, role: 'reference_image' })
}Jellyfish does the same mapping more formally. It numbers the attached images 图1, 图2 and so on, replaces each entity name in the prompt with its token, longest name first so that a short name inside a longer one is not clobbered, and prepends a legend:
# backend/app/services/studio/generation/frame/derive_preview.py:21-23, 294-298
replace_pairs.sort(key=lambda item: len(item[0]), reverse=True)
for name, token in replace_pairs:
text = text.replace(name, token)
...
lines.append("## 图片内容说明") # what each image is
for mapping in mappings:
lines.append(f"{mapping.token}: {mapping.name}")
lines.append("## 生成内容") # what to generateThe longest-first sort is the kind of detail that tells you someone hit the bug. Jellyfish's data
model is also the most thought-through of the six: a character is an actor plus a costume plus props
(app/models/studio_assets.py:199-204), each with images tagged by view angle, so the same actor can
change clothes between episodes without a new identity. Its UI shows that split as tabs.

Toonflow's skill adds two rules that show where this breaks. Every generation segment must list its
own reference images again, never "same as above" (workflow/SKILL.md:223), because the video model
sees one request, not your document. And it forbids the obvious shortcut:
"禁止的是:用上一段的尾帧画面作为站位参考" (do not use the previous segment's last frame as the staging
reference; workflow/SKILL.md:198). Chaining last frames looks like continuity, but each hop is a
re-encode of a re-encode, so a face drifts a little every segment and the error compounds. A sheet is
an anchor every segment returns to. Pixelle-Video does chain tail frames in one of its pipelines
(pixelle_video/pipelines/asset_based.py:709-738), and it is the only consistency device it has.

Does it work? Toonflow's README carries a 137-second vertical demo. I sampled twelve frames from it, evenly spaced.

Mostly, yes. The lead is recognisably one person in every frame, robe and hairpins included. What the grid does not show is how many takes each segment needed, and that is the number that decides the cost.
ViMax is the only one that measures the problem rather than just designing for it. It is a research system from HKU with a paper, and it adds two things to the sheet. First, a camera dependency graph: shots that share a camera position are generated in order, each child getting its parent's frame as an anchor, so a reverse shot stays in the same room. Second, a VLM judge that picks the better of two keyframe candidates before it becomes anyone's reference. The judge's instructions are worth quoting for the order of priorities:
# agents/best_image_selector.py:41-42
- Prioritize Character Consistency: Ensure that the characters in the generated image are highly
consistent with those in the reference image in terms of visual features ...
- Focus on Spatial Consistency: Verify whether the relative positions of characters, object
arrangements, and perspectives align logically with the reference image ...
The paper's ablation is the closest thing to evidence in the whole set. On its own 35-story benchmark, removing the dependency graph and generating every shot in parallel drops its global consistency score by 8.7%, and removing the VLM selection drops it by 3.8%. The authors' line on the parallel variant is the takeaway for anyone building one of these: character portraits alone "cannot sustain identity, layout, and scene state." The score is a ViCLIP cosine similarity between shots, which rewards stable features rather than correct ones, so read it as directional.

So the answer to "what works" is narrow and a little anticlimactic. A clean multi-view sheet per character, sent as a reference image on every single call, with names mapped to images explicitly, gets you most of the way with today's reference-to-video models. Planning shots so that related cameras inherit from each other gets you some more. Chaining last frames is the trap.
Six repos, six levels of finish
Same recipe, then. The differences are in what is actually built, who it is built for, and what the defaults quietly decide for you.
Huobao Drama: the one-sentence promise, under a non-commercial licence
Huobao (火宝短剧, chatfire-AI/huobao-drama, 16,046 stars) is the most literal implementation of the
post's pitch: a fixed pipeline of four Mastra agents behind REST routes, a Nuxt workbench, an Electron
desktop build. A novel or a sentence goes to script_rewriter, an extractor pulls out and
de-duplicates characters, scenes and props, storyboard_breaker cuts the script into segments, and a
loop writes one video prompt per segment.
The storyboard prompt is where the drama's rhythm gets decided, and it is concrete:
# backend/workspace/prompts/storyboard_breaker.md:8, 31, 33
核心定义:一个分镜 = 一个「分镜段落」= 一个视频生成任务。每个段落 8-15 秒,内部承载 2-4 个子镜头
总量锚定:目标总时长 = 剧本字数 ÷ 500字/分钟,段落数 ≈ 目标总时长 ÷ 12秒,允许 ±20% 浮动
台词下限:段落时长 ≥ 段内台词与旁白总字数 ÷ 4.5字/秒 + 2秒表演余量One storyboard entry is one video call of 8 to 15 seconds holding 2 to 4 sub-shots. Running time is anchored at 500 script characters per minute, segments average 12 seconds, and a segment must be at least as long as its dialogue read at 4.5 characters a second plus 2 seconds of acting. That last rule is the one I would steal: it is how you stop a model rushing a line.

The default video model is doubao-seedance-2-0-mini-260615, capped at 720p, with
watermark: false hard-coded (backend/src/services/adapters/volcengine-video.ts:22, 80-81).
There is no TTS: a test file asserts the old MiniMax TTS module stays deleted, and audio is whatever
the video model generates. The README's "subtitle handling" has no code behind it. Assembly is the
plainest possible join:
// backend/src/services/ffmpeg-merge.ts:106-118
ffmpeg()
.input(listPath)
.inputOptions(['-f', 'concat', '-safe', '0'])
.outputOptions([
'-fflags', '+genpts',
'-c:v', 'libx264', '-preset', 'medium', '-crf', '23',
'-c:a', 'aac', '-ar', '48000', '-b:a', '192k',
'-movflags', '+faststart',
])Three things an engineer should know before deploying it. The recommended setup is a one-key
"quick config" that points seven service configs at the vendor's own relay, api.firemux.cn or
.com depending on your UI language (frontend/app/pages/settings.vue:723, 774-784); the official
Volcengine, MiniMax and Bailian endpoints are there as manual templates. API keys sit in plaintext
in SQLite, the settings API returns them unredacted, there is no API authentication, and the compose
file publishes the app on every network interface. On a laptop that is fine. On a server, anyone who
can reach the app can read your provider keys, so bind it to localhost or put it behind
authentication before you deploy it anywhere shared.
The third is the licence. Huobao is CC BY-NC-SA 4.0, and its README spells it out: "❌ Commercial
use is prohibited … including paid services, commercial deployments, or resale … without prior
written permission from the author" (README.md:596). The post recommends it first, for making money.
Toonflow: a coding agent with a 1,400-line skill file
Toonflow (HBAI-Ltd/Toonflow-app, MIT, 17,229 stars) took the opposite approach. There is no
pipeline in code. There is an infinite canvas of nodes (image, video, audio, a three.js "director"
for previs), and a coding agent that operates the nodes through tools while following Markdown
skills. The production order lives in a table:
# packages/skills/canvas/references/videoProduction.md:11-18 (abridged)
需求与简报 → 完整剧本 → 资产设计与准备 → 剧本分片段与视频提示词 → 视频小样 → 批量制作与交付Brief, full script, assets, segments with one multi-reference prompt each, a sample clip, then the
rest once you approve. Keyframes are off by default: "每片段的全部镜头转成一份视频提示词,资产直接作为视频输入"
(all of a segment's shots become one video prompt, and the assets go straight in as video inputs;
videoProduction.md:7). The workflow skill is Seedance-shaped down to its section headings, with a
template of timed shot blocks separated by HARD CUT and closing locks for light, sound and on-screen
text. It routes there whether or not you mention Seedance (workflow/SKILL.md:23).
Two details I did not expect. On the APIMart provider, reference images are first submitted to a
Seedance "private avatar" asset group for review, and only approved URLs are used
(packages/providers/src/media/apiMart.ts:73-87), which is how real-face references get through
Seedance's moderation. And telemetry is on unless you turn it off
(apps/web/src/stores/settings.ts:83), posting usage counts, not content, to api.toonflow.net.
The README says plainly that the pages and API have no login, and binds the compose file to
localhost. There are no tests.
Toonflow is also the only repo that publishes a receipt. Its demo, about two hours of work for about
two minutes of finished film, lists Seedance 2.0 for video, GPT Image 2 for images and Claude Opus 4.6
for language, and "约 ¥130,其中语言约 ¥10、视频约 ¥120、图片不足 ¥1" (about 130 yuan: about 10 for language,
about 120 for video, under 1 for images; README.md:387). Hold on to that 92% video share.
Pixelle-Video: an explainer engine wearing a drama badge
Pixelle-Video (ATH-MaaS/Pixelle-Video, Apache-2.0, 28,874 stars, the most starred of the six)
makes a different product. You give it a topic; an LLM writes five narration lines of 5 to 20 words;
each line gets an image prompt, an image or clip, and a voice track; an HTML template is rendered to a
transparent PNG in headless Chromium and laid over each scene; ffmpeg joins them with background
music mixed at 0.2. The video length of each scene follows its audio.

There is no character stage. Nothing in the standard pipeline knows that scene 3 and scene 4 contain
the same person. Its only cross-scene glue is a style prefix glued onto every prompt,
return f"{prefix}, {prompt}" (pixelle_video/utils/prompt_helper.py:45), and the shipped default
prefix is "Minimalist black-and-white matchstick figure style illustration". Stick figures are
consistent by construction. It is a reasonable product for narrated explainers and a poor fit for
the post's claim.
What it does have is the only real local path. The selfhost/ ComfyUI workflows load FLUX.1-dev,
Qwen-Image with the 4-step Lightning LoRA, a Wan 2.1 FusionX text-to-video model (512x288, 81 frames
at 16 fps) and Index-TTS2. The defaults in config.example.yaml:62, 72, though, point at RunningHub,
a hosted ComfyUI service, and those workflow files are 70-byte stubs naming a remote workflow id.
One behaviour deserves a flag. When a video provider rejects a prompt in content review, Pixelle asks
an LLM to rewrite it and retries, with an instruction to make it pass and a rule
"不要提及"审核""违规""敏感词"等元信息" (do not mention review, violations or sensitive words;
pixelle_video/services/api_media.py:602-608). Softening a prompt so a model accepts it is an
ordinary retry strategy; doing it automatically and silently means the tool, not the person, is
deciding what gets past a provider's filter. There are no tests in the repo.
Jellyfish: the best database, and no editor
Jellyfish (Forget-C/Jellyfish, Apache-2.0, 6,675 stars) is the most engineered of the six:
FastAPI, async SQLAlchemy, Celery on Redis, 46 test files, Pyright. Its LangChain agents divide a
script into shots, flag text where one character is given two identities, merge entities across
shots, and extract a project draft whose shots use closed vocabularies (shot sizes ECU through ELS,
angles, moves) and 2 to 4 action beats each. Its frame-prompt template has 21 rules, including one
that understands animation better than most: a first frame may only show "事件触发瞬间或最初反应" (the
triggering instant or the first reaction), never the finished action
(app/chains/agents/shot_frame_prompt_agents.py:139).
Then it stops. Each shot becomes one generated video. There is no TTS, no subtitle code, no join: the
video editor page calls a timeline route that exists only in the front-end mock, and its "导出成片"
(export film) button has no handler (front/src/pages/aiStudio/editor/VideoEditor.tsx:51-53). The
README's "后期剪辑" is a plan. One more thing I would check before using the published Docker image:
langchain-openai, which the agents import, is listed only in the dev dependencies, and the backend
image is built with uv sync --no-dev; the code answers a missing import with HTTP 503 "Install
langchain-openai to enable script-processing tasks" (app/services/llm/runtime.py:58-60). I have not
run the image, so treat that as a likely failure, not a confirmed one.
waoowaoo: the post describes a version that is gone
The post calls waoowaoo "工业级" (industrial-grade) and describes novel to storyboard to characters to
video to dubbing. That was true of the README until July. The current HEAD, 0.5.0-beta.1 from
September, is "An AI creative workspace for images and videos": an assistant loading creative skills
on a canvas, Temporal for durable jobs, MinIO, a credits ledger. The old README's preview screenshots
were removed in a commit titled "remove outdated preview screenshots". This is what the post's
author would have seen:

The new code keeps the drama recipe as skills, and it is careful work: 68 test files, strict
TypeScript, encrypted API keys, and a shot template that refuses emotional adjectives: 写“呼吸变浅,指节抵住桌沿”,
不写“她很紧张” (write "breathing goes shallow, knuckles press the table edge", not "she is nervous";
creative-skills/skills/video-direction/SKILL.md:56).
Voice is handled the way I think it should be now: a designed voice is passed to the video model as
reference audio alongside the character sheet, instead of TTS followed by lip-sync. Assembly is the
best of the six, with two-pass loudness normalisation to -16 LUFS and the music bus ducked under
dialogue by a sidechain compressor (src/lib/video-compose/video-merge-audio.ts:355).
It is also the only repo that shows its margins. Its cost table for Seedance 2.0 on Volcengine,
0.9936 yuan a second at 720p (src/lib/ai-providers/ark/pricing.ts:27-29), matches Volcengine's
published 0.99. Its retail price for the same second is 19 credits at 0.1 yuan each
(shared/seedance-pricing.ts:12-15, billing/credits.ts), about 1.9 times cost, and the comment
above the markup table says the quiet part out loud: "1.8 means … a 44% gross margin"
(src/lib/ai-registry/pricing-retail.ts:21-22). The licence is Elastic 2.0: you may self-host and
modify it, but offering it to others as a hosted service needs permission.
ViMax: the research one, with an unfinished novel mode
ViMax (HKUDS/ViMax, MIT, 12,623 stars) is the one the post credits with long-novel adaptation, and
its novel path is the most interesting code in the set. The novel is split into 65,536-character
chunks with 8,192 of overlap (agents/novel_compressor.py:86-99), each chunk compressed by an LLM,
and the result merged. An extraction loop then pulls out up to 50 events, each a causal chain of
steps. For each step it searches the original text, re-split into 512-character pieces in FAISS, for
the 10 nearest chunks and keeps those a reranker scores at 0.7 or above
(pipelines/novel2movie_pipeline.py:173-179), then writes up to 30 scenes per event from what it
found. Characters are merged scene to event to novel, and each gets a base portrait that is edited per
scene for costume changes with "Keep the character's identity consistent with the base image"
(novel2movie_pipeline.py:417-422).
The file it all lives in starts with # TODO: NOT IMPLEMENTED YET. The code runs past that line to
per-scene rendering, but it returns a folder of scene videos and never joins them, so the novel mode
delivers parts, not an episode. The defaults are all hosted: gpt-5.5 through a relay called
yunwu.ai, Gemini image, Veo 3.1 Fast for 8-second clips, with Veo's own audio and no TTS
(agent_runtime/config.py:11-20).
The bill is the video model
Now the reply's question. Every one of these spends money in the same proportions, and Toonflow's receipt already told us the shape: video was 120 of 130 yuan. Language models and images are rounding errors next to it. So the cost of a finished minute is, to a good approximation,
where is the video model's price per generated second and is how many seconds you generate for every second you keep. is the number nobody publishes and everybody pays. A take with the wrong hand, a face that slipped, a line delivered too fast: each one is a full segment regenerated, and because the segment is the unit, a 12-second segment with one bad second costs 12 seconds.
The list prices, read from the vendors' own pages on 11 October 2026, for the models these repos default to:
| Model (vendor page) | 480p | 720p | 1080p | Default in |
|---|---|---|---|---|
| Seedance 2.0 mini (Volcengine) | ¥0.23/s | ¥0.50/s | none | Huobao |
| Seedance 2.0 (Volcengine) | ¥0.46/s | ¥0.99/s | ¥2.48/s | Toonflow's demo |
| Seedance 2.5 (Volcengine) | ¥0.67/s | ¥1.51/s | ¥3.74/s | Toonflow, waoowaoo option |
| Wan 3.0 (Alibaba Bailian, list) | ¥0.30/s | ¥0.60/s | ¥1.20/s | Huobao, Toonflow option |
| Kling 3.0, no native audio | none | $0.084/s | $0.112/s | Pixelle option |
| Veo 3.1 Fast (Gemini API) | none | $0.10/s | $0.12/s | ViMax |
Volcengine prices Seedance by tokens and publishes the per-second figures as examples for 5-second 16:9 clips with no input video; the token formula is duration × width × height × frame rate ÷ 1024, so a different aspect ratio moves the price a little. Wan 3.0 was on a time-limited 70% offer when I read the page; the table uses the list price.
At Seedance 2.0 and 720p, one kept minute with no retakes is 60 × 0.99, about 59 yuan. Toonflow's receipt of about 120 yuan of video for about two minutes lands almost exactly on that line: 120 yuan buys about 121 seconds at 720p, or about 261 seconds at 480p. Either the demo was made at 720p with nearly every segment kept first time, or at 480p with a little over two generations per kept second. The README does not say which, and its demo file is a 480p re-encode, so I can't tell.
The Huobao screenshot gives a second anchor: an episode of 16 segments and 184 seconds on Seedance 2.0 mini at 720p is 184 × 0.50, about 92 yuan per full pass. ViMax's paper gives a third, in dollars: $17.50 of API calls per benchmark story, at best-of-2 keyframes. Its stories have 8 to 16 shots; if each is the code's default 8 seconds that is 64 to 128 seconds of film, roughly $8 to $16 a minute. The paper does not state the shot length, so treat that range as mine.
60 s × 2.0 × ¥0.99/s + 4 × ¥0.22 = ¥120 per minute. Language-model and TTS fees are left out; both are small next to video.
Play with the reroll factor before anything else. Going from 1x to 3x triples the bill and nothing else on the panel comes close; moving from 720p to 480p halves it; the image budget barely registers. For a sense of scale, a series of 60 finished minutes at Seedance 2.0, 720p and 2x retakes is about 7,100 yuan of video fees at list price. Cheap next to a live-action shoot, but not free, and a hosted product built on these repos adds its own margin on top, as waoowaoo's ledger shows.
The labels none of them write
Since 1 September 2025, China's 人工智能生成合成内容标识办法 (Measures for Labelling AI-Generated and Synthetic Content, issued by the CAC with three other ministries) has required two labels. An explicit one a viewer can see: for video, at the opening frame and around the player (Article 4). And an implicit one in the file's metadata naming the content as generated, the provider and a content number (Article 5). Platforms must check the metadata and add a visible notice when it says AI, or when the uploader declares it, or when their own detector suspects it (Article 6). Uploaders must declare AI content themselves, and no one may remove or hide a label, or provide tools for doing so (Article 10). Douyin's one-year report says it reads and writes these metadata labels, added a "内容由AI生成" (content generated by AI) requirement in May 2026 for content made with third-party AI tools, and labels suspected AI content it finds unlabelled.
I grepped all six for 标识, AIGC, watermark, 水印 and C2PA. None writes an implicit label, none adds an
explicit one to the final cut, and four switch the provider's visible watermark off by default:
Huobao hard-codes watermark: false for Seedance, Toonflow sets it for Seedream and its compshare
provider, Pixelle defaults it to false across Seedream, DashScope and its video client, and
waoowaoo's Volcengine image adapter defaults to options.watermark ?? false. A
provider is allowed to hand over unwatermarked output under its user agreement (Article 9), so that
switch is not the problem. The problem is what happens next.
The usual last step is ffmpeg's concat demuxer. I checked what it does to a metadata label with
ffmpeg 6.1.1: I made two clips carrying a format-level AIGC tag and a comment, then joined them
twice, once with Huobao's exact output options and once with -c copy as Pixelle and waoowaoo do.
Both outputs kept only ffmpeg's own encoder tag; the AIGC tag and the comment were gone. My
synthetic tag is not necessarily where a given provider writes its label, and a watermark embedded in
the pixels would survive, but a container-level label does not make it through the join unless the
tool copies it on purpose, and none of these do.
The practical consequence is simple. The file these tools hand you is, as far as metadata goes, an ordinary video, so the platform's first check (Article 6, case one) finds nothing, and labelling falls to the uploader's declaration. If you build on any of them, add the label yourself: an explicit notice in the opening frames and the AIGC metadata on the final file, written after the join.
What I would take from each
If I were building a short-drama tool today, I would take Jellyfish's data model (actor, costume and props as separate assets, images per view angle, names mapped to image tokens), Huobao's storyboard arithmetic (segment length from dialogue at 4.5 characters a second plus acting room), Toonflow's two rules (re-bind references every segment, never chain last frames), waoowaoo's voice-as-reference and its audio mix, and ViMax's camera graph and best-of-2 keyframe check. I would not take anyone's assembly step without adding the labels after it.
Which one to run depends on what you want. For a working drama end to end with the least setup, Toonflow or Huobao, with the licence difference in mind: Toonflow is MIT, Huobao forbids commercial use. For narrated explainers, or anything you want to run locally, Pixelle. For a codebase to extend, Jellyfish or waoowaoo, which have tests. For the research question of long-form consistency, ViMax and its paper.
None of them changes the economics the post skips. The model does the hard part, the meter runs per generated second, and the retake rate, which no repo measures, decides whether a minute costs 59 yuan or several hundred.
Related reading on this site: WanGP and YuE2 for running Wan locally on a consumer GPU, Kandinsky 6.0 Video for where lip-sync comes from inside a video model, restore and relight LoRAs for the reference-image idea on the image side, Claude's product demos for another ffmpeg join taken apart, and the Diffusion Transformer explainer for what sits inside Seedance, Wan and Veo.
How I checked
I shallow-cloned all six repositories on 11 October 2026 (Huobao at 26de7df, Toonflow at 2c7fb25,
Pixelle-Video at 848b054, Jellyfish at a967819, waoowaoo at dfec20e, ViMax at fd4b72e) and
read the source; every file and line reference above is from those commits. For waoowaoo I fetched
27 commits of history to read the README as it was before September. I did not install or run any of
them and called no paid API. Star counts and licences come from GitHub's API on the same day.
Prices come from Volcengine's model-pricing page (updated 10 October 2026), Alibaba Bailian's
model-pricing page, Kling's developer pricing page (rendered in a headless browser, since it is a
single-page app) and the Gemini API pricing page. The market figures are the China Netcasting
Services Association's published white-paper findings, which are themselves estimates. The labelling
rules are quoted from the CAC's published text; Douyin's practice is from its own notice. I sampled
the demo frames from the videos linked in the Toonflow and ViMax READMEs with ffmpeg, and ran the
metadata test on synthetic clips I generated myself. I could not check how many takes any demo
needed, the shot length ViMax's paper used, or whether Jellyfish's published image actually fails.