# Six AI short-drama generators, read: the face is held by a reference sheet, and the bill is the video model

> Satyajit Ghana — Head of Engineering @ Inkers Technology
> canonical: https://ai.thesatyajit.com/articles/ai-short-drama-pipelines
> date: 2026-10-11
> tags: video-generation, agents, multi-agent, image-generation, pricing, licensing

[The post](https://x.com/bkdgiffug/status/2109073242333884691) 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.

<RepoCard repo="chatfire-AI/huobao-drama" />

<RepoCard repo="HBAI-Ltd/Toonflow-app" />

<RepoCard repo="ATH-MaaS/Pixelle-Video" />

<RepoCard repo="Forget-C/Jellyfish" />

<RepoCard repo="waooAI/waoowaoo" />

<RepoCard repo="HKUDS/ViMax" />

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](http://www.cnsa.cn/art/2024/11/6/art_1955_45923.html) 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](http://www.cnsa.cn/art/2025/11/11/art_1955_47836.html) 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.

<PipelineComparator />

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:

```text
# 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`).

<Figure
  src="https://ai.thesatyajit.com/articles/ai-short-drama-pipelines/fig2.jpg"
  alt="Huobao Drama's asset screen in dark mode: a row of generated character reference sheets, each a face close-up beside front, side and back full-body views, with scene and prop cards below, most still empty"
  caption="Huobao's asset stage: each character is one turnaround sheet, the image every later video call gets as its reference. Scenes and props get their own cards (Huobao Drama README, docs/screenshots/06-assets.png)."
/>

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:

```ts
// 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:

```python
# 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 generate
```

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

<Figure
  src="https://ai.thesatyajit.com/articles/ai-short-drama-pipelines/fig7.jpg"
  alt="Jellyfish's asset management page with tabs for actors, scenes, props and costumes, showing two actor cards described in Chinese with tags such as realism and urban"
  caption="Jellyfish keeps actors, scenes, props and costumes as separate assets, so a character is a combination rather than one picture (Jellyfish README, docs/img/资产管理.png)."
/>

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.

<Figure
  src="https://ai.thesatyajit.com/articles/ai-short-drama-pipelines/fig4.jpg"
  alt="Toonflow's canvas: a node holding a generated character board with a head close-up and front, side and back full-body views of a young man in dark clothes, and the agent's chat panel on the right"
  caption="Toonflow's character node: a four-view board generated on the canvas, its prompt below (written-out appearance anchors, the four views left to right, and a last line asking for no text, watermark or label: 无文字、水印或标识), the agent's notes on the right (Toonflow README, docs/images/screenshots/characterImageGeneration.png)."
/>

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

<Figure
  src="https://ai.thesatyajit.com/articles/ai-short-drama-pipelines/fig5.jpg"
  alt="Twelve frames from a vertical costume drama: the same young woman in a pale green robe and hair ornaments appears across close-ups, wide shots and a two-shot with an older man in black, with burned-in Chinese dialogue captions"
  caption="Twelve evenly spaced frames from Toonflow's demo (made, per the README, with Seedance 2.0, GPT Image 2 and Claude Opus 4.6). The lead's face, robe and hair ornaments hold across close-ups and wide shots; the captions are burned in. Frames sampled by me (Toonflow README demo video)."
/>

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](https://arxiv.org/abs/2606.07649), 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:

```text
# 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 ...
```

<Figure
  src="https://ai.thesatyajit.com/articles/ai-short-drama-pipelines/fig1.png"
  alt="ViMax architecture: a novel is chunked, compressed and aggregated into events and scenes with retrieval; an idea router feeds script instructions; script writer and character extractor agents feed an autonomous shot-planning block; a graph of nine numbered shots shows parent frames feeding child shots of two men on a rooftop"
  caption="ViMax's architecture: the novel path (chunk, compress, aggregate into events, retrieve per scene) along the top; shot planning in the middle; on the right, the graph-based visual dependency, where shot 1's wide frame anchors the shots that follow (ViMax paper, Figure 2)."
/>

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.

<Figure
  src="https://ai.thesatyajit.com/articles/ai-short-drama-pipelines/fig9.jpg"
  alt="Twelve frames from a ViMax demo of a Formula One race: a helmeted driver with APX branding in cockpit close-ups, black and red cars on track from several angles, and a final shot crossing the line"
  caption="Twelve evenly spaced frames from one of ViMax's README demos. The driver's helmet branding and the two liveries stay consistent across cockpit, track-side and close-up angles. Frames sampled by me (ViMax README demo video)."
/>

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:

```text
# 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.

<Figure
  src="https://ai.thesatyajit.com/articles/ai-short-drama-pipelines/fig3.jpg"
  alt="Huobao's video production screen: a list of 16 segments for episode 2, a selected segment's description and its timed video prompt starting 0-3 seconds at an abandoned factory gate, a panel of character references mostly unbound, and a preview player with the model set to doubao-seedance-2-0-mini at 720p"
  caption="Huobao's segment editor for one episode: 16 segments, 184 s, the prompt written in 3-second lines with @scene mentions, and doubao-seedance-2-0-mini at 720p as the default. Note the reference panel reads 1/12 bound (Huobao Drama README, docs/screenshots/07-storyboard.png)."
/>

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:

```ts
// 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:

```text
# 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.

<Figure
  src="https://ai.thesatyajit.com/articles/ai-short-drama-pipelines/fig6.png"
  alt="Pixelle-Video flow chart: input text, generate video script and narrations, generate image prompts, then a per-scene loop of generate audio (edge-tts, index-tts, chat-tts, custom), generate image (flux, qwen, sdxl, custom), compose frame with a style, render segment, then concatenate with BGM and output video"
  caption="Pixelle-Video's own pipeline diagram: narration first, then a per-scene loop of audio, image, frame composition and render, then concatenation with music (Pixelle-Video README, resources/flow_en.png)."
/>

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:

<Figure
  src="https://ai.thesatyajit.com/articles/ai-short-drama-pipelines/fig8.jpg"
  alt="waoowaoo's earlier storyboard view: a row of five generated panels of a woman in white hanfu in a palace courtyard, with shot type, camera move and dialogue fields under each panel"
  caption="waoowaoo's storyboard panels from its README before September 2026, when the project moved to a general creative canvas. The same lead appears across five panels with shot type, camera move and dialogue fields beneath (waoowaoo README at commit ce8edeb, GitHub attachment)."
/>

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,

$$
\text{cost per kept minute} \approx 60 \times r \times p
$$

where $p$ is the video model's price per generated second and $r$ is how many seconds you generate
for every second you keep. $r$ 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.

<CostPerMinute />

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
[人工智能生成合成内容标识办法](https://www.cac.gov.cn/2025-03/14/c_1743654684782215.htm) (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](http://www.cnsa.cn/art/2026/9/3/art_1957_49264.html) 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](/articles/vram-is-a-policy) for running Wan locally on
a consumer GPU, [Kandinsky 6.0 Video](/articles/kandinsky-6-video) for where lip-sync comes from inside
a video model, [restore and relight LoRAs](/articles/restore-and-relight-loras) for the reference-image
idea on the image side, [Claude's product demos](/articles/claude-demo-videos) for another ffmpeg join
taken apart, and the [Diffusion Transformer explainer](/architectures/diffusion-transformer) 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.
