@wji.ai/cli 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/dist/commands/canvas.js +91 -12
- package/dist/commands/fsnode.js +30 -1
- package/dist/commands/gen.js +4 -19
- package/dist/commands/workspace.js +6 -2
- package/dist/index.js +4 -1
- package/package.json +1 -1
- package/skill/short-drama/SKILL.md +305 -0
- package/skill/short-drama/examples/night-shift/episodes/E01.json +1883 -0
- package/skill/short-drama/examples/night-shift/project.json +774 -0
- package/skill/short-drama/reference/canvas-recipes.md +199 -0
- package/skill/short-drama/reference/craft-motion.md +116 -0
- package/skill/short-drama/reference/craft-shots.md +177 -0
- package/skill/short-drama/reference/craft-story.md +188 -0
- package/skill/short-drama/reference/dialogue-craft.md +120 -0
- package/skill/short-drama/reference/schema.md +435 -0
- package/skill/short-drama/reference/stage-art.md +56 -0
- package/skill/short-drama/reference/stage-characters.md +206 -0
- package/skill/short-drama/reference/stage-outline.md +103 -0
- package/skill/short-drama/reference/stage-script.md +113 -0
- package/skill/short-drama/reference/stage-storyboard.md +465 -0
- package/skill/short-drama/reference/workspace-layout.md +118 -0
- package/skill/short-drama/scripts/selftest.mjs +1411 -0
- package/skill/short-drama/scripts/short-drama.mjs +3371 -0
- package/skill/wji/SKILL.md +97 -22
- package/skill/wji/reference/canvas-recipes.md +16 -2
- package/skill/wji/reference/commands.md +15 -6
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Canvas recipes for short drama
|
|
2
|
+
|
|
3
|
+
Command sequences for the three canvas types. All ids are placeholders — take real ones from the
|
|
4
|
+
command output (`wji --json canvas add … | jq -r .id`) and `bind` them at once. `SD` below is
|
|
5
|
+
`node {baseDir}/scripts/short-drama.mjs`.
|
|
6
|
+
|
|
7
|
+
Common setup (once per project):
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
wji ws create "<title>" -r 9:16 --json | jq -r .id # default template: dataset, image generation, canvas → WS
|
|
11
|
+
wji ws use WS
|
|
12
|
+
SD bind <project> wji.workspaceId WS
|
|
13
|
+
DS_APP=$(wji --json ws get | jq -r '.apps[] | select(.app=="Dataset") | .id')
|
|
14
|
+
wji --json ws fs --app $DS_APP | jq -r '.. | objects | select(.content.semanticKey?) | "\(.content.semanticKey) \(.id)"'
|
|
15
|
+
SD bind <project> wji.datasetFolders.character <id> # story / character / location / prop / shot
|
|
16
|
+
# zsh: a variable holding several ids is not word-split — pass ids literally or pipe through `while read`
|
|
17
|
+
wji models list --feature image # pick the image model once (GPT Image 2.5 Sunburst if listed)
|
|
18
|
+
wji models get "<image model>" # confirm 1:1 and 16:9 ratios and the max reference count
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 1. `characters` canvas
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
wji canvas create characters --json | jq -r .id # → CV; bind wji.canvases.characters
|
|
25
|
+
# row for C01 (rows 700 px apart: --at 0,0 / 0,700 / …)
|
|
26
|
+
wji canvas add title -c CV -t "C01 林小夏" --at 0,0 --json | jq -r .id # → T1; bind characters.C01.wji.nodes.title
|
|
27
|
+
wji canvas add image -c CV -n "C01 headshot" -m "<image model>" -r 1:1 \
|
|
28
|
+
--at 400,0 -p "<image.prompt>, clean front-facing portrait, plain neutral background" --json | jq -r .id # → H1
|
|
29
|
+
wji canvas add image -c CV -n "C01 sheet" --from H1 -m "<image model>" -r 16:9 \
|
|
30
|
+
--prompt-file /tmp/C01-sheet.txt --json | jq -r .id # → S1 (file = "@image1 is the face to match exactly. " + image.sheet)
|
|
31
|
+
wji canvas add audio -c CV -n "C01 voice" --from H1 -m seed-audio-1.0 \
|
|
32
|
+
-p "$(SD prompt <project> voice C01)" --json | jq -r .id # → V1; references the HEADSHOT
|
|
33
|
+
# the prompt is (age;identity;personality;timbre;pitch;pace;accent;emotion;此刻<direction>)<line>
|
|
34
|
+
SD bind <project> characters.C01.wji.nodes.headshot H1 # sheet S1, voice V1
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Generate: headshots for all characters are one batch (quote the total, or `-auto`), then look at
|
|
38
|
+
each (`wji canvas get H1 --json | jq -r .assetId` → `wji asset download <asset> -o /tmp/sd`), then
|
|
39
|
+
sheets. `wji canvas gen S1 --yes --wait` per node; the result's asset id →
|
|
40
|
+
`bind characters.C01.wji.assets.sheet`. Attach to the dataset:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
wji fs set <C01 dataset> --add-images <headshot> <sheet> <voice> --icon <headshot> --set primaryAudio=<voice>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Reference for the sheet prompt file: `@image1 is the face to match exactly — same features, same
|
|
47
|
+
hairstyle. ` + `image.sheet`.
|
|
48
|
+
|
|
49
|
+
## 2. `scenes` canvas
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
wji canvas create scenes --json | jq -r .id # → SC; bind wji.canvases.scenes
|
|
53
|
+
wji canvas add title -c SC -t "S01 便利店店内" --at 0,0
|
|
54
|
+
wji canvas add image -c SC -n "S01 sheet" -m "<image model>" -r 16:9 --at 400,0 --prompt-file /tmp/S01-sheet.txt # → SS1
|
|
55
|
+
wji canvas add image -c SC -n "S01 lighting 监控回放绿" --from SS1 -m "<image model>" -r 16:9 \
|
|
56
|
+
-p "@image1 is this exact space; keep structure, materials and wear identical; change only the lighting: <lighting prompt>. Empty scene, no people, cinematic film still"
|
|
57
|
+
# props: same, white background, `handheld scale` etc. in the prompt
|
|
58
|
+
wji canvas add image -c SC -n "P01 sheet" -m "<image model>" -r 16:9 --at 400,700 --prompt-file /tmp/P01-sheet.txt
|
|
59
|
+
wji canvas add image -c SC -n "P01 state 接在主机上" --from <P01 sheet> -m "<image model>" -r 16:9 -p "@image1 is the prop to reproduce exactly. <state prompt>, pure white background, no people, no hands"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Variants: `--from` the parent scene's sheet node, prompt = parent master view + `changes` +
|
|
63
|
+
`keep the structure, materials and wear identical to @image1`.
|
|
64
|
+
|
|
65
|
+
After generation: inspect (no people / hands, one space across panels), attach
|
|
66
|
+
(`--add-images <sheet> <variants…> --icon <sheet>`), bind `scenes.S01.wji.nodes.sheet`,
|
|
67
|
+
`scenes.S01.wji.assets.sheet`, `scenes.S01.wji.assets.lighting.<state>`.
|
|
68
|
+
|
|
69
|
+
## 3. `E01` canvas
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
wji canvas create E01 --json | jq -r .id # → E1; bind --ep 1 wji.canvasId
|
|
73
|
+
# row 0 — the sheets this episode uses, as display nodes (assets already generated in stages 2–3)
|
|
74
|
+
wji canvas add image -c E1 -n "C01 sheet" --asset <C01 sheet asset> --at 0,0 --json | jq -r .id # → D_C01
|
|
75
|
+
SD bind <project> --ep 1 wji.displayNodes.C01:sheet D_C01
|
|
76
|
+
wji canvas add image -c E1 -n "S02 sheet" --asset <S02 sheet asset> --at 500,0 … # D_S02, D_C03, D_P01 …
|
|
77
|
+
wji canvas add audio -c E1 -n "C01 voice" --asset <C01 voice asset> --at 2000,0 # D_C01v (only if a voice exists)
|
|
78
|
+
wji canvas add dataset -c E1 --dataset <C01 dataset id> --at 0,300 # optional: the character card, for people reading the canvas
|
|
79
|
+
|
|
80
|
+
# row 1 — segment E01-01
|
|
81
|
+
SD prompt <project> segment E01-01 # reference plan per keyframe + video prompt skeleton
|
|
82
|
+
wji canvas add title -c E1 -t "E01-01 · 雨棚 · 15 s" --at 0,700
|
|
83
|
+
wji canvas add image -c E1 -n "E01-01 f1" --from D_S02 D_C01 D_C03 D_P01 -m "<image model>" -r 9:16 --at 400,700 \
|
|
84
|
+
--prompt-file /tmp/E01-01-f1.txt # → K1 … K5
|
|
85
|
+
SD bind <project> --ep 1 storyboard.segments.E01-01.wji.nodes.keyframes.0 K1
|
|
86
|
+
wji canvas gen K1 --yes --wait # first segment: generate, download, inspect, fix, then the rest of the segment
|
|
87
|
+
wji canvas add video -c E1 -n "E01-01" --from K1 K2 K3 K4 K5 D_C01v -m minimax-h3-ref -r 9:16 -d 15 \
|
|
88
|
+
--prompt-file /tmp/E01-01-prompt.txt --json | jq -r .id # → VID1
|
|
89
|
+
wji canvas add text -c E1 -n "E01-01 prompt" --text-file /tmp/E01-01-prompt.txt
|
|
90
|
+
wji canvas gen VID1 # prints the cost and refuses → tell the user → then --yes --wait (or -auto)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The keyframe prompt file is the plan's prefix (`@image1 is the environment …; @image2 is the
|
|
94
|
+
character sheet of one person …`) followed by the cut's `frame`. Reference order in `--from` must
|
|
95
|
+
match the plan's labels — `wji canvas get K1` shows `@image1 ← D_S02` etc.; fix with
|
|
96
|
+
disconnect/connect if it does not.
|
|
97
|
+
|
|
98
|
+
Video models, one per `params.video`: `h3` → `minimax-h3-ref`, `seedance` → `seedance-2.5-ref`,
|
|
99
|
+
`seedance2` → `seedance-2.0-ref`, `seedance2fast` → `seedance-2.0-fast-ref`, `wan` → `wan-3.0-ref`.
|
|
100
|
+
`prompt segment` prints the right one under `video.model` with the resolution already in that
|
|
101
|
+
model's spelling — copy both rather than typing them, and `wji models get <name>` confirms the caps.
|
|
102
|
+
Pass `-d` **only in `videoDuration: fixed`** (it switches `autoDuration` off, which is what pins the
|
|
103
|
+
clip to the storyboard); in `auto`, leave it out. `minimax-h3-ref` has no `autoDuration`, so it is
|
|
104
|
+
always `-d`.
|
|
105
|
+
|
|
106
|
+
**Connect the voices too.** Everyone who speaks in the segment brings their voice asset as an audio
|
|
107
|
+
reference — `canvas add audio --asset <voiceAsset>` once per character on the episode canvas, then
|
|
108
|
+
`--from` them **after** the pictures (and after the clip reference, if there is one: `canvas connect`
|
|
109
|
+
labels each edge as it is made, and `wji canvas connect <prev video node> <this video node>` prints
|
|
110
|
+
`as @video1`, which is how to check the numbering landed where the prompt expects). They become `@audio1…M` (their own series, so a voice
|
|
111
|
+
connected after three sheets is `@audio1`, not `@image4`), and the prompt attributes every one of
|
|
112
|
+
that character's lines to the label. Caps: 3 audio references on `minimax-h3-ref` and the Seedance
|
|
113
|
+
2.0 pair, 5 on `wan-3.0-ref`, 10 on `seedance-2.5-ref`. `prompt segment` prints the whole list,
|
|
114
|
+
pictures then voices, in the order to connect them; drop them only if the model shows no audio
|
|
115
|
+
reference support (`params.voiceSamples: false`).
|
|
116
|
+
|
|
117
|
+
Sheets mode (`params.references: sheets`, no keyframes — **the default**) — the video node's
|
|
118
|
+
`--from` are the sheet display nodes then the voice display nodes, in the order `prompt segment`
|
|
119
|
+
prints, and with `videoDuration: auto` there is no `-d`:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
wji canvas add video -c E1 -n "E01-01" --from D_S01 D_C01 D_P01 D_C01_VOICE -m seedance-2.5-ref -r 9:16 \
|
|
123
|
+
--resolution 480p --prompt-file /tmp/E01-01-prompt.txt # resolution values are case-sensitive per model
|
|
124
|
+
# D_S01 D_C01 D_P01 → @image1 @image2 @image3 · D_C01_VOICE → @audio1
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The segment's **soundtrack node** (Seed Audio; `params.audioTrack`, default `bed`) sits beside the
|
|
128
|
+
video node — no `--from` for a bed, the voice display nodes in speaking order for `--full`:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
SD prompt <project> audio E01-01 > /tmp/E01-01-audio.txt # timecoded ambience / sfx / music
|
|
132
|
+
wji canvas add audio -c E1 -n "E01-01 track" -m seed-audio-1.0 --prompt-file /tmp/E01-01-audio.txt --json | jq -r .id # → A1
|
|
133
|
+
SD bind <project> --ep 1 storyboard.segments.E01-01.wji.nodes.track A1
|
|
134
|
+
wji canvas gen A1 --yes --wait # ~0.15 credits a minute; attach: fs set <shot dataset> --add-images <asset>
|
|
135
|
+
# --full: wji canvas add audio … --from D_C02_VOICE D_C01_VOICE (→ @Audio1 @Audio2, the order the prompt names them)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`wan` mode, one clip per segment (the model speaks the dialogue itself, so no voice nodes):
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
wji canvas add video -c E1 -n "E01-01" --from K1 K2 K3 -m wan-3.0-ref -r 9:16 -d 15 \
|
|
142
|
+
--resolution 480P --prompt-file /tmp/E01-01-prompt.txt
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`wan-3.0-ref` takes at most **10** reference images and whole-second durations (2–30 s); the
|
|
146
|
+
`timing` gate already refuses a segment that breaks either rule. `--set audio=false` turns the
|
|
147
|
+
generated sound off if you are laying your own track.
|
|
148
|
+
|
|
149
|
+
`wan-3.0-ref` rejections from DashScope's green-net (`DataInspectionFailed`) are random and free —
|
|
150
|
+
retry the same node 8–12 times, then shorten the prompt (see `stage-storyboard.md`).
|
|
151
|
+
|
|
152
|
+
Queue: FREE accounts run 3 jobs at once — submit 3 keyframes, `wji history get <id> --wait` (or
|
|
153
|
+
`wji canvas get <node>` until `done`), submit the next 3. A 429 was rejected before charging;
|
|
154
|
+
wait, don't loop.
|
|
155
|
+
|
|
156
|
+
After the clip: `wji fs set <E01-01 shot dataset> --add-images K1a K2a … --icon K1a --set primaryVideo=<clip asset>`,
|
|
157
|
+
bind `storyboard.segments.E01-01.wji.assets.video`, then `SD manifest <project> --ep 1`.
|
|
158
|
+
|
|
159
|
+
## Reference order after `connect`
|
|
160
|
+
|
|
161
|
+
WJI numbers connected references **per type and in edge order** — `@image1 @image2 …` for pictures,
|
|
162
|
+
`@video1 …` for clips, `@audio1 …` for the character voices — and that numbering is what the prompt
|
|
163
|
+
addresses. So a voice node connected alongside three sheets is `@audio1`, not `@image4`.
|
|
164
|
+
|
|
165
|
+
References are numbered by edge creation order. `canvas connect` appends, so adding a sheet later
|
|
166
|
+
puts it *last* even if the legend says `@image2`. To restore the legend order, `disconnect` the
|
|
167
|
+
edges that should come after it and `connect` them again in order — then `canvas get <video>`
|
|
168
|
+
must print `@image1 ← <scene>`, `@image2 ← <person>` … exactly as `prompt segment` lists them.
|
|
169
|
+
|
|
170
|
+
## Waiting for long clips
|
|
171
|
+
|
|
172
|
+
`canvas gen --wait` gives up after 600 s by default and a 25–30 s Seedance clip can take longer;
|
|
173
|
+
the task keeps running. Pass `--timeout 900`, or pick it up with `wji history get <id> --wait` —
|
|
174
|
+
never resubmit a node whose status is still `generating`.
|
|
175
|
+
|
|
176
|
+
## Measured prices (2026-09, one FREE account — re-check with `canvas gen` without `--yes`)
|
|
177
|
+
|
|
178
|
+
With `params.videoReferences: previous`, the previous segment's **video node** is `--from`'d
|
|
179
|
+
directly — it already carries the clip, so no display node is needed, and segment k cannot be built
|
|
180
|
+
until k−1 has generated.
|
|
181
|
+
|
|
182
|
+
| Generation | Credits |
|
|
183
|
+
| --- | --- |
|
|
184
|
+
| gpt-image-2.5-sunburst 1:1 1k (headshot, keyframe) | 18.3 |
|
|
185
|
+
| gpt-image-2.5-sunburst 16:9 1080p (sheet) | 14.34 |
|
|
186
|
+
| wan-3.0-ref 480P | 15 / s (15 s = 225) |
|
|
187
|
+
| minimax-h3-ref 480P | 15 / s (15 s = 225) |
|
|
188
|
+
| seedance-2.5-ref 480p, auto duration | ≈ 31 / s, billed on the real length (≈30 s = 900–930) |
|
|
189
|
+
|
|
190
|
+
The Seedance 2.0 pair was not price-measured here; `canvas gen` without `--yes` quotes before
|
|
191
|
+
charging, and `seedance-2.0-fast-ref` is the cheap one — use it for a draft pass of a shot you
|
|
192
|
+
expect to re-cut, then re-run the approved segments on 2.5.
|
|
193
|
+
|
|
194
|
+
A rejected submission (content filter, real-person check, 429) is not charged.
|
|
195
|
+
|
|
196
|
+
## Cleaning up
|
|
197
|
+
|
|
198
|
+
`wji canvas rm` and `wji fs rm` are destructive — name the targets in the chat and wait for a yes
|
|
199
|
+
(the `wji` skill rules). Never delete a node whose asset is attached to a dataset without saying so.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Motion craft — what happens over the seconds, and how the prompt says it
|
|
2
|
+
|
|
3
|
+
The method behind `motion`, `cameraNote`, `sound` and the prompt-hygiene rules, distilled from
|
|
4
|
+
the user's `short-drama-video-prompts` skill. The frame says how a cut starts; **the motion
|
|
5
|
+
sentence says what changes between the start and the end boundary**, and the prompt is delivery
|
|
6
|
+
text for a machine, not prose for a reader.
|
|
7
|
+
|
|
8
|
+
## 1. The seven parts of a motion (gates `motion`, `sound`)
|
|
9
|
+
|
|
10
|
+
1. **Start anchor** — the start boundary, in the present tense, static: "her hands are crossed on
|
|
11
|
+
her knees, her eyes on the puddle". Never "she is about to stand" (that is already motion).
|
|
12
|
+
2. **Ordered subject motion** — `motion.trigger` (the cue: a sound, a line, a look), `motion.action`
|
|
13
|
+
(one visible state chain: who, what, direction, contact, landing — a hand-over names the giver,
|
|
14
|
+
the receiver, the hand and where the object lands) and `motion.result` (the end state, or
|
|
15
|
+
`hold`). Causal order, not a list: "hearing the latch, her eyes go to the door first; her left
|
|
16
|
+
hand stops on the page; only then does her back leave the chair". "Slowly, naturally,
|
|
17
|
+
cinematic" are not paths.
|
|
18
|
+
3. **Performance arc** — never emotion labels in sequence (calm → tense → shocked). Trigger →
|
|
19
|
+
what is received → one or two visible signals in a channel the size can read (gaze, breath,
|
|
20
|
+
body set, object handling) → the decision (an action taken or withheld) → the landing at the
|
|
21
|
+
end boundary. A wide cannot carry an eyelid; a close-up cannot carry a full-body retreat.
|
|
22
|
+
Keeping still is a valid performance when it is the character's strategy.
|
|
23
|
+
4. **Camera** — `cameraNote`. A lock-off is written like a move: the framing, **what still moves
|
|
24
|
+
inside it**, how long it holds (`hold`). An empty camera line is read as "free to drift", and
|
|
25
|
+
the model grows a push-in nobody asked for. A move names its `motivation` (reveal / pressure
|
|
26
|
+
/ alignment / relationship / transition / stillness), its `trigger`, its `path` and tempo, and
|
|
27
|
+
its `endFraming` inside the cut's boundaries. Lock and move never rule the same interval
|
|
28
|
+
without a stated transition. One camera idea per cut; camera words are dialect-specific
|
|
29
|
+
(`CAMERAS` is H3's list, `CAMERAS_ZH` wan's) — do not carry a term validated on one model to
|
|
30
|
+
another.
|
|
31
|
+
5. **Environment** — only motion that touches the subject or carries a cue: wind on a curtain,
|
|
32
|
+
steam, a reflection. Nothing invented for liveliness; weather or damage that is not in the
|
|
33
|
+
accepted state does not appear.
|
|
34
|
+
6. **Sound** — `segment.sound`: `ambience` (the room tone, **identical across every segment of a
|
|
35
|
+
scene** — separately generated clips each invent their own, and every cut point then "whooshes"
|
|
36
|
+
into a new room), `sfx` pinned to a cut, `music` as `N/A` or an intent (where it enters, what it
|
|
37
|
+
sits under — music is implemented on the timeline, not burned into a clip). For a same-pass
|
|
38
|
+
model the sound section is a **complete timeline**: every voice event in order with speaker and
|
|
39
|
+
spoken language, ambience or silence between them, closed with the exclusions the script
|
|
40
|
+
declared. Left undefined, the seconds fill with sound the model chose.
|
|
41
|
+
7. **End report** — the `end` boundary, field by field. A "more natural ending" in the prompt does
|
|
42
|
+
not override it; if the motion cannot reach it, the storyboard changes, not the boundary.
|
|
43
|
+
|
|
44
|
+
## 2. Timing is arithmetic (gate `timing`)
|
|
45
|
+
|
|
46
|
+
The cut seconds are the explicit timing plan and they sum to the segment. Both directions are
|
|
47
|
+
defects: **overflow** is truncated — the closing action, the line's tail and the end pose go with
|
|
48
|
+
it; **shortfall** is not a held frame — the model fills the unallocated seconds with motion that
|
|
49
|
+
has no source. A line needs a lead-in before the mouth opens (`speechLeadSeconds`, 0.5) and a
|
|
50
|
+
landing after it; a 4.0 s line does not fit a 4 s cut. Measured on H3 Chinese: ~4.1 speakable
|
|
51
|
+
characters a second, with rushing first and silent truncation after — lengthen the cut, split
|
|
52
|
+
it, or ask the script to cut the line; never quicken the delivery to make the sum work.
|
|
53
|
+
|
|
54
|
+
## 3. Delivery text carries only what is to be filmed (gate `prompt-hygiene`)
|
|
55
|
+
|
|
56
|
+
Inside the prompt there is no room for how the work was done:
|
|
57
|
+
|
|
58
|
+
| never in the prompt | why |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| file names, versions, paths (`sheet_v3.png`) | rendered as text on screen |
|
|
61
|
+
| entity ids, segment ids, rule ids, status words | the same, or read as an instruction to draw them |
|
|
62
|
+
| sketch references ("as in panel 2"), retake notes ("fix the hands this time") | meaningless to the model, and "hands" becomes a subject |
|
|
63
|
+
| walls of negatives ("no extra people, no deformed hands, no text…") | the nouns become the picture; write the positive fact instead ("only the two of them in frame, both hands complete and visible") |
|
|
64
|
+
| `…` left from the skeleton | an unfilled slot |
|
|
65
|
+
|
|
66
|
+
Bind on **every** mention or on none. In sheets mode a person is `@imageK` in every shot they
|
|
67
|
+
are in; bound once and then "she" is read as two different people. The skeleton does this for the
|
|
68
|
+
lines; the gate checks it per shot.
|
|
69
|
+
|
|
70
|
+
**Subtitles are off unless asked.** Same-pass models add captions on their own; every prompt
|
|
71
|
+
says so in its own language (`no subtitles, no captions, no on-screen dialogue text` / `全程无字幕`)
|
|
72
|
+
— `params.subtitles: true` to allow them. Readable on-screen text (a prop with `textPolicy:
|
|
73
|
+
readable`) is exact, everywhere it is shown, and never cancelled by a global "no text".
|
|
74
|
+
|
|
75
|
+
## 4. Per model, measured
|
|
76
|
+
|
|
77
|
+
**MiniMax H3** (`minimax-h3-ref`). Structured fields in English, dialogue kept in the original
|
|
78
|
+
language inside `<d>[Chinese] …</d>` — only the line, no parenthetical, no seconds. On first
|
|
79
|
+
mention a speaker is placed on- or off-screen with a timbre; **when another face is on screen
|
|
80
|
+
during a line, write that they `do not speak; lips remain completely closed`** — 3/3 correct
|
|
81
|
+
lip-sync against 2/3 without it, because the model puts the mouth on the most visible face; better
|
|
82
|
+
still, have the non-speaker turned away or out of frame. `non_diegetic_music: N/A` when there is
|
|
83
|
+
no score (omitting it produced music). Cut timestamps land near but not exactly; `<scenetrans>`
|
|
84
|
+
carries a line across an in-generation cut, `<cutoff>` ends a clip mid-line only when the script
|
|
85
|
+
wants it. Duration is any integer 4–15 (WJI's form: 5–15); first/last-frame inputs and reference
|
|
86
|
+
inputs are mutually exclusive, so a start frame plus sheets all go in as references.
|
|
87
|
+
|
|
88
|
+
**Seedance 2.5 / 2.0** (`seedance-*-ref`). `镜头 k [0:00–0:03]` timelines with no gaps and the
|
|
89
|
+
last endpoint equal to the total; bind on every mention; 2.5 takes `extend` (continue from an
|
|
90
|
+
actual clip plus its actual tail frame as `@image1`) and `edit`; tail frames improve the last
|
|
91
|
+
frame's landing but hand the path between two frames to interpolation — an action the cut exists
|
|
92
|
+
for must not rest on that gap. Two-frame chaining is not available on WJI today; `videoReferences:
|
|
93
|
+
previous` passes the previous clip only.
|
|
94
|
+
|
|
95
|
+
**Seed Audio 1.0** (`seed-audio-1.0`) — the soundtrack node. One prompt is a mini script:
|
|
96
|
+
name the environment, each element and how the scene unfolds; `[start s:end s]` in front of an
|
|
97
|
+
element pins it to that interval (100 ms precision), which is how the bed lines up with the cuts
|
|
98
|
+
and how music is made to duck, swell or fall silent at a moment ("Let the music drop before the
|
|
99
|
+
key line" is the documented idiom). Up to 120 s per generation, 2048 characters, three reference
|
|
100
|
+
voices as `@Audio1..3` **or** one reference image, never both; a reference clip is under 30 s.
|
|
101
|
+
Ask for `instrumental` when there are to be no vocals, and say "no dialogue" on a bed — left
|
|
102
|
+
open, it invents a narrator. `prompt audio` derives all of this from `segment.sound`.
|
|
103
|
+
|
|
104
|
+
**Wan 3.0** (`wan-3.0-ref`). Chinese prompt, same-pass audio, the 音频 line is the whole sound
|
|
105
|
+
design; the content filter judges the assembled prompt's *length* (`stage-storyboard.md`), so the
|
|
106
|
+
motion and camera clauses stay terse.
|
|
107
|
+
|
|
108
|
+
## 5. Self-check before generating
|
|
109
|
+
|
|
110
|
+
Does the prompt start from the exact start boundary and restate only what this execution needs?
|
|
111
|
+
Is every person and prop that acts, reacts or is handed over resolvable — bound or described? Do
|
|
112
|
+
two people on screen resolve to two different bindings on every mention? Has every performance
|
|
113
|
+
change a trigger and a visible channel? Do the seconds add up in both directions, with the
|
|
114
|
+
lead-in? Does the sound section cover the whole cut — lines, ambience between, music declared?
|
|
115
|
+
Is there any file name, id, note or negative dump left? Would the end the prompt describes match
|
|
116
|
+
the `end` boundary field by field?
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Shot craft — how a cut earns its place
|
|
2
|
+
|
|
3
|
+
The method behind the storyboard fields added to stage 5, distilled from the user's
|
|
4
|
+
`short-drama-storyboard` skill. It applies in **both** reference modes: in `keyframes` the frame
|
|
5
|
+
becomes an image, in `sheets` it is the shot's description inside the segment prompt — either
|
|
6
|
+
way the cut carries the same shot grammar, and `prompt segment` composes it. What can be checked
|
|
7
|
+
is a gate, named per section; the rest is judgement.
|
|
8
|
+
|
|
9
|
+
## 1. A cut has one job — `purpose` (gate `shot-purpose`)
|
|
10
|
+
|
|
11
|
+
A cut exists to change what the audience knows, who holds power, the pressure in the room, the
|
|
12
|
+
space, or the rhythm. "Medium shot of her talking" is not a purpose. Design in this order:
|
|
13
|
+
|
|
14
|
+
1. find the key action in the beats the cut claims — an act, a line, a discovery, a refusal, a
|
|
15
|
+
hand-over, a reveal;
|
|
16
|
+
2. say what changes for the audience or a character because of it (`purpose.change`);
|
|
17
|
+
3. decide whose experience the picture is organised from;
|
|
18
|
+
4. fix what must be visible at the start and the end;
|
|
19
|
+
5. only then choose the size, the camera move and the cut point.
|
|
20
|
+
|
|
21
|
+
`purpose.kind`: `establish` (space, who is where), `reveal` (new information enters), `evidence`
|
|
22
|
+
(the object the audience must read), `reaction` (the receiver's face or hands), `pressure`
|
|
23
|
+
(distance closes, an exit is taken), `decision` (a visible choice), `consequence` (the result
|
|
24
|
+
lands), `performance` (the line and the body that says it), `transition`.
|
|
25
|
+
|
|
26
|
+
**Cut on a change.** Adjacent cuts differ in at least one of size, angle or who is on screen —
|
|
27
|
+
the same framing twice is a jump cut with a number. **A turn needs a reader.** A cut claiming a
|
|
28
|
+
script `turn` beat or the 爽点 is a reveal-class cut (`reveal / evidence / decision /
|
|
29
|
+
consequence`), or the next cut is a `reaction` on someone who did not speak the line — a blow
|
|
30
|
+
nobody is seen to receive did not land. **The cliff cut** (the episode's last beat) is `reveal /
|
|
31
|
+
consequence / reaction / pressure`; it never resolves.
|
|
32
|
+
|
|
33
|
+
## 2. The size ladder
|
|
34
|
+
|
|
35
|
+
| 景别 | what it carries |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| 远景 `extreme-wide` | geography, the person swallowed by the space; no expression |
|
|
38
|
+
| 全景 `wide` | the room, who controls the door, group power |
|
|
39
|
+
| 中景 `medium` | interaction, hands, two-person strategy, blocking |
|
|
40
|
+
| 近景 `close` | a decision, evidence, a hidden reaction |
|
|
41
|
+
| 特写 `extreme-close` | one face, one hand, one wound — the only fact in frame; the space is gone |
|
|
42
|
+
|
|
43
|
+
A scene opens one step wider than it will play, lands on its **working size** on the second
|
|
44
|
+
cut, then steps a size up or down around it; a wide or an extreme close-up is an excursion,
|
|
45
|
+
used once and returned from. Do not use the size as an emotion dial — the question is always
|
|
46
|
+
*where does the information the audience must read live*: on the knuckles, give the extreme
|
|
47
|
+
close-up; in the distance between two people, do not cut in. A segment that only tightens has
|
|
48
|
+
nowhere to go by its middle (`storyboard-advice`).
|
|
49
|
+
|
|
50
|
+
**9:16 narrows the ladder.** Wides carry information sideways, and a phone has a third of the
|
|
51
|
+
width. Vertical drama plays in medium / close / extreme-close, and space is built in **depth**:
|
|
52
|
+
foreground, mid-ground, background — a doorframe, a counter edge, a shoulder in front, the room
|
|
53
|
+
behind (`foreground`, `background`). A wide on 9:16 must say why (`note`) or carry a `background`
|
|
54
|
+
that does the geography.
|
|
55
|
+
|
|
56
|
+
## 3. Three axes, three fields (gate `framing-axis`)
|
|
57
|
+
|
|
58
|
+
"A motivated angle" hides three separate decisions, and the common accident is writing 俯拍 when
|
|
59
|
+
what was meant was "from behind her shoulder".
|
|
60
|
+
|
|
61
|
+
| field | vocabulary | what it answers |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| `angle` | `front` 正面 · `three-quarter` 斜侧 · `profile` 正侧 · `rear-three-quarter` 后斜侧 · `back` 背面 | how much face the audience may read, and whose side they stand on |
|
|
64
|
+
| `height` | `ground` · `low` 仰 · `eye` 平视 · `high` 俯 · `top` | who is bigger than whom this instant — `eye` is a *choice* for equals |
|
|
65
|
+
| `focal` | the lens (`FOCAL_BY_SIZE` or your own) | how far apart two people look |
|
|
66
|
+
|
|
67
|
+
They do not derive from each other: a low angle from behind is "we follow him as he grows", a
|
|
68
|
+
low angle from the front is "he is coming down on us"; a long lens on a wide flattens two people
|
|
69
|
+
across a room into one. Height is expensive on 9:16 — a tilt eats the vertical room the person
|
|
70
|
+
has — so carry power with angle and distance first.
|
|
71
|
+
|
|
72
|
+
## 4. The axis — `segment.axis`, `axisSide`, `facing`
|
|
73
|
+
|
|
74
|
+
The 轴线 is the line between two named people. Write it as three checkable assertions, not an
|
|
75
|
+
adjective:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
"axis": { "between": ["C01", "C02"], "workingSide": "the customer side of the counter, camera looking at the clerk over the oden warmer",
|
|
79
|
+
"screenLeft": "C02", "screenRight": "C01" }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- **Bare left / right always means screen left / right.** A person's own side carries the
|
|
83
|
+
subject: "her right hand", "his left shoulder". Mixing the two readings is the usual cause of a
|
|
84
|
+
reversed reverse-shot, and every sentence looks fine on its own.
|
|
85
|
+
- **Reverse shots are complementary**: if A faces `screen-right` in her single, B faces
|
|
86
|
+
`screen-left` in his. Two singles facing the same way read as both looking at a third person.
|
|
87
|
+
Match the eyeline height to the real height difference; an asymmetric pair (one higher, one
|
|
88
|
+
tighter) is a statement of power — make it on purpose.
|
|
89
|
+
- **Over-the-shoulder** names whose shoulder is in the foreground (`foreground`); that decides
|
|
90
|
+
whose shot it is.
|
|
91
|
+
- **Crossing the axis** is legal with a neutral shot, an in-shot crossing, a deliberate
|
|
92
|
+
disorientation or a re-established geography — `axisSide: cross` with a `note` that says which;
|
|
93
|
+
the new working side is then inherited by the cuts after it.
|
|
94
|
+
- Three or more people: draw the **directed relationship** first (who protects / presses /
|
|
95
|
+
watches whom, from which beat), then place bodies, facing, distance and lines of action; one
|
|
96
|
+
representative reaction beats a row of identical gasps; background people do not change sides
|
|
97
|
+
between cuts without a reason.
|
|
98
|
+
|
|
99
|
+
## 5. Start → one action → end (gate `continuity`)
|
|
100
|
+
|
|
101
|
+
Every cut has two boundaries, and the boundaries are the continuity system:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
"start": { "positions": { "C01": "behind the counter" }, "facing": { "C01": "screen-left" }, "gaze": { "C01": "at the bag" },
|
|
105
|
+
"hands": { "C01": "both hands on the counter edge" }, "heldProps": { "C01": [] }, "state": ["the bag lying on the counter"] },
|
|
106
|
+
"end": { … the same fields … }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
- `start` is written on a segment's **first** cut only; every later cut begins where the previous
|
|
110
|
+
one ended (the script derives it), and a segment in the same scene begins where the previous
|
|
111
|
+
segment ended — positions and held props are compared.
|
|
112
|
+
- Each boundary is an absolute fact readable without the last cut ("on the stool" — never "same
|
|
113
|
+
as before"). A person who enters on a cut has no start; `render segment` marks them 入画.
|
|
114
|
+
- **A prop changes hands only on an action beat.** A hand-over between two lines is teleporting.
|
|
115
|
+
- `state[]` are short visible facts ("the drawer slightly ajar", "steam rising off the bowl").
|
|
116
|
+
A state that only exists in `end` may not be named in `frame` — that is **keyframe drift**,
|
|
117
|
+
the picture already showing the result.
|
|
118
|
+
|
|
119
|
+
## 6. The frozen frame — `frame`
|
|
120
|
+
|
|
121
|
+
The frame is the **start instant**, in both modes: the still a photographer could take at
|
|
122
|
+
second 0.00 of the cut. Twelve things make it renderable without the artist inventing any of
|
|
123
|
+
them; ~400–500 characters is full, 800 is padding:
|
|
124
|
+
|
|
125
|
+
| write | or the model decides it for you |
|
|
126
|
+
| --- | --- |
|
|
127
|
+
| where each person is and how far apart | spacing drifts cut to cut, the room seems to change |
|
|
128
|
+
| foreground / mid-ground / background | depth collapses into one layer |
|
|
129
|
+
| where the eye should land (the shot's one fact) | the frame is evenly weighted, nobody knows what to look at |
|
|
130
|
+
| composition and size phrase | each cut composed at random; they do not cut together |
|
|
131
|
+
| which side of the axis, height, lens | the reverse angle does not match |
|
|
132
|
+
| where the light comes from and its quality — its *result* on the face | the key jumps between cuts of one scene |
|
|
133
|
+
| every present person's pose, facing, hands, held props | the next cut cannot pick them up |
|
|
134
|
+
| what is the same as the previous cut, in one clause | "unwritten" is read as "free to change" |
|
|
135
|
+
|
|
136
|
+
**Static test**: no ordered verbs (then / before / after that / begins to / 先 / 再 / 然后),
|
|
137
|
+
no expression *changing*, no camera move, no weather *transforming* — those belong to `motion`.
|
|
138
|
+
A held pose can imply tension; it cannot require two moments. **No names**, no ids, no file
|
|
139
|
+
names: the frame is delivery text.
|
|
140
|
+
|
|
141
|
+
Lighting: `light.direction` is relative to the camera; `light.note` describes what the light
|
|
142
|
+
*does* on the face or the object ("the cabinet glow holds the right of his face; nothing moves
|
|
143
|
+
but the light on his jaw") — the result reads more stably than the position alone, and it must
|
|
144
|
+
say whether left / right is the screen's or the subject's.
|
|
145
|
+
|
|
146
|
+
## 7. Generability (gates `filmable`, `motion`; advice in `storyboard-advice`)
|
|
147
|
+
|
|
148
|
+
A video model performs what it has seen a million times: walk in, sit, stand, turn, nod, hand
|
|
149
|
+
over, take, hold, push a door, set something down, reach. Four risk classes it does not perform:
|
|
150
|
+
|
|
151
|
+
| risk | example | rewrite |
|
|
152
|
+
| --- | --- | --- |
|
|
153
|
+
| precise interception | blocking a closing lid with a palm | close it, then keep the hand on it (two common actions + a hold) |
|
|
154
|
+
| invisible inner state | 像是听见了什么 · seems to realise | the visible action that shows it |
|
|
155
|
+
| the negative action | 没有接话 · does not press it | the action that happens instead — a hold, a hand that stays |
|
|
156
|
+
| a hand chain | four steps of two-hand work in four seconds | hand the change to an object, split the cut, or end on the result |
|
|
157
|
+
|
|
158
|
+
Drama lives in the **combination and timing** of ordinary actions, not in their precision. The
|
|
159
|
+
test: read the action to someone who has not seen the script — can they mime it at once?
|
|
160
|
+
|
|
161
|
+
## 8. Key scenes — `storyboard.visualPlans[]` (gate `visual-plan`)
|
|
162
|
+
|
|
163
|
+
Only for scenes where the directing choice changes the experience: a first appearance, a reveal
|
|
164
|
+
of identity or evidence, a reversal, the climax or the cliff. `seed storyboard` writes the
|
|
165
|
+
worksheet for the 爽点 scene and the cliff scene; before cutting them answer 戏剧转向 (`turn`),
|
|
166
|
+
观众立场 (`alignment`: where we stand at the start, where we are moved to), 空间压力
|
|
167
|
+
(`pressure`: entrances, distance, blocking, exits), 视觉推进 (`progression`: what lands first —
|
|
168
|
+
information, reaction or space), 摄影节奏 (`rhythm`: what triggers a lock, a move, a cut-in, a
|
|
169
|
+
hold), 反应落点 (`landing`: whose choice ends the scene) and 声音策略 (`sound`). Ordinary scenes
|
|
170
|
+
go straight to cuts.
|
|
171
|
+
|
|
172
|
+
## 9. Review questions
|
|
173
|
+
|
|
174
|
+
Which beats does this cut realise, omit or repeat? What has changed when it ends? Why this size
|
|
175
|
+
and this camera behaviour? Can every person stand, see and move where the space puts them? Is the
|
|
176
|
+
end a start the next cut can pick up? If this cut were deleted or merged, what story meaning would
|
|
177
|
+
be lost — and if the answer is nothing, merge it.
|