visual-plan · diff

git:20261012.3ce8edb to git:20261015.07749c7

64 added, 85 removed. Audit A to A.

---
name: visual-plan
- description: Decide what the viewer sees on every line of a video where words carry it — one treatment per line (the speaker, a punch-in, B-roll, stock, an icon, native text, a designed graphic, a generated shot, a screen, or nothing on purpose) with the word it lands on and why, balanced over the whole video, written to plan.visuals and handed to the skill that builds each row. Use after the cut is locked in a talking head, tutorial, explainer, review, podcast clip or voiceover ad, or when asked what to show over a script. Triggers: "minh hoạ", "kế hoạch hình ảnh", "câu này hiện gì", "b-roll cho script", "visual plan", "illustrate the script", "làm giống video mẫu", "thêm hình cho lời nói".
+ description: Decide what the viewer sees on every line of a talking video: one treatment per line (speaker, punch-in, B-roll, stock, icon, text, graphic, screen, nothing) anchored to a word, balanced, written to plan.visuals. Triggers: "minh hoạ", "kế hoạch hình ảnh", "câu này hiện gì", "b-roll cho script", "visual plan", "thêm hình cho lời nói".
---
# Visual plan
- Reply in the user's language. With a `[Scope]` (Send to Agent), plan only those lines (`bc:edit-workflow`).
- Each building skill (`bc:stock-images`, `bc:motion-graphics`, `bc:effects`, `bc:captions-text`) decides well for
- one moment; this skill decides for the whole video first, so the treatments vary, land on the words and add up to
- the density and the look the video needs. It plans and researches; the building skills build.
+ Building skills decide one moment; this plan decides the whole video first, so treatments vary, land on words and
+ reach the density and look needed. Plan and research here; the building skills build.
## 0. When and where
- The stage `visuals`, added by the plan after the cut is locked (the words and their frames no longer move) and before
- sound and captions (SFX and the caption mode depend on it):
+ Stage `visuals`, added at the story stage when words carry the video (none for a music montage or a vlog told by
+ pictures). It runs after the cut is locked (words and frames fixed) and before sound and captions (SFX and caption
+ mode depend on it):
```sh
- # --merge replaces top-level fields whole: read plan.stages (context get), add the key, write all of stages back.
+ # --merge replaces top-level fields whole: read plan.stages, add the key, write all of stages back.
# stages.json: {"stages": {…the recipe's stages…, "visuals": {"after": "voiceover", "required": true, "why": "talking video"}}}
bashcut project set-data plan stages.json --merge --base-rev N
```
- Add it at the story stage for any video whose words carry it; skip it (no stage) for a music montage or a vlog told
- by the pictures. A BashCut that ignores `after` lists the stage before review: do it after the cut anyway.
+ If BashCut lists the stage before review (ignoring `after`), still do it after the cut.
## 1. Read what is said and what exists
- - **A written script** (`bashcut.vlog:hook-script` wrote `plan.beats` [{id, section, text, job, onScreen,
- treatment?, source}]): start from it, do not re-derive. `bashcut script check` gives each beat's heard frames
- (`at`, `end`, `heardShare`); join them with `plan.beats` by `id` (`context get` → plan counts; the beats from
- `project data plan`). Each beat with an `onScreen` note is a draft row: `line` = its text, `from`/`to` = `at`/`end`,
- `beat` = its id, `show` = the note, `treatment` = its `treatment` or the table's name for what the note asks. Then
- only check them (§2–§3) and fill the gaps: a beat without a note, a long beat that needs two rows, a beat with
- `heardShare` below about 0.6 (it was re-worded or cut: take its words from what is heard).
- - **No script**: `bashcut transcript words --from F --to F2`. Split into lines at sentence or idea boundaries; keep
- each line's first and last word frames.
- - What the footage already shows: the survey's described shots (`bashcut review coverage`, `media describe`), and
- `timeline sheet --cuts --text` for what is on screen now.
- - The targets: a reference's measured profile (`bc:style-study`: picture change interval, graphics a minute, share
- of time the speaker is on screen, text mode), else the recipe's ranges, else the kit's (`bc:motion-graphics` §3,
- `bc:effects`). Write each target with its source.
+ - **A written script** (`plan.beats` from `bashcut.vlog:hook-script`): start from it, do not re-derive. Join
+ `script check` (`at`, `end`, `heardShare` per beat) with `plan.beats` by `id`. A beat with an `onScreen` note is a
+ draft row: `line` = text, `from`/`to` = `at`/`end`, `beat` = id, `show` = the note, `treatment` = its `treatment`
+ or the table's name for what the note asks. Only check them (§2–§3) and fill gaps: a beat without a note, a long
+ beat needing two rows, `heardShare` below ~0.6 (re-worded or cut: take its words from what is heard).
+ - **No script**: split `transcript words` into lines at sentence or idea boundaries, with first and last word frames.
+ - What exists: described shots (`review coverage`, `media describe`), on screen now (`timeline sheet --cuts --text`).
+ - Targets, each with its source: a reference's measured profile (`bc:style-study`), else the recipe's ranges, else
+ the kit's (`bc:motion-graphics` §3, `bc:effects`).
## 2. One treatment per line
- Ask of every line: what does the viewer imagine here, and does the picture already show it? Then choose.
+ Ask of every line: what does the viewer imagine, and does the picture already show it?
| Treatment | Shows | Built with |
|---|---|---|
- | `speaker` | the face carries it: an opinion, a feeling, the punchline | nothing added |
- | `punch-in` | the same shot, closer, on the line's strongest word | `bc:beat-cut`, `bc:effects` |
- | `own-broll` | a shot from the user's footage of what is said | `bc:rough-cut`, `media place` |
- | `stock` | a photo or video of a thing, place or action the footage lacks | `bc:stock-images` |
- | `icon` | a small symbol: money, time, place, yes/no, an arrow | `bc:stock-images` (Iconify) |
- | `text` | the keyword, a number or a label as native text | `bc:captions-text` |
- | `graphic` | designed motion: kinetic type, a counter or chart, a pointer clicking, a mock screen, a card, a diagram, the speaker shrinking into a card | `bc:motion-graphics` → a `graphics.render` plugin |
+ | `speaker` | the face carries it: opinion, feeling, punchline | nothing added |
+ | `punch-in` | same shot, closer, on the strongest word | `bc:beat-cut`, `bc:effects` |
+ | `own-broll` | the user's shot of what is said | `bc:rough-cut`, `media place` |
+ | `stock` | photo or video of a thing, place or action the footage lacks | `bc:stock-images` |
+ | `icon` | small symbol: money, time, place, yes/no, arrow | `bc:stock-images` (Iconify) |
+ | `text` | keyword, number or label as native text | `bc:captions-text` |
+ | `graphic` | designed motion: kinetic type, counter, chart, pointer, mock screen, card, diagram | `bc:motion-graphics` |
| `generated` | a shot that cannot be filmed or found | `bashcut.vlog:scene-prompt`, `library generate` |
- | `screen` | a screen recording or screenshot of what is explained | `media place`, `bc:effects` (focus) |
- | `none` | the line stays bare on purpose so the next one lands | — |
+ | `screen` | screen recording or screenshot of what is explained | `media place`, `bc:effects` (focus) |
+ | `none` | bare on purpose so the next line lands | — |
- These are the common ones, not a closed list: a new treatment is fine with a name, what it shows and who builds it.
- Combinations are one treatment (a `stock` photo with a `text` keyword on it is `stock`, with `show` saying both).
+ Not a closed list: a new treatment needs a name, what it shows and who builds it. A combination is one treatment (a
+ `stock` photo with a `text` keyword is `stock`; `show` says both).
Guides, not rules:
- - Concrete words (a thing, a number, a place, a step, a comparison) can be shown; abstract or emotional lines are
- usually the speaker's.
- - A number reads best counted or written; a process as steps or a diagram; a comparison side by side; a named object
- as the user's own shot first, then stock, then an icon.
- - Anchor each row to one word (`at`): the visual lands on it, entrances end on its first frame. Hold until the idea's
- narration ends, unless the treatment is an accent.
- - Text and captions never say the same thing twice: decide the caption mode here (full captions, keywords only,
- none) and write it into `stages.captions.rules` (with the rest of `stages`, as in §0).
+ - Concrete words (thing, number, place, step, comparison) can be shown; abstract or emotional lines are usually the
+ speaker's.
+ - A number reads best counted or written, a process as steps or a diagram, a comparison side by side, a named object
+ as the user's own shot, then stock, then an icon.
+ - Anchor each row to one word (`at`): entrances end on its first frame. Hold until the idea's narration ends,
+ unless it is an accent.
+ - Text and captions never say the same thing twice: decide the caption mode here (full, keywords only, none) and
+ write it into `stages.captions.rules` (with all of `stages`, as in §0).
## 3. Balance the whole video
- Lay the rows end to end and check them against the targets before researching anything:
- - **Density and interval**: picture changes and graphics per minute within the target; nothing in the hook's first
+ Check the rows end to end against the targets before researching:
+ - **Density and interval**: picture changes and graphics per minute within target; nothing in the hook's first
1–3 s that does not serve the hook.
- - **Variety**: the same treatment on three lines in a row reads as a template unless the reference does exactly
- that; vary the device within a treatment too (a counter, then a card, then type).
- - **Presence**: the share of time the speaker is on screen within the target; keep the face on lines that carry
- emotion, the hook's promise and the payoff.
- - **Faces and safe areas**: nothing covers the face while it speaks the point (`media subjects`).
+ - **Variety**: one treatment on three lines in a row reads as a template unless the reference does exactly that;
+ vary the device within it too.
+ - **Presence**: speaker screen share within target; keep the face on emotion, the hook's promise and the payoff.
+ - **Faces**: nothing covers the face while it speaks the point (`media subjects`).
- Change rows until it fits, and say which targets you left on purpose (`"deliberate": true` with the reason).
+ Change rows until it fits; mark targets left on purpose `"deliberate": true` with the reason.
## 4. Research and look
- For rows that need something the project does not have:
- - `stock`, `icon`: 3–6 candidates per row (`bc:stock-images` §1 and Icons), all candidates of a batch on one
- contact sheet; look, pick, import the pick (`media import`).
- - `own-broll`: the matching described shots; check the frame (`media frames --sheet`).
- - `graphic`: the graphics plugin's examples and catalog (`bashcut.hyperframes:hyperframes` §1); note which one each
- row starts from, or that it is new. Design happens when it is built.
- - `generated`: say the prompt idea; generation and any price wait for the build (paid providers: `--dry-run`).
+ Rows that need what the project lacks:
+ - `stock`, `icon`: 3–6 candidates per row (`bc:stock-images` §1 and Icons), a batch on one contact sheet; look,
+ pick, import.
+ - `own-broll`: matching described shots; check the frame (`media frames --sheet`).
+ - `graphic`: note each row's starting example from the plugin's catalog (`bashcut.hyperframes:hyperframes` §1),
+ or new; design happens at build.
+ - `generated`: the prompt idea; generation and any price wait for the build.
- A row with no good candidate changes treatment (often to `text` or `speaker`) rather than keeping a weak picture.
+ No good candidate: change treatment (often to `text` or `speaker`); never keep a weak picture.
## 5. Write the plan
- ```sh
- bashcut project set-data plan visuals.json --merge --base-rev N
- ```
-
- `visuals` is a list of rows, in time order:
+ `project set-data plan visuals.json --merge --base-rev N`; `visuals` rows in time order:
```json
{"visuals": [
{"line": "one of the best ways", "from": 0, "to": 36, "at": 12, "treatment": "graphic",
"show": "serif lead-in, 'Best ways' slams in lime", "why": "the hook's claim, made to read in 1 s"},
- {"line": "to start getting more views", "from": 36, "to": 81, "at": 66, "treatment": "graphic",
- "show": "paper card turns in, 'more views' builds word by word", "why": "pattern break after 1.2 s of face"},
{"line": "which can boost", "from": 186, "to": 216, "at": 201, "treatment": "punch-in",
"show": "1.12× on 'boost'", "why": "a strong verb the face sells"}
]}
```
- `from`/`to`/`at` are timeline frames; `show` is one phrase of what the viewer sees; `why` is the line's need, not the
- treatment's name; `beat` (the script beat's id, when there is a script) ties the row to its ON SCREEN note. A row
- that departs from the note says so in `why` ("note asked for a price card; the board in shot already shows it"). Where the picture comes from lives on the imported media, not here.
+ Frames are timeline frames; `show` is one phrase of what is seen; `why` is the line's need, not the treatment's
+ name; `beat` is the script beat's id. A row departing from its note says so in `why` ("note asked for a
+ price card; the board in shot already shows it"). The picture's source lives on the imported media, not here.
- Gate: when the brief asks to approve visuals, or rows need paid generation, request
- `bashcut checkpoint request visuals --summary "<rows by treatment, targets>" --attach <contact sheet>`; otherwise go
- on (`bc:edit-workflow`, Gates).
+ Gate: when the brief asks to approve visuals or rows need paid generation, `checkpoint request visuals --summary
+ "<rows by treatment, targets>" --attach <contact sheet>`; otherwise go on.
## 6. Hand off and close
- Build in this order, each row by its skill, reading `plan.visuals` for its rows: picture that replaces a moment
- (`own-broll`, `stock` video, `screen`) → `graphic` → `stock` photos and `icon` → `text` → `punch-in`. Sound for each
- visual (a pop, a whoosh, a click) is `bc:audio-mix`'s, at the row's `at`.
-
- ```sh
- bashcut run append stage --stage visuals --status done --evidence "plan.visuals 24 rows;renders/visuals-candidates.jpg"
- ```
-
- The draft review compares the timeline with `plan.visuals` (a row not built, a visual off its word by more than
- 0.3 s, a row built over a face).
+ Build in this order, each row by its skill: picture that replaces a moment (`own-broll`, `stock` video, `screen`)
+ → `graphic` → `stock` photos and `icon` → `text` → `punch-in`. Each visual's sound is `bc:audio-mix`'s, at the
+ row's `at`. Record the stage (`run append stage --stage visuals`, evidence: row count,
+ candidates sheet). The draft review checks every row against the timeline (`bc:review`).
## Report
- The targets and where they came from, the rows by treatment with the shares (speaker on screen, graphics a minute,
- mean picture change), what you researched and rejected, the caption mode, and the targets you left on purpose.
+ Targets and sources, rows by treatment with shares (speaker on screen, graphics a minute, mean picture change),
+ what you rejected, the caption mode, targets left on purpose.