diff --git a/packages/skills/orchestration/SKILL.md b/packages/skills/orchestration/SKILL.md index 51dd74c..ce4d669 100644 --- a/packages/skills/orchestration/SKILL.md +++ b/packages/skills/orchestration/SKILL.md @@ -45,7 +45,7 @@ For COMPOSE or AUTO compose segments, also apply `frontend-design` before writin ## 2.6 Narration voice -When the piece has voiceover, run `ovs speech-capabilities` and copy its executable route/model/voice/format into the Gate B plan together with the BCP-47 video language and a natural speed. Do not invent a voice id. Before Gate B, run `ovs narration fit --text ... --target ...`; revise over/under text internally before any paid synthesis. After `ovs speak`, probe the produced audio and run the same fit with `--measured`; retime scenes from the measured duration without silently shortening the approved target. If no TTS provider is configured, tell the user and explicitly choose silent delivery or wait for configuration. +When the piece has voiceover, run `ovs speech-capabilities` and copy its executable route/model/voice/format into the Gate B plan together with the BCP-47 video language and a natural speed. Do not invent a voice id. Before Gate B, run `ovs narration fit --text ... --target ...`; revise OVER-budget text internally before any paid synthesis — a read that finishes early is an accepted delivery, so pad or extend only when the trailing silence is not the ending you intended. After `ovs speak`, probe the produced audio and run the same fit with `--measured`; retime scenes from the measured duration without silently shortening the approved target. If no TTS provider is configured, tell the user and explicitly choose silent delivery or wait for configuration. TALKING-HEAD note: if a GENERATE clip already returned lip-synced built-in speech, THAT is the voice — do NOT synthesize a narration over it (a fresh TTS track desyncs from the mouth). Use `ovs speak` only for a silent clip, or for COMPOSE / EDIT / off-screen voiceover. @@ -92,7 +92,7 @@ Ingest every supplied clip from evidence (probe + transcribe/OCR-or-frame-readin ## plan.json as the editable record (all lines) — keep follow-up edits cheap -Once a draft exists, keep `project/plan.json` faithful so a later tweak only re-touches one piece (never the whole video): (1) every produced segment carries its real output under `produced_path` + `status:"done"`; (2) narration is `tracks.narration` whose lines each carry their own `produced_path`, so one line can be re-voiced alone; (3) captions are DATA in `tracks.captions.lines` ({text, start_sec, target_sec}) — NOT burned into the picture — so a typo is a one-line edit re-burned at assemble; (4) set top-level `"draft": "render/draft.mp4"`. +Once a draft exists, keep `project/plan.json` faithful so a later tweak only re-touches one piece (never the whole video): (1) every produced segment carries its real output under `produced_path` + `status:"done"`; (2) narration is `tracks.narration` whose lines each carry their own `produced_path`, so one line can be re-voiced alone; (3) captions are DATA in `tracks.captions.lines` ({text, start_sec, target_sec}) — NOT burned into the picture — so a typo is a one-line edit re-burned at assemble; (4) record delivery outputs under the reserved `_runtime` envelope (`"_runtime": {"render": {"draft": "render/draft.mp4"}}`), never as a new top-level key — unknown top-level plan fields are approval-bearing, so a root `draft` key would invalidate the recorded Gate B approval. **Local follow-up edits — make the minimal targeted change; never redo the whole video.** Once a `plan.json` is present and the user asks to change ONE local thing (a segment's narration / caption / text, a trim, volume / speed, a single shot swap), edit ONLY the matching entry in `plan.json` and re-produce ONLY what it touched (`ovs speak` for that one line, `ovs draft` for that one compose segment, or `ovs edit` for that one cut), then re-assemble. Do NOT re-author the whole EDL and DO NOT regenerate a segment whose `status` is `done` that the user did not touch. Fall back to a full re-plan only when the request genuinely restructures the timeline. diff --git a/packages/skills/stage-assemble/SKILL.md b/packages/skills/stage-assemble/SKILL.md index e203010..832c532 100644 --- a/packages/skills/stage-assemble/SKILL.md +++ b/packages/skills/stage-assemble/SKILL.md @@ -11,22 +11,24 @@ How to execute a validated `project/plan.json` into one finished file. By the ti Iterate segments in `order`. For each, produce its `produced_path` according to `source`, then write that path + `status:"done"` back into the segment so a resume never re-produces it: -- **edit** → `stage-edit`: `ovs edit trim` the `input_id` to `[in_sec, out_sec]` → `project/cuts/.mp4`. +- **edit** → `stage-edit`: `ovs edit trim` the `input_id` to `[in_sec, out_sec]` → `project/cuts/.mp4`. Those are the EDL's field names, not flags — the command is `ovs edit trim --start --end --out project/cuts/.mp4`. - **compose** → `stage-compose`: build a small visual-only manifest-owned composition for `spec.kind` (title card, lower-third, stat card, captions) under `project/compositions//` → run `ovs draft project/compositions/ --out project/parts/.mp4 --quality draft --report project/reports/-compose-report.json`. This keeps compose segments on the same manifest/source/check/video-QA path as standalone COMPOSE while still letting the assembler own narration and loudness. - **generate** → `stage-generate` (+ `stage-consistency` for recurring characters): only AFTER gate C. `ovs video`/`ovs image` → `project/assets/.mp4`. For `operation:"edit"`, pass the exact original reference video and obey top-level `references` plus `edit_strategy`; never widen it into regeneration. A failed/unknown paid attempt is not an automatic retry. Preserve completed siblings and require a new output path for any later authorized attempt. - **provided** → use `spec.asset_id` as-is (probe it first; conform aspect/fps if needed). Billable `generate` segments must not run before gate C has confirmed the count from `cost_estimate`. Produce cheap/free segments (edit, compose, provided) freely. +Only `compose` segments need snapshot/frame QA evidence, because their artifact is HTML. An `edit`/`generate`/`provided` segment is captured by its own `produced_path` file the moment that file exists — never run a composition QA phase on one, and never treat it as unfinished work because it has no frame evidence. + ## Step 2 — Assemble in ffmpeg tiers (the default path) Assemble deterministically, bottom-up. This tiered order is the default; it is predictable and cheap, and keeps each clip's real audio intact: 1. **Primary track** — `ovs edit concat` the primary-layer `produced_path`s in `order` → `project/render/primary.mp4`. Conform aspect/fps on the way in if sources differ. -2. **Overlays / bg** — for each overlay/bg segment, `ovs edit overlay` its part onto the primary over the window of the segment named in `over` (title cards, lower-thirds, logos). Composed layers are VISUAL-ONLY — they must not carry their own narration audio. **This includes a compose segment that IS the primary track (a full-video composition): render it SILENT — do not put a narration `