@amaster.ai/pi-video-gen 0.1.29 → 0.1.31

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.
@@ -1,229 +1,52 @@
1
1
  ---
2
2
  name: video-gen
3
- description: "Create video from existing clips, direct video-model calls, batch render scripts, FFmpeg timelines, or Remotion projects. Use when the deliverable is a video; use pi-image-gen for still images."
3
+ description: "Create or edit videos using existing media, video models, FFmpeg timelines or Remotion. Use for clips, video assembly, product films and animated explainers; use image-gen for still-image deliverables."
4
4
  ---
5
5
 
6
6
  # Video generation
7
7
 
8
- Choose each shot's source independently: existing video, a model-generated clip, or graphics in a Remotion project. In a proposed workflow, name the actual tool at each handoff, including `image_generate` for missing portraits or reference frames; a package or skill name alone does not specify the executable tool. Then choose the assembly path:
8
+ Choose each shot's source independently: existing media, a model-generated clip, or graphics in an editable Remotion project. Name the executable tool at each handoff. The video model comes from `pi-video-gen.defaultModel`; image generation uses pi-image-gen's active model. `<outputDir>` is the configured `pi-video-gen.outputDir`, defaulting to `<cwd>/.video-gen`; `/video-gen doctor` reports its resolved path.
9
9
 
10
- - **C0 local concat** — `video_compose` joins compatible existing MP4 clips.
11
- - **Timeline render** — `video_compose` locally turns images/screenshots and existing video clips into a video with overlays, motion, transitions, soft or burned subtitles, source audio, and optional BGM. Narration is an optional network feature.
12
- - **Remotion compose** — `video_compose` renders a trusted editable React project with existing media and optional generated clips; read [the Remotion handoff](references/remotion-handoff.md) when using this path.
13
- - **Direct model calls** — `video_generate` creates each missing model clip; use `video_compose` afterwards if the clips need assembly.
14
- - **Batch render script** — `video_render` runs a prepared `render-input.json` with existing and generated shots, durable remote-task recovery and optional assembly; read [the render script reference](references/video-render-workflow.md) when using this path.
10
+ ## Route the task
15
11
 
16
- The AI video model is fixed by `pi-video-gen.defaultModel`; generated images use pi-image-gen's active model.
12
+ Honor the user's specified method and existing usable material. Read only the relevant assembly guide:
17
13
 
18
- ## A. Workflow rules
14
+ | Goal | Tool and reference |
15
+ |---|---|
16
+ | Join compatible MP4 clips without re-encoding | `video_compose`; follow Compatible clip concat below |
17
+ | Create one or several model clips under direct control | `video_generate`; follow Direct model clips below; use `video_compose` if assembly is needed |
18
+ | Assemble images/screenshots and clips with overlays, transitions or narration | `video_compose`; read [Timeline composition](references/timeline-compose.md) |
19
+ | Animate exact UI, charts, typography or editable graphics | `video_compose`; read [Remotion handoff](references/remotion-handoff.md) |
20
+ | Execute a prepared batch with saved remote tasks and optional assembly | `video_render`; read [render script and recovery](references/video-render-workflow.md), plus the selected assembly guide |
19
21
 
20
- 0. **Route first.** Choose the right flow before anything:
22
+ For a product film, demonstration, capability showcase or authored explainer, read [film direction](references/film-direction.md) before designing scenes. An explicitly supplied edit, single clip or straightforward assembly follows its supplied instructions without that planning stage. For continuous UI/graphic handoffs, film direction routes to the motion-authoring guide. Read [shot planning and frame preparation](references/shot-planning.md) only when recurring identities, narrative continuity or missing reference frames require it.
21
23
 
22
- | User goal | Flow |
23
- |---|---|
24
- | Existing local mp4 clips to join | `video_compose` (C0 — lossless, local, no paid models) |
25
- | One or several model clips under direct control | `video_generate` for each missing clip; `video_compose` if assembly is needed |
26
- | Prepared script with generated and existing shots, recovery and assembly | `video_render` |
27
- | Promo/explainer from images, screenshots & clips | `video_compose` (TimelineSpec — local mixed-media render; optional network TTS) |
28
- | Precise UI, charts, typography or editable frame animation | `video_compose` with a trusted Remotion project, or `video_render` with Remotion assembly when the script also generates shots |
24
+ ## Execution rules
29
25
 
30
- **Creative planning.** For a product launch film, product demo, or authored explainer, read [film direction](references/film-direction.md) before designing scenes, including when all media is local. Follow its direction, rhythm, sound and review workflow alongside the selected assembly path. A single requested clip or a straightforward assembly follows its supplied instructions without this planning stage.
26
+ - **Preserve scope.** Reuse suitable assets; generate or replace images when needed or explicitly requested. Use `image_generate` for those images and read the installed image-gen skill before using it. If it is unavailable, disclose the gap and continue only with suitable existing material or an agreed alternative. Any user restriction on generation charges also applies to image calls.
27
+ - **Model preflight.** Before preparing new generated-video requests, call `video_capabilities` and respect the active model's durations, ratios, audio, frame and trusted-asset support. Local-only work needs no video-model credentials or capability call. For Seedance recognizable portraits or provider-managed portrait/material choices, read [Seedance assets](references/seedance-assets.md) before selecting inputs or preparing a paid call.
28
+ - **Paid scope.** Before the first paid video call, state the generated shot count and durations, provider/account, model and exact asset choices. Obtain approval unless that exact scope is already authorized; reuse approval for unchanged resumes using the saved job identity. A material scope change needs agreement. A prepared batch uses one initial `video_render` call per requested version; resume the same spec after interruption. Additional prototypes or versions must serve the requested task.
29
+ - **Cost.** State call counts and durations. If the user requests prices, verify current provider pricing and state the assumptions; if pricing cannot be verified, say so rather than guessing. Do not promise a fixed completion time.
30
+ - **Immutable jobs.** Revised inputs or frozen project source require a NEW job directory. Rerunning the SAME spec resumes completed shots without resubmitting them. Preserve saved clips and remote handles; never delete shot outputs to force a retry. Missing or changed committed artifacts fail integrity checks rather than being silently regenerated.
31
+ - **Degradation.** When a capability or preflight check fails, explain supported alternatives and obtain agreement for a materially changed result. Omit unsupported native-audio cues; if requested audio would be lost, resolve that gap before generation. Narration uploads and silent-subtitle fallbacks follow the Timeline guide's disclosure and agreement rules.
32
+ - **Cancellation.** Stopping local polling/rendering may leave a remote task running and billable; Ark remote cancellation is unverified. Report that limitation.
31
33
 
32
- 1. **Local flows use their assembly guide.** For C0 follow §A0; for Timeline follow §A1; for Remotion read its handoff. All-local scripts need no video-model credentials or paid-model confirmation. Use `image_generate` only when source images are missing.
33
- 2. **AI preflight only for generated shots.** Call `video_capabilities` and respect the active model's duration, audio, frame and trusted-asset support. Confirm `image_generate` is available only when source frames need to be generated (`/video-gen doctor` checks; config health is `/image-gen list`).
34
- 3. **Pick direct or scripted generation.** Use `video_generate` directly for each model clip when the agent is controlling the calls. Use `video_render` for a prepared script that automates per-shot generation, persistence, recovery and assembly. A project may mix generated shots with existing footage without generating it again.
35
- 4. **Plan only what the film needs.** For a story with recurring characters or shot-to-shot continuity, write a shot book in conversation using §B. For other clips, work from the supplied media or shot instructions. Existing frames can be reused; generate missing portraits or first/last frames with `image_generate` using §C when they improve consistency.
36
- 5. **Confirm paid scope.** Before the first paid video call, state the generated shot count and durations, provider/account, model and asset choices. Reuse an existing approval for the same scope; get agreement when the scope changes. For a scripted film, write one render spec and call `video_render` once; a resumed job reruns the same spec.
37
- 6. **Cost honesty.** AI video calls are paid and take minutes each. Never state amounts (prices change); state call counts and durations.
38
- 7. **Revisions.** The render spec is immutable per job directory. Text-stage revisions happen in chat (regenerate frames as needed); a revised film goes in a NEW job directory. NEVER suggest "delete shots/<id>/ and rerender" — that breaks downstream dependencies. Rerunning the SAME spec path resumes an interrupted job (finished shots don't re-bill).
39
- 8. **Degradation negotiation.** If generation preflight fails (e.g. last frame unsupported), present the options (switch model / edit spec / `allowDegradations`) and let the user choose. Never degrade silently. When the model's `nativeAudio` is false, omit audio cues and obtain acceptance of silence if audio was requested.
40
- 9. **Cancellation honesty.** Interrupting stops local polling only — remote tasks may keep running and billable (Ark cancellation is unverified). Say so.
41
-
42
- ## A0. C0 — composing existing clips (`video_compose`)
34
+ ## Compatible clip concat
43
35
 
44
36
  1. **Tell the user first**: clip count, order, output location (`<jobDir>/final_video.mp4`), `mode: "copy"`. This is LOCAL compute — do not use the paid-model confirmation script for it.
45
37
  2. Write `<jobDir>/compose-input.json` (`{"clips":[{"id":"c1","path":"/abs/a.mp4"},…],"output":{"mode":"copy"}}`) under the video-gen output dir, then call `video_compose` ONCE. Keep source clips outside `<jobDir>/clips/`; that directory and `final_video.mp4` are reserved pipeline outputs, and a fresh job refuses either conflict.
46
- 3. **Only promise** lossless concat of compatible MP4s (C0). **Never promise** trimming, transitions, overlays, subtitles, TTS, BGM, or re-encoding **for the C0 path** — those live in the Timeline path (A1 below), not here; do not hint at them for `compose-input.json`.
38
+ 3. **Only promise** lossless concat of compatible MP4s (C0). **Never promise** trimming, transitions, overlays, subtitles, TTS, BGM, or re-encoding **for the C0 path** — those live in [Timeline composition](references/timeline-compose.md), not here; do not hint at them for `compose-input.json`.
47
39
  4. On any ordered stream incompatibility across all tracks (codec/resolution/fps/timebase/pix_fmt/sample-rate/audio layout), hand the exact ffprobe differences back to the user/agent: re-encode the odd clips first. NEVER silently transcode, and NEVER fall back to `video_generate`/`video_render` as a workaround.
48
40
  5. Interrupted? Rerun the SAME path (fingerprint-verified resume / cached). Changed clips or order? NEW job directory. A completed final video is hash-bound; if it is missing or changed, restore the exact artifact or start a NEW job.
49
41
 
50
- ## A1. Timeline compose (`video_compose` with `timeline-input.json`)
51
-
52
- Use for promos/explainers from still images and existing clips. Media rendering is local and uses no paid video model. If narration is requested, disclose that the explicit `edge-tts:<voice>` option sends narration text to Microsoft before using it.
53
-
54
- 1. **Collect existing images/screenshots/clips first**, and use `image_generate` only for missing visual material. Keep all source media outside the job directory, then author `<jobDir>/timeline-input.json`. `assets/`, `overlays/`, `audio/`, `segments/`, `qc/`, generated tracks, subtitles, and `final_video.mp4` are reserved pipeline outputs; a fresh job refuses any conflicts rather than deleting them.
55
- ```jsonc
56
- {
57
- "title": "产品宣传片",
58
- "output": { "resolution": "1920x1080", "fps": 25, "codec": "h264" },
59
- "voice": "edge-tts:zh-CN-YunyangNeural", // explicit opt-in: narration text is sent to Microsoft
60
- "ttsFailureMode": "fail", // or "silent-subtitles" only after the user accepts that degradation
61
- "subtitles": { "mode": "burn", "fontSize": 36,
62
- "textColor": "#ffffff", "backgroundColor": "#000000", "backgroundOpacity": 0.55 },
63
- "segments": [
64
- {
65
- "id": "intro",
66
- "image": "/abs/frame-1.png",
67
- "durationSec": 5, // image only: may be "auto" from narration
68
- "motion": "kenburns-in", // image only
69
- "transitionTo": { "type": "xfade", "style": "fade", "durationSec": 0.8 },
70
- "overlay": { "title": "标题", "subtitle": "副标题", "position": "bottom-left" },
71
- "narration": "这一段的中文旁白文本"
72
- },
73
- {
74
- "id": "demo",
75
- "video": "/abs/demo.mp4",
76
- "trimStartSec": 2.5,
77
- "durationSec": 6, // video always uses a numeric duration
78
- "fit": "contain", // contain | cover
79
- "sourceAudio": { "muted": false, "volume": 0.25 }
80
- }
81
- ]
82
- }
83
- ```
84
- 2. **Chinese text NEVER comes from an image model** — titles/subtitles go in `overlay` and are rendered locally via SVG (no garbled CJK).
85
- 3. **Paid-model confirmation is unnecessary** for the local media render, but still show the segment count and total planned duration before calling `video_compose`. Obtain explicit agreement before sending narration text to Edge TTS.
86
- 4. Every segment contains exactly one of `image` or `video`. Video segments are normalized to the output resolution/fps, may be trimmed/scaled, and mix their source audio with narration before optional BGM. Video source audio without a stream degrades to silence; `sourceAudio.muted: true` or `volume: 0` disables it. A video's numeric `durationSec` is its fixed trim window; narration that does not fit is rejected instead of extending it.
87
- 5. Narration uses Edge TTS only with an explicit `edge-tts:<voice>` selection; its text is sent to Microsoft. Measured audio duration drives image `durationSec: "auto"`; subtitles use each segment's actual video timing. `subtitles.mode` defaults to `"soft"` (`mov_text`); `"burn"` renders the configured font/color/background directly into each narrated segment. TTS failures stop the job by default. Use `ttsFailureMode: "silent-subtitles"` only as an explicit degradation choice; it keeps the subtitle track and fills that segment with silence. Once accepted, that degradation is cached for the immutable job; create a NEW job to retry real narration.
88
- 6. On completion, review the QC frames in `<jobDir>/qc/` yourself (Read the PNGs) before showing the result — flipped/overlapping text only shows up visually. Soft `mov_text` subtitles are not burned into those PNGs; the pipeline separately verifies that the subtitle stream exists and that the SRT cues match the resolved segment timeline.
89
- 7. The spec is immutable per job: rerunning the same path resumes only regular job-local artifacts whose manifest hashes still match; changes require a NEW job directory. A committed artifact that is missing or changed is rejected rather than regenerated underneath cached downstream outputs. A completed manifest with any missing artifact hash is rejected; an interrupted manifest invalidates unverified downstream hashes before rebuilding an uncommitted upstream artifact.
90
-
91
- ## A2. Seedance trusted portraits and provider-managed assets
92
-
93
- Before any paid Seedance call that may contain a recognizable human face:
94
-
95
- 1. **Classify the source.** Ordinary uploaded or generated images/videos of a recognizable real person may be rejected by Seedance's privacy checks. Do not treat a local file path or public URL as an authorized portrait.
96
- 2. **Search preset personas when needed.** If the user has not already chosen an identity, run this skill's `scripts/search-seedance-personas.mjs` with `--query "<space-separated traits>" --framing half|full --limit 5`. Use `half` for close/medium portrait shots and `full` when the whole body or body movement must be visible. Present the bounded matches with label, short bio, framing, and Asset ID; let the user choose before a paid call. The script is the access path; do not load the entire 3.6 MB JSON catalog into context.
97
- 3. **Use the exact trusted asset.** For a catalog choice, copy the returned `selectedAssetId`. Otherwise ask the user for a preset-avatar or Active authorized-person `asset-...` ID from the current Ark account/project. Catalog IDs were observed on 2026-08-24 and are not documented as permanent or cross-account. If the active account rejects one, ask the user to copy the current ID from that account's virtual-avatar library.
98
- 4. **Preserve modality order.** Put provider assets in `referenceAssets` as `{ "modality": "image|video|audio", "assetId": "asset-..." }`. Order is significant within each modality. In the prompt say `Image 1`, `Video 1`, or `Audio 1`; never expose or cite the Asset ID in prompt prose. For the built-in Seedance 2.0 models, keep each request within 9 image references total (local frames plus image assets), 3 video assets, and 3 audio assets.
99
- 5. **Reconfirm the paid context.** Approval is scoped to the exact asset list, provider/account context, model, clip count, and duration. An unchanged resumed job retains its existing approval. A changed asset, account/project, provider, model, or job requires a new confirmation.
100
- 6. **Keep onboarding out of scope.** This package submits already-created assets. It does not perform identity verification, authorization H5 flows, asset activation, upload, or asset-library management.
101
-
102
- Official references: [preset avatars](https://docs.volcengine.com/docs/82379/2608626?lang=zh#preset-avatar), [authorized-person assets](https://docs.volcengine.com/docs/82379/2223965?lang=zh), and [Seedance asset request format](https://console.volcengine.com/ark/region:cn-beijing/docs/82379/2333589?projectName=default&lang=zh#d9a7d853).
103
-
104
- ## A3. Seedance public image/video/audio materials
105
-
106
- When the user asks for built-in Seedance materials, action references, camera references, visual styles, environments, characters, or sample voices, read [`references/seedance-public-material-library.md`](references/seedance-public-material-library.md) completely before proposing choices. Use the exact Chinese display labels from that catalog, copy its exact Asset IDs into `referenceAssets`, and keep the selected media in modality order. These IDs were read from the public material cards, not from the separate virtual-avatar library. If the active account rejects a listed ID, re-open the experience center and copy the current card ID instead of guessing or substituting a media URL.
107
-
108
- ## A4. Direct AI clips (`video_generate`)
109
-
110
- 1. Complete the AI preflight in §A and resolve any Seedance asset requirements in §A2–A3. Use the active tool schema for parameters.
111
- 2. Fill structured prompt fields: `visuals` is camera/framing, `action` is in-frame movement, `scene` is setting, `effects` is time-varying appearance, and `audio` is sound/dialogue. `visuals` and `action` are required; without `firstFrame`, `style` and `scene` are also required. The tool assembles the prompt.
112
- 3. If source frames must be generated, read the image-gen skill first, generate them and record the returned paths. Show the prepared clip, duration, exact assets and provider/account/model context. Obtain explicit approval for this paid request unless already authorized unchanged.
113
- 4. Call `video_generate` for each missing clip. If interrupted, resume that clip with its returned `jobId`; `prompt` is not needed on resume. For an ambiguous submission, check the provider console and use `/video-gen recover <jobId>` before any retry: `reset` only a confirmed-absent task or `adopt` its existing task ID. If the clips need assembly, choose the C0, Timeline or Remotion `video_compose` path after generation.
114
- 5. Finish after the saved video is returned and reviewed. Report its path and any accepted degradation; if visual verification is unavailable, state that limitation.
115
-
116
- ## B. Shot book (VideoProject) — authoring reference
117
-
118
- Use a shot book when narrative continuity benefits from one. Author it in conversation; save to `<jobDir>/project.json` when the project needs an editable planning record.
119
-
120
- ```jsonc
121
- {
122
- "title": "...", "style": "Cartoon",
123
- "characters": [{ "id": "alice", "visible": true,
124
- "appearance": "long blonde hair, blue eyes, slender", // static features
125
- "outfit": "red scarf, black leather jacket" }], // dynamic features
126
- "shots": [{
127
- "id": "s1",
128
- "intent": "Wide shot, rainy alley. <Alice> enters from the left, stops under the streetlamp…",
129
- "scene": "Rainy alley at night, neon signs, wet pavement", // optional: the shot's setting
130
- "firstFrame": "…pure static description of the FIRST frame…",
131
- "lastFrame": "…(optional) pure static description of the LAST frame…",
132
- "visuals": "Static camera, wide shot from across the street…", // camera + framing only
133
- "action": "A woman with long blonde hair and a red scarf walks in from the left…",
134
- "effects": "…(optional) time-varying visuals: rain picks up, neon reflections intensify…",
135
- "audio": "[Sound Effect] rain, distant traffic. [Speaker] Alice (soft): \"We're here.\"",
136
- "visibleCharacters": ["alice"],
137
- "durationSec": 5,
138
- "continuityGroup": "alley",
139
- "startFrameFromShotId": "s0", // optional: this shot's frame builds on s0's frame
140
- "continuityNote": "In s0's frame Alice faces away; front view missing"
141
- }]
142
- }
143
- ```
144
-
145
- Field rules:
146
-
147
- - **Give each story shot a purpose** (establish / emotion / reaction). Choose framing to serve that purpose; use close-ups for emotion and wide shots for context when appropriate.
148
- - **Keep dialogue within the selected model's duration and audio support.** Character names in `intent` may be wrapped in angle brackets: `<Alice>`.
149
- - **firstFrame / lastFrame are pure static snapshots** — no ongoing actions ("he is sitting, leaning forward", NOT "he is about to stand"). Include shot size, angle, composition, who is where and facing which way.
150
- - **visuals = camera + framing only** (movement, shot size, angle, focus); **action = in-frame movement only**. Split them — they become separate labeled sections in the assembled prompt. Refer to characters by visible traits ("the woman in the red scarf"), never by name.
151
- - **scene is the shot's setting**, copied verbatim into the render spec's `prompt.scene`. Optional when the first frame fully anchors the setting; write it when the setting carries mood/lighting the frame may not convey.
152
- - **effects is for what a static frame cannot carry**: transformations, lighting/atmosphere shifts, particles, slow motion. Omit when the shot is visually static.
153
- - **lastFrame needed when**: composition/focus changes drastically, a character enters or turns to face camera, a major reveal happens. Otherwise omit it.
154
- - **Use `continuityGroup` where shots share a space or visual base.** Start a new group when the setting or camera relationship warrants it.
155
- - **continuityGroup** = shots sharing a space/base image; **startFrameFromShotId** pins a specific parent frame for composition; **continuityNote** says what the parent frame lacks (the frame prompt must then keep the background and replace those elements). Self-check: parent shot EXISTS, comes EARLIER, same continuityGroup, no cycles.
156
- - **audio** uses `[Sound Effect] …` / `[Speaker] Name (Emotion): "line"` format.
157
- - **durationSec and all capability values come from `video_capabilities`** — never from memory or this document. Durations, resolutions, ratios, audio and frame support differ per model and change over time.
158
- - **Behavioral quirks worth knowing** (still verify with `video_capabilities`): some models have no native audio (omit audio cues or the render is silent); some cannot do last-frame interpolation (never pass lastFrame to them); HappyHorse takes a first frame OR reference images in one call, not both — cite references in the prompt as `[Image 1]`, `[Image 2]`, …
159
-
160
- ## C. Image operation manual (via `image_generate`)
161
-
162
- When a shot book needs missing character portraits or first/last frames, call `image_generate` to create those images before `video_render`. Follow the **pi-image-gen skill** for parameters, sizes, `n`, and edit labeling; it is the single authority. Two video-specific handoff rules:
163
-
164
- - **Never assume a saved filename**: the actual extension follows the MIME type and collisions get `-v2`. **The returned absolute path is the only truth** — record it immediately in `assets.json` (see below) and reference it in the render spec.
165
- - `assets.json` in the job dir: `{ "assets": { "<shotId>/<part>": { "sourcePath": "…" } } }` mapping semantic assets (e.g. `s1/firstFrame`, `alice/front`) to real paths.
166
-
167
- **Character portrait views (generate only those the planned frames need)**:
168
-
169
- - front (text-to-image): `Generate a full-body, front-view portrait of character {identifier} based on the following description, with a pure white background. Use a wide 16:9 landscape canvas, not a vertical portrait canvas. The character should be centered in the image, occupying the middle of the wide frame with enough horizontal empty space. Gazing straight ahead. Standing with arms relaxed at sides. Natural expression. Features: {appearance}; {outfit}. Style: {style}`
170
- - side (edit with front as reference): `Generate a full-body, side-view portrait of character {identifier} based on the provided front-view portrait, with a pure white background. Use a wide 16:9 landscape canvas, not a vertical portrait canvas. The character should be centered in the image, occupying the middle of the wide frame with enough horizontal empty space. Facing left. Standing with arms relaxed at sides.`
171
- - back (edit with front as reference): `Generate a full-body, back-view portrait of character {identifier} based on the provided front-view portrait, with a pure white background. Use a wide 16:9 landscape canvas, not a vertical portrait canvas. The character should be centered in the image, occupying the middle of the wide frame with enough horizontal empty space. No facial features should be visible.`
172
-
173
- If an optional side/back view fails after one retry, reuse an existing suitable view. Characters with `visible: false` get no portraits.
174
-
175
- **Reference selection for frames**: candidates = portraits of visible characters (ONE view each, chosen by facing) + continuity frames. Pick a SMALL set of the most relevant ones — same camera/group first, most recent frames first, drop redundant near-duplicates, prefer the portrait when a character newly appears. How many images a call accepts is pi-image-gen's authority (its skill/tool description), not this document's.
176
-
177
- **Frame prompt assembly**: prefix each reference image with its role, then the frame description mapping elements to images:
178
-
179
- ```
180
- Image 1: A front view portrait of Alice.
181
- Image 2: [alley] Wide shot of the rainy alley from shot s1.
182
- Create an image based on the following description: <firstFrame text>. The alley background should reference Image 2; Alice's appearance should reference Image 1.
183
- ```
184
-
185
- ## D. Assemble a batch render spec when using `video_render`
186
-
187
- Write `<outputDir>/<jobId>/render-input.json` (jobId: letters/digits/dash/underscore). This is a generated-shot example; for local `videoPath` shots and optional Timeline or Remotion assembly, read [the render script reference](references/video-render-workflow.md):
188
-
189
- ```jsonc
190
- {
191
- "title": "…", "aspectRatio": "16:9",
192
- "style": "Cartoon, warm palette, soft shading", // film-level look — from the shot book's style
193
- "characters": [ // film-level registry — id + appearance/outfit merged
194
- { "id": "alice", "description": "long blonde hair, blue eyes, slender; red scarf, black leather jacket" }
195
- ],
196
- "consistency": "Faces, hair and outfits stay identical across the shot, no morphing or drift.",
197
- "negative": "no text, watermarks, or subtitles",
198
- "shots": [{
199
- "id": "s1",
200
- "prompt": { // from the shot book's fields, verbatim
201
- "scene": "Rainy alley at night, neon signs, wet pavement", // omit when the first frame says it all
202
- "visuals": "Static camera, wide shot from across the street",
203
- "action": "The woman in the red scarf walks in from the left, stops under the streetlamp",
204
- "effects": "Rain picks up halfway through; neon reflections ripple in puddles",
205
- "audio": "[Sound Effect] rain, distant traffic. [Speaker] Alice (soft): \"We're here.\"",
206
- "visibleCharacters": ["alice"]
207
- },
208
- "firstFramePath": "<project>/path/from/assets.json.png", // optional for asset-only shots
209
- "lastFramePath": "<project>/optional.png",
210
- "referenceAssets": [
211
- { "modality": "image", "assetId": "asset-avatar-from-current-account" },
212
- { "modality": "audio", "assetId": "asset-voice-from-current-account" }
213
- ],
214
- "durationSec": 5
215
- }]
216
- }
217
- ```
218
-
219
- The plugin assembles each shot's labeled prompt (`[Style]` / `[Character]` / `[Scene]` / `[Visuals]` / `[Action]` / `[Effects]` / `[Audio]` + consistency and negative directives) — never pre-join a prompt string yourself. Validation fails before any paid call when: a generated shot has neither `firstFramePath` nor `referenceAssets`, `visuals`/`action` are empty, `visibleCharacters` references an id missing from `characters`, or a shot without `firstFramePath` lacks `style`/`scene`. Film-level `style`/`consistency`/`negative` apply to every shot — write them once; shot-level `scene` repeats per shot even when consecutive shots share a location (each shot is submitted independently).
220
-
221
- Every reference-frame path that is present must resolve to a regular png/jpg/webp file inside the session cwd. Absolute paths are accepted only when they remain inside that approved project directory; symlinks and outside paths are rejected. `referenceAssets` are provider-managed and are not local files. Keep their order stable: changing an asset, modality, or order changes the request and requires a new job directory and paid confirmation.
222
-
223
- Then call `video_render` with that path. Interrupted? Call it again with the same path — it resumes. If an ambiguous submit is reported, do not delete a shot or call render again blindly: run `/video-gen recover <jobId>`, check the provider console, then explicitly `reset` a confirmed-absent task or `adopt` its task id. Revisions? New job directory.
42
+ ## Direct model clips
224
43
 
225
- ## E. Completion
44
+ 1. Complete model preflight and any applicable Seedance asset checks above. Use the active tool schema.
45
+ 2. Fill structured prompt fields: `visuals` describes camera/framing, `action` in-frame movement, `scene` the setting, `effects` time-varying appearance, and `audio` sound/dialogue. `visuals` and `action` are required; without `firstFrame`, `style` and `scene` are also required. The tool assembles the prompt.
46
+ 3. Generate requested/missing source frames through `image_generate`, recording its returned paths. Confirm the exact paid-video scope if not already authorized.
47
+ 4. Call `video_generate` for each missing clip. Resume an interrupted clip with its returned `jobId`; `prompt` is not needed on resume. An ambiguous submit requires checking the provider console and `/video-gen recover <jobId>`: `reset` only a confirmed-absent task or `adopt` its existing task ID. Do not blindly resubmit. Choose the appropriate local assembly path if needed.
48
+ 5. Inspect the returned saved video or available QC evidence and report its path, accepted degradation and any verification limitation.
226
49
 
227
- Before reporting success, verify the requested clip/segment count and order, inspect the final video or available QC evidence, and report the returned absolute path and any accepted degradation. For Timeline, perform the QC-frame and subtitle checks in §A1. A successful tool call alone does not establish visual acceptance; state any verification limitation.
50
+ ## Completion
228
51
 
229
- For films using [film direction](references/film-direction.md), complete its delivery review and revision checks against the actual exported version. Report separately what was checked in stills, in motion and in audio.
52
+ Before reporting success, verify the requested clip/segment count and order, review the actual exported version or available QC evidence, and return the absolute output path plus any editable project and accepted limitations. Complete the selected assembly guide's checks. For creative films, apply film direction's delivery review and revision rules and report separately what was checked in stills, motion and audio. A successful render or recorded QC is evidence, not visual or user acceptance.
@@ -35,40 +35,35 @@
35
35
  ]
36
36
  },
37
37
  {
38
- "id": "single-ai-shot",
39
- "prompt": "Create one five-second AI-generated shot of a paper boat moving through a rainy gutter. No multi-shot film is needed. Explain which Pi video flow and preflight you would use and what confirmation is required, but do not call tools.",
40
- "expected_output": "Use video_capabilities, then one video_generate call after explicit paid confirmation.",
38
+ "id": "paid-clip-approval-response",
39
+ "prompt": "Prepare one five-second paper-boat clip. The capability check has already returned provider/account eval, model eval-video, duration 5 seconds supported, no native audio. I accept silence and want no reference images. I have not approved paid generation. Give your next user-facing reply; do not call tools or create files.",
40
+ "expected_output": "Ask for explicit approval of one five-second eval-video clip on provider/account eval, with no references and silence accepted, before any paid call. Do not claim generation or an output exists.",
41
41
  "expectations": [
42
42
  {
43
- "text": "Chooses the single-shot generation tool",
43
+ "text": "Actually asks the user to approve the exact paid scope, including count, duration, provider/account, model, references and silence; merely describing a future approval step is insufficient.",
44
44
  "includes": [
45
- "video_generate"
46
- ]
47
- },
48
- {
49
- "text": "Runs capability preflight",
50
- "includes": [
51
- "video_capabilities"
52
- ]
53
- },
54
- {
55
- "text": "Requires confirmation before the paid call",
56
- "includes": [
57
- "paid"
45
+ "eval-video",
46
+ "eval"
58
47
  ],
59
48
  "includes_any": [
60
- "confirmation",
49
+ "approve",
61
50
  "confirm",
62
- "go-ahead",
63
51
  "approval"
64
52
  ]
53
+ },
54
+ {
55
+ "text": "Does not claim that a video was submitted, generated or saved.",
56
+ "excludes": [
57
+ "generation completed",
58
+ "video is ready"
59
+ ]
65
60
  }
66
61
  ]
67
62
  },
68
63
  {
69
- "id": "multi-shot-film",
70
- "prompt": "I want a 30-second, three-shot AI-assisted product launch film with a recurring mascot and visual continuity. AI assistance may generate missing mascot stills; model-generated video clips are optional. The product is a task manager; I have supplied actual UI screenshots and brand assets but no measured performance data. You may choose a sensible visual direction and proceed without waiting for a style selection. Explain the product evidence, rhythm and key-frame plan, frame generation, paid confirmation and render stages, including how many times the final render tool is invoked. I also want a music/effects treatment aligned to the reveals. Explain how you would achieve that using the existing Timeline or Remotion path and how you would review the export. Do not call task tools or create files; you may read skill references.",
71
- "expected_output": "Read film-direction.md; ground claims in supplied product material without inventing performance numbers, recommend a direction without a mandatory selection, and provide a structured multi-shot plan covering intent, timing, readable key frames and mascot continuity. Use image_generate only for missing frames and confirm any paid scope. Choose a supported route: one video_compose call for local/Remotion assembly, or one video_render call for a prepared generated-shot batch with assembly. Explain feasible audio timing in Remotion or disclose Timeline limitations; review actual stills, motion and audio with honest verification limits.",
64
+ "id": "continuous-product-film",
65
+ "prompt": "Plan a 30-second, three-part launch film for a task manager. Supplied material: genuine screenshots of its inbox, request composer and completed-result view, plus brand colors; no performance measurements or mascot art. Use a recurring mascot. Choose the visual direction yourself. Keep the request visibly connected as input expands into the workspace and becomes its result. I want music and effects on the reveals, with varied energy rather than three identical beats. Explain the production route and what you will check before delivery. No paid generation is approved. No tools or files except reading skill references.",
66
+ "expected_output": "Read film-direction.md and its motion-authoring reference; ground claims in supplied product material without inventing performance numbers, recommend a direction without a mandatory selection, and provide a structured multi-shot plan covering intent, timing, readable key frames and mascot continuity. Identify persistent objects and before/after states at continuous handoffs. Use image_generate only for missing frames and confirm any paid scope. Choose one video_compose call for local/Remotion assembly or one video_render call for a prepared generated-shot batch with assembly. Share landing times between picture and audio in Remotion, select qcTimesSec around handoffs, and review actual stills, motion and audio with honest verification limits. Timeline does not provide arbitrary timed effects or dynamic ducking. Choose a motion language that explains the actual product operation, describe meaningful contrasts in shot scale, pace, density or music, and plan concrete director review without inventing export observations.",
72
67
  "expectations": [
73
68
  {
74
69
  "text": "Provides a structured multi-shot plan with shot intent, timing and recurring mascot continuity; a shot book, beat map or equivalent scene plan is acceptable without a required artifact name",
@@ -81,7 +76,7 @@
81
76
  ]
82
77
  },
83
78
  {
84
- "text": "Generates frames through image_generate",
79
+ "text": "Uses image_generate for needed mascot/reference frames while reusing suitable supplied screenshots; does not regenerate all supplied visuals by default.",
85
80
  "includes": [
86
81
  "image_generate"
87
82
  ]
@@ -128,6 +123,40 @@
128
123
  "duck"
129
124
  ]
130
125
  },
126
+ {
127
+ "text": "Plans identifiable persistent objects and their before/after states at the continuous handoffs, and uses qcTimesSec to inspect actual export frames around those handoffs without claiming that sampled stills prove motion quality",
128
+ "includes": [
129
+ "qcTimesSec"
130
+ ],
131
+ "includes_any": [
132
+ "object",
133
+ "request",
134
+ "composer",
135
+ "container"
136
+ ]
137
+ },
138
+ {
139
+ "text": "Selects a motion language that fits the actual task-manager operation and supplied evidence; uses decorative motifs only when they help explain the operation, rather than substituting generic moving cards or geometric art for the product",
140
+ "includes_any": [
141
+ "cursor",
142
+ "workflow",
143
+ "demonstration",
144
+ "continuous",
145
+ "operation",
146
+ "interface"
147
+ ]
148
+ },
149
+ {
150
+ "text": "Describes meaningful changes in shot scale, pace, density, camera or music across the film and plans concrete director-review questions; does not invent timestamped defects or claim normal-speed or audio review of a nonexistent export",
151
+ "includes_any": [
152
+ "contrast",
153
+ "rhythm",
154
+ "pace",
155
+ "density",
156
+ "scale",
157
+ "music"
158
+ ]
159
+ },
131
160
  {
132
161
  "text": "Reviews the exported film in stills, at normal speed and in audio, stating unavailable visual or listening checks honestly",
133
162
  "includes_any": [
@@ -142,7 +171,7 @@
142
171
  "id": "single-shot-approval-trace",
143
172
  "mode": "tools",
144
173
  "prompt": "Prepare one five-second AI clip of a paper boat. Check the active capabilities and explain the request. I have not approved any paid generation yet.",
145
- "expected_output": "Read the skill, follow its single-shot workflow, check capabilities, ask for approval, and make no paid call.",
174
+ "expected_output": "Read the skill, check capabilities, and make no generation or composition calls. This trace case checks call ordering and absence of unapproved calls; the paid-clip-approval-response case checks the user-facing approval request.",
146
175
  "expectations": [
147
176
  {
148
177
  "text": "Read the video entry",
@@ -0,0 +1,37 @@
1
+ # Continuous motion film
2
+
3
+ An original 26-second, 1920×1080 Remotion film about pi-video-gen's creation workflow. The same preview object moves from a spatial material collection into a full-frame shot, onto an editing timeline, through separated picture/text/audio planes, into a review view and finally a play mark. This is an authored workflow illustration, not a recording of an editor supplied by the plugin. Geometric footage is rendered by code, with no upstream skill, remote media or paid model call.
4
+
5
+ ## Editing units and timing
6
+
7
+ | Time | Viewer follows | Information | Sound |
8
+ |---|---|---|---|
9
+ | 0–3s | Blue moving preview | An idea becomes a shot | Opening pulse and restrained arpeggio |
10
+ | 3–6.2s | Same preview among collected materials | Materials become a sequence | Gathering accent at 4.2s |
11
+ | 6.2–10.2s | Preview grows to fill the screen | One object carries into the next view | Short anticipation pause, landing at 7.6s |
12
+ | 10.2–14s | Same picture moves onto the timeline | Picture, sound and text share time | Timeline landing at 11s |
13
+ | 14–18s | Picture and its lower planes separate | Different layers share event timing | Layer accent at 14.8s |
14
+ | 18–22s | Picture and its review strip | Hashes, handoff frames and editable source | Review landing at 18.5s |
15
+ | 22–26s | Preview contracts into the play mark | Resolve into the product name | Closing accent at 22.8s and a decaying tail |
16
+
17
+ `timing.mjs` owns camera poses and important landing times. The composition interpolates those poses from the current frame; `prepare-audio.mjs` reads the same events for its original stereo score. The score uses synthesized pads, bass, arpeggios, percussion, transition air and landing accents, with music reduced around accents. There is no speech track or claim of verified word alignment. Timeline and review UI are illustrative; the plugin's actual returned QC report is the delivery evidence.
18
+
19
+ ## Prepare and preview
20
+
21
+ Copy this directory into a trusted project outside the configured video output directory. In the copy run `npm install --package-lock=false`, then `npm run prepare-audio`. This creates `public/score.wav` locally and checks the event order, finite audio samples, peak range and quiet endpoints. The generated score is excluded from Git. No external sound samples are downloaded. Dependencies are pinned; Remotion's own license terms apply.
22
+
23
+ Run `npm run studio` for the editable preview. Dependencies and the installed Chrome/Chromium browser are project preparation; the plugin does not install them during a tool call.
24
+
25
+ ## Render through pi-video-gen
26
+
27
+ Create `<configured-outputDir>/continuous-v3/remotion-input.json`, replacing `projectDir` with the copy's absolute path. Provide `browserExecutable` if the environment requires an explicit installed browser path.
28
+
29
+ ```json
30
+ {
31
+ "projectDir": "/absolute/path/to/copied-continuous-demo",
32
+ "compositionId": "ContinuousDemo",
33
+ "qcTimesSec": [0, 2.5, 3.4, 4.2, 6.2, 6.9, 7.6, 9.5, 10.2, 11, 13.6, 14.2, 14.8, 16, 17.5, 18.5, 19.7, 21.2, 22, 22.8, 24.5]
34
+ }
35
+ ```
36
+
37
+ Call `video_compose` with the spec path or run `/video-gen compose <spec-path>`. Inspect the MP4 and returned QC report/frames; check the joins at 6.2–7.6s, 9.5–11s and 21.2–22.8s at normal speed, and listen to the actual mix. After source or timing changes, render in a new job directory. A successful render or a peak check does not establish aesthetic acceptance.
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "pi-video-gen-continuous-demo",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "prepare-audio": "node prepare-audio.mjs",
7
+ "studio": "remotion studio src/index.tsx"
8
+ },
9
+ "dependencies": {
10
+ "@remotion/bundler": "4.0.527",
11
+ "@remotion/renderer": "4.0.527",
12
+ "react": "19.1.1",
13
+ "react-dom": "19.1.1",
14
+ "remotion": "4.0.527"
15
+ },
16
+ "devDependencies": {
17
+ "@remotion/cli": "4.0.527"
18
+ }
19
+ }
@@ -0,0 +1,66 @@
1
+ import assert from 'node:assert/strict';
2
+ import { mkdirSync, writeFileSync } from 'node:fs';
3
+ import { durationSec, events, poses } from './timing.mjs';
4
+
5
+ assert(poses[0].at === 0 && poses.at(-1).at === durationSec);
6
+ assert(poses.every((p, i) => Object.values(p).every(Number.isFinite) && p.w > 0 && p.h > 0 && (!i || p.at > poses[i - 1].at)));
7
+ assert(Object.values(events).every((t) => t > 0 && t < durationSec));
8
+ const rate = 48000;
9
+ const count = Math.round(rate * durationSec);
10
+ const samples = new Float32Array(count * 2);
11
+ const roots = [73.416, 65.406, 87.307, 98];
12
+ const scale = [0, 7, 12, 16, 19, 12, 7, 16];
13
+ const hits = Object.values(events);
14
+ let seed = 317;
15
+ let peak = 0;
16
+ for (let i = 0; i < count; i++) {
17
+ const t = i / rate;
18
+ const root = roots[Math.min(3, Math.floor(t / 6))];
19
+ const beat = t % 0.6;
20
+ const note = Math.floor(t / 0.3);
21
+ const nt = t % 0.3;
22
+ const f = root * 2 ** (scale[note % scale.length] / 12) * 2;
23
+ seed = (Math.imul(seed, 1664525) + 1013904223) >>> 0;
24
+ const noise = seed / 4294967296 * 2 - 1;
25
+ const fade = Math.min(1, t / 0.35, (durationSec - t) / 1.8);
26
+ const pause = t > 6.9 && t < 7.55 ? 0.15 : 1;
27
+ const duck = hits.reduce((v, hit) => v * (1 - 0.55 * Math.exp(-(((t - hit) / 0.22) ** 2))), 1);
28
+ const bass = Math.sin(2 * Math.PI * root * t) * Math.exp(-beat * 6) * 0.09;
29
+ const pluck = (Math.sin(2 * Math.PI * f * nt) + 0.25 * Math.sin(2 * Math.PI * f * 2.01 * nt)) * Math.exp(-nt * 15) * Math.min(1, nt * 500) * 0.055;
30
+ const pad = (Math.sin(2 * Math.PI * root * 2 * t) + Math.sin(2 * Math.PI * root * 2.5 * t)) * 0.023;
31
+ const kick = Math.sin(2 * Math.PI * (45 * beat - 4 * Math.exp(-beat * 28))) * Math.exp(-beat * 22) * 0.11;
32
+ const hat = noise * Math.exp(-(t % 0.15) * 140) * 0.013;
33
+ let accent = 0;
34
+ for (const at of hits) {
35
+ const d = t - at;
36
+ if (d > -0.4 && d < 0) accent += noise * (1 + d / 0.4) ** 2 * 0.045;
37
+ if (d >= 0 && d < 0.75) {
38
+ accent += Math.sin(2 * Math.PI * (54 * d + 4 * (1 - Math.exp(-d * 15)))) * Math.exp(-d * 10) * 0.18;
39
+ accent += (Math.sin(2 * Math.PI * 880 * d) + 0.28 * Math.sin(2 * Math.PI * 2216 * d)) * Math.exp(-d * 12) * Math.min(1, d * 600) * 0.06;
40
+ }
41
+ }
42
+ const music = ((bass + pluck + pad) * pause * duck + kick * pause + hat * pause) * fade;
43
+ const left = music + accent * fade;
44
+ const right = music + Math.sin(t * 1.9) * pad * 0.3 * fade + accent * fade;
45
+ assert(Number.isFinite(left) && Number.isFinite(right));
46
+ samples[i * 2] = left;
47
+ samples[i * 2 + 1] = right;
48
+ peak = Math.max(peak, Math.abs(left), Math.abs(right));
49
+ }
50
+ assert(peak > 0.05 && peak < 2);
51
+ const gain = 0.65 / peak;
52
+ const wav = Buffer.alloc(44 + count * 4);
53
+ wav.write('RIFF', 0); wav.writeUInt32LE(wav.length - 8, 4); wav.write('WAVEfmt ', 8);
54
+ wav.writeUInt32LE(16, 16); wav.writeUInt16LE(1, 20); wav.writeUInt16LE(2, 22);
55
+ wav.writeUInt32LE(rate, 24); wav.writeUInt32LE(rate * 4, 28);
56
+ wav.writeUInt16LE(4, 32); wav.writeUInt16LE(16, 34);
57
+ wav.write('data', 36); wav.writeUInt32LE(count * 4, 40);
58
+ for (let i = 0; i < samples.length; i++) {
59
+ const value = Math.round(samples[i] * gain * 32767);
60
+ assert(Math.abs(value) <= 32767);
61
+ wav.writeInt16LE(value, 44 + i * 2);
62
+ }
63
+ assert(Math.abs(samples[0]) < 1e-6 && Math.abs(samples.at(-1)) < 0.001);
64
+ mkdirSync(new URL('./public/', import.meta.url), { recursive: true });
65
+ writeFileSync(new URL('./public/score.wav', import.meta.url), wav);
66
+ console.error(`[continuous-demo] Created ${durationSec}s original stereo score; peak target -3.7 dBFS.`);