@wji.ai/cli 0.7.1 → 0.8.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/package.json +1 -1
- package/skill/short-drama/SKILL.md +22 -10
- package/skill/short-drama/reference/bgm-sfx.md +124 -0
- package/skill/short-drama/reference/canvas-recipes.md +19 -2
- package/skill/short-drama/reference/film-mixing-guideline.md +447 -0
- package/skill/short-drama/reference/mix-over-video.md +89 -0
- package/skill/short-drama/reference/operations-cli.md +1 -1
- package/skill/short-drama/reference/schema.md +4 -2
- package/skill/short-drama/reference/stage-characters.md +2 -2
- package/skill/short-drama/reference/stage-storyboard.md +29 -6
- package/skill/short-drama/reference/workspace-layout.md +2 -2
- package/skill/short-drama/scripts/selftest.mjs +54 -9
- package/skill/short-drama/scripts/short-drama.mjs +150 -12
package/package.json
CHANGED
|
@@ -211,7 +211,7 @@ Read `{baseDir}/reference/stage-characters.md`.
|
|
|
211
211
|
sheet prompt prefixed with `@image1 is the face to match`), and a **voice** audio node
|
|
212
212
|
(`seed-audio-1.0`, `--from` the headshot — the model reads the face and invents a voice for it;
|
|
213
213
|
the composed prompt asks for a dry voice, because the same model also makes rooms, scores and
|
|
214
|
-
sound effects — that is what
|
|
214
|
+
sound effects — that is what the episode score over the edit is for;
|
|
215
215
|
`prompt voice C01` composes the text: a parenthetical carrying age, identity, personality,
|
|
216
216
|
timbre, pitch, pace, accent and emotion, then the acted line).
|
|
217
217
|
Recipes in `reference/canvas-recipes.md`.
|
|
@@ -345,15 +345,27 @@ must be connected: pictures, then clips, then voices.
|
|
|
345
345
|
segment's keyframes only, inspect, then continue. Keyframes for one segment are a batch (quote
|
|
346
346
|
the total). Do not switch a project to keyframes on your own — it doubles the images to pay for
|
|
347
347
|
and approve.
|
|
348
|
-
5. **
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
348
|
+
5. **No BGM in the clips** (`params.audioTrack: post`, the default). Each segment is a separate
|
|
349
|
+
generation, so music or sound design made inside a clip stops at its last frame and cannot carry
|
|
350
|
+
across a cut. The video prompt keeps the lines, the ambience and the sfx the world makes, says
|
|
351
|
+
there is no music, and leaves out every sfx marked `post: true` (stingers, risers, whooshes,
|
|
352
|
+
impact hits). Still write `sound.music` (intent + cues) and the `post: true` hits — they are the
|
|
353
|
+
spotting notes for the score.
|
|
354
|
+
6. After each clip: `fs set <shot dataset> [--add-images <keyframes…>] --set primaryVideo=<clip>`;
|
|
355
|
+
bind asset ids.
|
|
356
|
+
7. **Score the edited episode.** When every clip is in, edit them into a locked cut (picture lock),
|
|
357
|
+
`wji asset upload` it and bind `wji.assets.edit`. `prompt score E0N [--fps 24]` prints the planned
|
|
358
|
+
spotting sheet — SMPTE rows for the scene beds, every line (where the music ducks), each
|
|
359
|
+
segment's music cues at episode time, the `post` sound design, the sfx already in the clips, the
|
|
360
|
+
hook / turns / 爽点 / cliff (起承转合) and the ≤120 s Seed Audio sections. Conform it to the edit's
|
|
361
|
+
real cuts and write the cue sheet and the section prompts (`reference/mix-over-video.md`; craft in
|
|
362
|
+
`reference/bgm-sfx.md`, loudness and terms in `reference/film-mixing-guideline.md`): BGM, BGE /
|
|
363
|
+
ambience and sound design only — never what the clips already carry. One `canvas add audio -n
|
|
364
|
+
"E0N score K" -m seed-audio-1.0 --prompt-file …` per section (~0.15 credits a minute — quote
|
|
365
|
+
first), mix the sections under the edit at their offsets, upload and bind `wji.assets.mix`.
|
|
366
|
+
`manifest --ep N` must come back clean before you call the episode done. (`audioTrack: bed` /
|
|
367
|
+
`full` instead make a Seed Audio node per segment from `prompt audio E0N-01` and put the music in
|
|
368
|
+
the clip.)
|
|
357
369
|
|
|
358
370
|
- **A failed generation is not always a bad prompt.** `wan-3.0-ref` rejections from DashScope's
|
|
359
371
|
content filter (`DataInspectionFailed`) charge nothing and are partly random — retry the same node
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# BGM timed to video + short-drama SFX
|
|
2
|
+
|
|
3
|
+
## Segment `sound` SoT
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
"sound": {
|
|
7
|
+
"ambience": "neon KTV booth hum, leather sofa creak",
|
|
8
|
+
"sfx": [
|
|
9
|
+
{ "cut": 2, "event": "wine glass tip and splash on table" },
|
|
10
|
+
{ "cut": 7, "event": "SPECIAL: cliff freeze sting — single high piano hit then silence", "post": true }
|
|
11
|
+
],
|
|
12
|
+
"music": {
|
|
13
|
+
"intent": "romantic neon slow pulse, soft keys, restrained satin bass",
|
|
14
|
+
"cues": [
|
|
15
|
+
{ "at": 1, "do": "enter", "note": "under dialogue" },
|
|
16
|
+
{ "at": "10.5s", "do": "swell", "note": "rise into kiss handoff" },
|
|
17
|
+
{ "at": 4, "do": "duck", "note": "under roast lines" },
|
|
18
|
+
{ "at": 6, "do": "drop", "note": "after climax into plea" },
|
|
19
|
+
{ "at": 7, "do": "silence", "note": "before P02 reveal" },
|
|
20
|
+
{ "at": "end", "do": "out" }
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Where it goes depends on `params.audioTrack`:
|
|
27
|
+
|
|
28
|
+
- **`post` (default)** — the clip gets only the ambience, the in-picture sfx and the lines; `music`
|
|
29
|
+
and every `post: true` sfx stay out of it. They are the spotting notes for the episode score:
|
|
30
|
+
`$SD prompt <project> score E01` lays them on the episode timeline (SMPTE) for scoring over the
|
|
31
|
+
edit (`mix-over-video.md`). A cue `at` is still a cut of *this* segment — the sheet adds the
|
|
32
|
+
segment's offset.
|
|
33
|
+
- **`bed` / `full`** — `prompt audio … --bed` / `--full` expands this into `[start s:end s]` lines
|
|
34
|
+
for a Seed Audio node per segment, and the music intent also goes into the clip prompt.
|
|
35
|
+
|
|
36
|
+
## BGM cue verbs
|
|
37
|
+
|
|
38
|
+
`enter | swell | duck | drop | silence | out`
|
|
39
|
+
|
|
40
|
+
Put mood vocabulary in `intent` + `note`:
|
|
41
|
+
|
|
42
|
+
| Want | How to write |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| rise / build | `swell` + note "intensity climb / rise into …" |
|
|
45
|
+
| drone / dread | intent "low dread drone, barely moving" + `enter`/`drop` |
|
|
46
|
+
| romantic | intent "romantic …" + `swell` on romantic beats |
|
|
47
|
+
| comedy | intent "light comedy pizzicato" + duck under punchlines |
|
|
48
|
+
| cliff | `drop` or `silence` then one special sting SFX |
|
|
49
|
+
| triumphant | intent "bright brass sting" — use sparingly |
|
|
50
|
+
|
|
51
|
+
Rules: one music intent per segment (or continuous across a scene); instrumental unless vocals are a story beat; **duck under dialogue**; hit 爽点 / cliff on purpose. Continuous texture belongs in **ambience**, not twenty music mood words.
|
|
52
|
+
|
|
53
|
+
### With a `params.cinematography` preset (sound is half the look)
|
|
54
|
+
|
|
55
|
+
Craft in `cinematography-<preset>.md`; not gated.
|
|
56
|
+
|
|
57
|
+
| preset | music / sfx |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| `low-key` | nothing extra — the usual dread / tension vocabulary |
|
|
60
|
+
| `sweet-romance` | the OST is the segment's `sound.music`, cues on the cut: `enter` on the eye-lock's last cut, `swell` on the look back / the carry / the gap closing, `silence` as the hand lands or just before a confession line (so it lands in a hush), `drop` on the 壁咚; rain on the umbrella, a heartbeat if wanted |
|
|
61
|
+
| `period-nostalgia` | diegetic music of the era — the radio, a period song on the cassette player — in `sound.sfx` or as the segment's `music` intent; cicadas in the courtyard, the bicycle bell, a street hawker, a distant train |
|
|
62
|
+
| `costume-idol` | follows `sweet-romance` for the 心动 set pieces (执手, 簪花, 共乘一马, 月下对饮, 灯会) — `enter` / `swell` / `silence`; wind, chimes, the lantern festival crowd as ambience |
|
|
63
|
+
| `costume-dark` | fire crackle, wind, rain on tiles, armour creaking, distant drums; **`silence`** in the court before a verdict; violence carried by sound and consequence rather than choreography |
|
|
64
|
+
| `scifi-hard` | hums, fans, relays, alarms, radio chatter with squelch, breathing in a helmet; **silence in vacuum** (only the suit's breathing and radio); music sparse — a low drone, a single piano line |
|
|
65
|
+
| `scifi-soft` | rain, crowds in many languages, synth hums, holographic chimes, drones passing; music synthwave / ambient pads |
|
|
66
|
+
|
|
67
|
+
### By segment grammar (`segment.grammar`, else `params.grammar`)
|
|
68
|
+
|
|
69
|
+
Craft in `grammar-faceslap.md` §3, `grammar-comedy.md` and
|
|
70
|
+
`action.md` / `action-<style>.md` ("Sound"); gate `grammar-advice` checks the 打脸 music hit.
|
|
71
|
+
|
|
72
|
+
| grammar | music / sfx |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `faceslap` | `silence` or `drop` under the insult, **`enter` / `swell` on the entrance or the proof**, full through the reaction cascade; sfx: the document slapped on the table, the gasp, the cup falling, the murmur rising |
|
|
75
|
+
| `comedy` | **silence before the punchline** (a `silence` cue or a pause in the ambience); `slapstick` — cartoon sfx on every beat (boing, whoosh, record scratch) and a comic sting after the punchline; `deadpan` — no comic sfx, often no music, the ambience (clock, fly, fridge hum) fills the hold; `romcom` — playful pops and plinks, a heartbeat, a cute sting, the OST entering on the blush |
|
|
76
|
+
| `action` | **every impact gets an sfx on its cut**; the music `drop`s out before the decisive blow; per style: `bullet-time` stretched / pitched-down sound then snap back, `gun-fu` driving low synth, `hk-kungfu` exaggerated whooshes and snaps with a comic sting, `historical-realist` metal on metal and often no score, `street-brawl` none or a low drone, `car-chase` engines then the silence after the crash |
|
|
77
|
+
|
|
78
|
+
## SFX + special short-drama FX
|
|
79
|
+
|
|
80
|
+
Every story-visible hit needs `sfx[]` tied to a **cut** (or absolute time in a hand-written prompt). Prefer concrete / onomatopoeic events.
|
|
81
|
+
|
|
82
|
+
Mark hero moments with `SPECIAL:` in `event` so QC can hear them.
|
|
83
|
+
|
|
84
|
+
**In the clip or in post?** An sfx the world makes — a glass, a door, a slap, footsteps, rain — is
|
|
85
|
+
in-clip: the video model makes it in sync with the picture. Sound design the world does not make —
|
|
86
|
+
stinger, riser, whoosh, impact hit, reverse cymbal, drone hit, the silence drop — gets `"post": true`:
|
|
87
|
+
it stays out of the clip prompt and is made over the edit, where it can land across a cut. A hit that
|
|
88
|
+
is both (the slap *and* a stinger on it) is two entries.
|
|
89
|
+
|
|
90
|
+
| Beat | Typical special FX |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| 打脸 / reveal | sharp whoosh + muted impact + brief silence |
|
|
93
|
+
| 身份揭露 | rising drone → glass-ring sting |
|
|
94
|
+
| 强宠 / romantic turn | soft shimmer / heartbeat under VO |
|
|
95
|
+
| Comedy mishap | spill / choke / bonk — diegetic if live-action |
|
|
96
|
+
| Cliffhanger | near-silence + one iconic prop sound |
|
|
97
|
+
| Transition | whip-pan whoosh (sparingly) |
|
|
98
|
+
|
|
99
|
+
Few high-value FX per segment. If the beat is only atmosphere, put it in ambience.
|
|
100
|
+
|
|
101
|
+
## Intent vocabulary bank (examples — not a closed list)
|
|
102
|
+
|
|
103
|
+
Write these into `music.intent` and cue `note`. Pair with `enter | swell | duck | drop | silence | out`. Mix freely.
|
|
104
|
+
|
|
105
|
+
**Tension / suspense:** suspense pad · ticking urgency · dread drone · cold empty room · stalking pulse · pressure build · quiet danger · held breath
|
|
106
|
+
|
|
107
|
+
**Rise / climax:** slow rise · intensity climb · heartbeat acceleration · approaching climax · swelling strings · peak hit
|
|
108
|
+
|
|
109
|
+
**Romantic:** romantic neon · soft satin · afterglow haze · tender piano · yearning guitar · candlelit hush · close whisper hush
|
|
110
|
+
|
|
111
|
+
**Comedy / farce:** light comedy pizzicato · clumsy slapstick · awkward silence bed · wink-and-nudge · drunken wobble · karaoke parody · punchline duck-and-sting
|
|
112
|
+
|
|
113
|
+
**Face-slap / twist / 爽点:** smug turnaround · reveal sting · power-flip brass · gotcha hit · vindication swell · identity-drop silence then sting
|
|
114
|
+
|
|
115
|
+
**Sad / bruised:** lonely night · soft regret · bruised tenderness · rain-on-window · hollow after
|
|
116
|
+
|
|
117
|
+
**Anger / control:** cold command · sharp authority · icy control · simmering rage · light disciplinary march
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
**Place texture:** neon booth haze · muffled corridor bass · office night hum · leather sofa creak bed · fluorescent buzz · city window night
|
|
121
|
+
|
|
122
|
+
**Transition / end:** whip cut · hard reset · freeze-frame sting · cliff hang · unresolved chord · fade-to-black
|
|
123
|
+
|
|
124
|
+
Example: `intent: "awkward comedy pizzicato under neon booth haze"` · note: `swell — intensity climb into climax` · note: `drop — freeze-frame sting then silence`
|
|
@@ -162,8 +162,11 @@ that character's lines to the label. Caps: 3 audio references on `minimax-h3-ref
|
|
|
162
162
|
pictures then voices, in the order to connect them; drop them only if the model shows no audio
|
|
163
163
|
reference support (`params.voiceSamples: false`).
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
**Soundtrack.** By default (`params.audioTrack: post`) there is **no per-segment soundtrack node**:
|
|
166
|
+
the clips carry no music, the episode is edited first, and the score + sound design are made over the
|
|
167
|
+
edit, one Seed Audio node per ≤ 120 s section (see the post recipe below). Only in `bed` / `full`
|
|
168
|
+
does each segment get a **soundtrack node** beside its video node — no `--from` for a bed, the voice
|
|
169
|
+
display nodes in speaking order for `--full`:
|
|
167
170
|
|
|
168
171
|
```bash
|
|
169
172
|
SD prompt <project> audio E01-01 > /tmp/E01-01-audio.txt # timecoded ambience / sfx / music
|
|
@@ -173,6 +176,20 @@ wji canvas gen A1 --yes --wait #
|
|
|
173
176
|
# --full: wji canvas add audio … --from D_C02_VOICE D_C01_VOICE (→ @Audio1 @Audio2, the order the prompt names them)
|
|
174
177
|
```
|
|
175
178
|
|
|
179
|
+
**Post soundtrack (`audioTrack: post`)** — after every clip is bound and the episode is edited:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
wji asset upload ./E01-edit.mp4 --json | jq -r .id # the locked edit, no music → EDIT
|
|
183
|
+
SD bind <project> --ep 1 wji.assets.edit EDIT
|
|
184
|
+
SD prompt <project> score E01 > /tmp/E01-score.md # planned spotting sheet + ≤120 s sections
|
|
185
|
+
# Sound Designer conforms it to the edit's real cuts and writes one bed prompt per section
|
|
186
|
+
wji canvas add audio -c E1 -n "E01 score 1" -m seed-audio-1.0 --prompt-file /tmp/E01-score-1.txt --json | jq -r .id
|
|
187
|
+
wji canvas gen <node> --yes --wait # ask first; ~0.15 credits a minute
|
|
188
|
+
# mix the sections under the edit at their offsets (ffmpeg), then:
|
|
189
|
+
wji asset upload ./E01-mix.mp4 --json | jq -r .id # → MIX
|
|
190
|
+
SD bind <project> --ep 1 wji.assets.mix MIX
|
|
191
|
+
```
|
|
192
|
+
|
|
176
193
|
`wan` mode, one clip per segment (the model speaks the dialogue itself, so no voice nodes):
|
|
177
194
|
|
|
178
195
|
```bash
|