novel-script
Write for AI short dramasscripts。The premise is carved into the bones: the script governs the drama, the storyboard governs the shoot— "Is it satisfying?" and "How do we shoot it?" are two different iteration rhythms. Dialogue must be repeatedly overturned and rewritten, and binding it to shot breakdown means every changed line requires rearranging shots. So this layer only has episodes, scenes, and beat flow, with no shot numbers; shots, first-frame prompts, and generation batches are the job of the next layer, the storyboard skill.
But there is one bottom line:dialogue must be structured data, not written as prose. Each line of dialogue is an independent entry (speaker + dialogue + tone), and actions are independent beats — this is the foundation of all deterministic checks:
| Deliverable | What it solves |
|---|---|
| Per-episode duration budget | If an episode is three minutes, it is three minutes: dialogue is converted by speech rate, actions are estimated by beat, and overruns or underruns are stopped on the spot instead of only being discovered during generation |
| Beat flow (action ⇄ dialogue) | Dialogue directly connects to TTS for line-by-line generation; action beats are exactly what must happen on screen. Mixing them into prose means neither end can be fed into the pipeline |
| At least one action beat per scene | A scene with pure dialogue is a radio drama — there is no picture to write when AI generates it |
| Opening hook + ending suspense | The lifeline of a short drama, every episode must land it on paper;the hook is not a label but the first beat——hookBeat claim a concrete position and must land within the first 3 beats of the entire episode (cold open) |
| Satisfaction point claim | If the outline says this episode has a big explosive point, the script must have action to claim it — preventing the explosive point from being lost during revisions |
| Upstream reconciliation | Scenes/lighting/props reconcile against art.json, characters against outline.json, and any lighting state that is written but not registered in art is reported on the spot |
{baseDir} = the directory where this file is located. Script {baseDir}/scripts/novel-script.mjs, zero dependencies,node run directly.
Boundaries (things not done): no shot splitting, no shot numbers, no writing image-generation prompts, no image output, no music — none of the storyboard layer's work is touched. Do not change the outline structure (cutting lines or merging characters is the job of novel-outline ); do not do character and scene settings (the job ofnovel-characters / novel-art ).
Step 0 — Define inputs and scope
outline.json is the direct upstream of the script(episode synopses, satisfaction point placements, and single-episode duration are all in it), and the standard process starts from it. If it is absent, first ask the user whether to run novel-outline; if the user insists on writing directly, ask clearly for the number of episodes and minutes per episode, manually build the skeleton, and the reconciliation gate will explicitly say it was skipped.
How many episodes to write at a time: default batch ≤ 3 episodes. The script is the layer most heavily revised in the entire pipeline, so output in small batches, get quick decisions, then continue writing. If the user explicitly wants the whole drama, also produce it in batches, with each batch passing validation once.
Bring along as convenient (all optional; only if provided will names be reconciled/displayed):
--outline: character reference reconciliation + satisfaction point claim check + C01 displayed as a person's name in the report--art: scene/lighting state/prop reconciliation + S01 displayed as a scene name in the report
Step 1 — seed skeleton
node {baseDir}/scripts/novel-script.mjs seed <outline.json> --eps 1-3 > <workdir>/script.json
Deterministic transfer: target seconds (per-episode minutes × 60), hooks, suspense, this episode's payoff claims, candidate scenes and characters (add seedNote)。Don't make the model think through these facts again. leave scenes empty; that's the work of writing the drama.
Step 2 — Write the drama episode by episode
One task per episode, parallelize if possible. Each task gets:
{baseDir}/references/script-pass.mdand{baseDir}/references/schema.md(read them, follow them)- This episode's seed skeleton + this episode's synopsis/payoffs/audience plan from the outline
- The scene cards used in this episode (anchors and lighting states in art.json) and character info (temperament, way of speaking—cast.json is better)
- The previous episode's ending suspense(this episode's opening must connect)
The core requirements are all in script-pass.md; the four heaviest:Action beats only use common actions(shouldering a pole onto a boat, lending a hand to unload a pole—the kind of thing AI has seen tens of millions of times; delicate actions like blocking with a raised pole or a trembling eyelash will definitely break generation);Time budget before everything(a three-minute episode is about 50 beats; after writing, run validate yourself to check the seconds); dialogue colloquial, one sentence in one breath,each person's words sound like them(if cast.json is available, use the character's temperament and way of speaking);Each episode's first beat is a cold open giving the hook's concrete form(hookBeat claim, gate check position), the ending beat must be suspense.
When done, delete seedNote .
Step 3 — Validation ⛔ cannot skip
node {baseDir}/scripts/novel-script.mjs validate <script.json> \
--outline <outline.json> --art <art.json>
The 10 quality gates are all code: each episode's duration within target ±15% (dialogue converts at 4.5 characters/second, actions at 2.5 seconds/beat,params adjustable), single dialogue line ≤ 35 characters, speaker in this scene's characters or marked VO, each episode's hook and suspense on the page,hook's concrete form delivered within the first 3 beats of the whole episode(hookBeat claim,params.hookWindow adjustable), each scene has at least one action beat, action narration doesn't mix quoted dialogue, payoff claims, character reconciliation, scene/lighting/prop reconciliation.
Fix violations one by one, rerun after changes, until it passes. If over, cut action beats first, then compress dialogue; if under, add drama without padding—add conflict, not small talk. When a lighting state not registered in art isn't available, go add the state in art.json and come back; don't bypass the gate.
Step 4 — Output and report
cd <输出目录>
node {baseDir}/scripts/novel-script.mjs render <剧名>-script.json --md \
--outline <outline.json> --art <art.json> > <剧名>-script.md
node {baseDir}/scripts/novel-script.mjs render <剧名>-script.json --html \
--outline <outline.json> --art <art.json> --cast <cast.json> > script-report.html
# 英文界面:加 --lang en(默认中文,也可跟 script.json 顶层的 lang 字段)
The report includes: KPI strip (including dialogue ratio), duration gauge (each episode's bar against the target range band, over/under in red), episode scripts (two per row, scene info over 300px fades and truncates, click to expand), scene summary table,dialogue book(two per row, grouped by character, list six rows high and scrollable, copy whole group; if provided --cast each character group header has avoice promptbutton—dialogue and voice together on one page, ready to run TTS), quality gate panel, export JSON (what's downloaded is script.json exactly as-is).
Report in one sentence: how many episodes, scenes, and dialogue lines, estimated total duration vs target, which episodes are near the tolerance edge, report path; state clearly any gates not passed.
Final deliverable:
<输出目录>/
├── <剧名>-script.json
├── <剧名>-script.md
└── script-report.html ← 双击就能开
The relay of the four skills
novel-outline → outline.json (什么:结构与分集)
novel-characters → cast.json (谁:角色资产)
novel-art → art.json (哪里 + 手里拿的:美术资产)
novel-script → script.json (戏:场次、节拍、台词)
seed consumes outline.json; validate/render's --outline --art Responsible for reconciliation and displaying names. The reports of the four JSON files each have an export button, and after editing they can all be fed back into their respective render/validate. The next layer down is the storyboard: shot number, single-shot duration, first-frame prompt, and generation batch sheet are all over there.
Boundaries
- The report interface has built-in Chinese and English (
--lang, defaulting to Chinese, or following script.json'slangfield); dialogue language follows the drama - Duration is anestimate, not a stopwatch—the ±15% tolerance is reserved for exactly this;
params.charsPerSecondcan be adjusted according to voiceover speaking rate VOis the unified marker for voiceover; whose inner thoughts are written indelivery; in the dialogue script, VO forms its own group- There is no upper limit on the number of scenes per episode—AI scene changes cost nothing, and the number of scene changes only goes into KPI statistics with no gate set
Self-test
node {baseDir}/scripts/selftest.mjs
154 assertions, no model calls, no quota spent. Each of the 10 quality gates has a breaking test case. Run this first after modifying the script.
Built-in samples
{baseDir}/examples/渡口-script.json: "Ferry Crossing"Complete script for all 6 episodes(9 scenes, 123 lines of dialogue, each episode's cold open delivers on the hook, and all fall within 120 seconds ±15%), and all quality gates pass against the novel-outline and novel-art samples. Serves as the quality baseline and also as the self-test fixture.