videowright 0.1.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 +91 -0
- package/dist/cli/argv.d.ts +28 -0
- package/dist/cli/argv.d.ts.map +1 -0
- package/dist/cli/argv.js +115 -0
- package/dist/cli/argv.js.map +1 -0
- package/dist/cli/bin.d.ts +7 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +10 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/dev.d.ts +19 -0
- package/dist/cli/dev.d.ts.map +1 -0
- package/dist/cli/dev.js +104 -0
- package/dist/cli/dev.js.map +1 -0
- package/dist/cli/discover.d.ts +29 -0
- package/dist/cli/discover.d.ts.map +1 -0
- package/dist/cli/discover.js +104 -0
- package/dist/cli/discover.js.map +1 -0
- package/dist/cli/discover_project.d.ts +29 -0
- package/dist/cli/discover_project.d.ts.map +1 -0
- package/dist/cli/discover_project.js +108 -0
- package/dist/cli/discover_project.js.map +1 -0
- package/dist/cli/errors.d.ts +10 -0
- package/dist/cli/errors.d.ts.map +1 -0
- package/dist/cli/errors.js +13 -0
- package/dist/cli/errors.js.map +1 -0
- package/dist/cli/ffmpeg.d.ts +57 -0
- package/dist/cli/ffmpeg.d.ts.map +1 -0
- package/dist/cli/ffmpeg.js +122 -0
- package/dist/cli/ffmpeg.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +152 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/playwright_check.d.ts +44 -0
- package/dist/cli/playwright_check.d.ts.map +1 -0
- package/dist/cli/playwright_check.js +20 -0
- package/dist/cli/playwright_check.js.map +1 -0
- package/dist/cli/prompt.d.ts +13 -0
- package/dist/cli/prompt.d.ts.map +1 -0
- package/dist/cli/prompt.js +47 -0
- package/dist/cli/prompt.js.map +1 -0
- package/dist/cli/render.d.ts +60 -0
- package/dist/cli/render.d.ts.map +1 -0
- package/dist/cli/render.js +471 -0
- package/dist/cli/render.js.map +1 -0
- package/dist/cli/script_cmd.d.ts +26 -0
- package/dist/cli/script_cmd.d.ts.map +1 -0
- package/dist/cli/script_cmd.js +88 -0
- package/dist/cli/script_cmd.js.map +1 -0
- package/dist/cli/time_shim.d.ts +44 -0
- package/dist/cli/time_shim.d.ts.map +1 -0
- package/dist/cli/time_shim.js +390 -0
- package/dist/cli/time_shim.js.map +1 -0
- package/dist/cli/ts_loader.d.ts +28 -0
- package/dist/cli/ts_loader.d.ts.map +1 -0
- package/dist/cli/ts_loader.js +95 -0
- package/dist/cli/ts_loader.js.map +1 -0
- package/dist/cli/vite_helpers.d.ts +62 -0
- package/dist/cli/vite_helpers.d.ts.map +1 -0
- package/dist/cli/vite_helpers.js +273 -0
- package/dist/cli/vite_helpers.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/player/hash_router.d.ts +23 -0
- package/dist/player/hash_router.d.ts.map +1 -0
- package/dist/player/hash_router.js +49 -0
- package/dist/player/hash_router.js.map +1 -0
- package/dist/player/hud.d.ts +33 -0
- package/dist/player/hud.d.ts.map +1 -0
- package/dist/player/hud.js +357 -0
- package/dist/player/hud.js.map +1 -0
- package/dist/player/index.d.ts +123 -0
- package/dist/player/index.d.ts.map +1 -0
- package/dist/player/index.js +848 -0
- package/dist/player/index.js.map +1 -0
- package/dist/player/input.d.ts +14 -0
- package/dist/player/input.d.ts.map +1 -0
- package/dist/player/input.js +90 -0
- package/dist/player/input.js.map +1 -0
- package/dist/player/slot.d.ts +22 -0
- package/dist/player/slot.d.ts.map +1 -0
- package/dist/player/slot.js +43 -0
- package/dist/player/slot.js.map +1 -0
- package/dist/player/transitions/cut.d.ts +7 -0
- package/dist/player/transitions/cut.d.ts.map +1 -0
- package/dist/player/transitions/cut.js +9 -0
- package/dist/player/transitions/cut.js.map +1 -0
- package/dist/player/transitions/fade.d.ts +7 -0
- package/dist/player/transitions/fade.d.ts.map +1 -0
- package/dist/player/transitions/fade.js +18 -0
- package/dist/player/transitions/fade.js.map +1 -0
- package/dist/player/transitions/index.d.ts +4 -0
- package/dist/player/transitions/index.d.ts.map +1 -0
- package/dist/player/transitions/index.js +4 -0
- package/dist/player/transitions/index.js.map +1 -0
- package/dist/player/transitions/slide.d.ts +6 -0
- package/dist/player/transitions/slide.d.ts.map +1 -0
- package/dist/player/transitions/slide.js +35 -0
- package/dist/player/transitions/slide.js.map +1 -0
- package/dist/script/index.d.ts +2 -0
- package/dist/script/index.d.ts.map +1 -0
- package/dist/script/index.js +2 -0
- package/dist/script/index.js.map +1 -0
- package/dist/script/script.d.ts +10 -0
- package/dist/script/script.d.ts.map +1 -0
- package/dist/script/script.js +41 -0
- package/dist/script/script.js.map +1 -0
- package/dist/segment/SegmentRunner.d.ts +52 -0
- package/dist/segment/SegmentRunner.d.ts.map +1 -0
- package/dist/segment/SegmentRunner.js +187 -0
- package/dist/segment/SegmentRunner.js.map +1 -0
- package/dist/segment/defineConfig.d.ts +6 -0
- package/dist/segment/defineConfig.d.ts.map +1 -0
- package/dist/segment/defineConfig.js +7 -0
- package/dist/segment/defineConfig.js.map +1 -0
- package/dist/segment/defineSegment.d.ts +7 -0
- package/dist/segment/defineSegment.d.ts.map +1 -0
- package/dist/segment/defineSegment.js +25 -0
- package/dist/segment/defineSegment.js.map +1 -0
- package/dist/segment/index.d.ts +5 -0
- package/dist/segment/index.d.ts.map +1 -0
- package/dist/segment/index.js +4 -0
- package/dist/segment/index.js.map +1 -0
- package/dist/timeline/index.d.ts +73 -0
- package/dist/timeline/index.d.ts.map +1 -0
- package/dist/timeline/index.js +142 -0
- package/dist/timeline/index.js.map +1 -0
- package/dist/timeline/loadAudioTrack.d.ts +18 -0
- package/dist/timeline/loadAudioTrack.d.ts.map +1 -0
- package/dist/timeline/loadAudioTrack.js +44 -0
- package/dist/timeline/loadAudioTrack.js.map +1 -0
- package/dist/timeline/loadVoiceover.d.ts +18 -0
- package/dist/timeline/loadVoiceover.d.ts.map +1 -0
- package/dist/timeline/loadVoiceover.js +38 -0
- package/dist/timeline/loadVoiceover.js.map +1 -0
- package/dist/timeline/resolveTiming.d.ts +28 -0
- package/dist/timeline/resolveTiming.d.ts.map +1 -0
- package/dist/timeline/resolveTiming.js +63 -0
- package/dist/timeline/resolveTiming.js.map +1 -0
- package/dist/timeline/validateTiming.d.ts +29 -0
- package/dist/timeline/validateTiming.d.ts.map +1 -0
- package/dist/timeline/validateTiming.js +62 -0
- package/dist/timeline/validateTiming.js.map +1 -0
- package/dist/types.d.ts +216 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +47 -0
- package/skill/SKILL.md +64 -0
- package/skill/assets/hello_world/PLAN.md +31 -0
- package/skill/assets/hello_world/README.md +27 -0
- package/skill/assets/hello_world/audio/audio_plan.md +14 -0
- package/skill/assets/hello_world/segments/hello_intro.ts +69 -0
- package/skill/assets/hello_world/segments/hello_outro.ts +71 -0
- package/skill/assets/hello_world/timeline.ts +15 -0
- package/skill/assets/hello_world/voiceover_script/script.md +10 -0
- package/skill/assets/install/package.json +10 -0
- package/skill/assets/install/tsconfig.json +23 -0
- package/skill/assets/styles/editorial-mono/STYLE.md +124 -0
- package/skill/assets/styles/editorial-mono/brand.md +85 -0
- package/skill/assets/styles/editorial-mono/reference/animations.jsx +752 -0
- package/skill/assets/styles/editorial-mono/reference/scenes.html +563 -0
- package/skill/assets/styles/editorial-mono/sample/bullet.ts +101 -0
- package/skill/assets/styles/editorial-mono/sample/content.ts +104 -0
- package/skill/assets/styles/editorial-mono/sample/cta.ts +113 -0
- package/skill/assets/styles/editorial-mono/sample/feature.ts +111 -0
- package/skill/assets/styles/editorial-mono/sample/grid.ts +97 -0
- package/skill/assets/styles/editorial-mono/sample/kinetic.ts +96 -0
- package/skill/assets/styles/editorial-mono/sample/section.ts +101 -0
- package/skill/assets/styles/editorial-mono/sample/stat.ts +128 -0
- package/skill/assets/styles/editorial-mono/sample/title.ts +97 -0
- package/skill/assets/styles/editorial-mono/sample/ui-showcase.ts +159 -0
- package/skill/assets/styles/editorial-mono/tokens.css +44 -0
- package/skill/assets/styles/iso-diagram/STYLE.md +109 -0
- package/skill/assets/styles/iso-diagram/brand.md +32 -0
- package/skill/assets/styles/iso-diagram/reference/animations.jsx +673 -0
- package/skill/assets/styles/iso-diagram/reference/scenes.html +427 -0
- package/skill/assets/styles/iso-diagram/sample/bullet.ts +144 -0
- package/skill/assets/styles/iso-diagram/sample/content.ts +192 -0
- package/skill/assets/styles/iso-diagram/sample/cta.ts +162 -0
- package/skill/assets/styles/iso-diagram/sample/feature.ts +205 -0
- package/skill/assets/styles/iso-diagram/sample/grid.ts +181 -0
- package/skill/assets/styles/iso-diagram/sample/kinetic.ts +102 -0
- package/skill/assets/styles/iso-diagram/sample/section.ts +149 -0
- package/skill/assets/styles/iso-diagram/sample/stat.ts +164 -0
- package/skill/assets/styles/iso-diagram/sample/title.ts +173 -0
- package/skill/assets/styles/iso-diagram/sample/ui-showcase.ts +162 -0
- package/skill/assets/styles/iso-diagram/tokens.css +40 -0
- package/skill/assets/styles/motion-engineering/STYLE.md +106 -0
- package/skill/assets/styles/motion-engineering/brand.md +29 -0
- package/skill/assets/styles/motion-engineering/reference/animations.jsx +673 -0
- package/skill/assets/styles/motion-engineering/reference/scenes.html +513 -0
- package/skill/assets/styles/motion-engineering/sample/bullet.ts +176 -0
- package/skill/assets/styles/motion-engineering/sample/content.ts +228 -0
- package/skill/assets/styles/motion-engineering/sample/cta.ts +209 -0
- package/skill/assets/styles/motion-engineering/sample/feature.ts +299 -0
- package/skill/assets/styles/motion-engineering/sample/grid.ts +190 -0
- package/skill/assets/styles/motion-engineering/sample/kinetic.ts +159 -0
- package/skill/assets/styles/motion-engineering/sample/section.ts +196 -0
- package/skill/assets/styles/motion-engineering/sample/stat.ts +230 -0
- package/skill/assets/styles/motion-engineering/sample/title.ts +219 -0
- package/skill/assets/styles/motion-engineering/sample/ui-showcase.ts +267 -0
- package/skill/assets/styles/motion-engineering/tokens.css +40 -0
- package/skill/assets/styles/neon-terminal/STYLE.md +105 -0
- package/skill/assets/styles/neon-terminal/brand.md +27 -0
- package/skill/assets/styles/neon-terminal/reference/animations.jsx +673 -0
- package/skill/assets/styles/neon-terminal/reference/scenes.html +387 -0
- package/skill/assets/styles/neon-terminal/sample/bullet.ts +113 -0
- package/skill/assets/styles/neon-terminal/sample/content.ts +117 -0
- package/skill/assets/styles/neon-terminal/sample/cta.ts +131 -0
- package/skill/assets/styles/neon-terminal/sample/feature.ts +112 -0
- package/skill/assets/styles/neon-terminal/sample/grid.ts +128 -0
- package/skill/assets/styles/neon-terminal/sample/kinetic.ts +105 -0
- package/skill/assets/styles/neon-terminal/sample/section.ts +96 -0
- package/skill/assets/styles/neon-terminal/sample/stat.ts +123 -0
- package/skill/assets/styles/neon-terminal/sample/title.ts +122 -0
- package/skill/assets/styles/neon-terminal/sample/ui-showcase.ts +127 -0
- package/skill/assets/styles/neon-terminal/tokens.css +39 -0
- package/skill/assets/styles/risograph/STYLE.md +110 -0
- package/skill/assets/styles/risograph/brand.md +26 -0
- package/skill/assets/styles/risograph/reference/animations.jsx +673 -0
- package/skill/assets/styles/risograph/reference/scenes.html +403 -0
- package/skill/assets/styles/risograph/sample/bullet.ts +124 -0
- package/skill/assets/styles/risograph/sample/content.ts +135 -0
- package/skill/assets/styles/risograph/sample/cta.ts +149 -0
- package/skill/assets/styles/risograph/sample/feature.ts +152 -0
- package/skill/assets/styles/risograph/sample/grid.ts +123 -0
- package/skill/assets/styles/risograph/sample/kinetic.ts +125 -0
- package/skill/assets/styles/risograph/sample/section.ts +130 -0
- package/skill/assets/styles/risograph/sample/stat.ts +145 -0
- package/skill/assets/styles/risograph/sample/title.ts +132 -0
- package/skill/assets/styles/risograph/sample/ui-showcase.ts +147 -0
- package/skill/assets/styles/risograph/tokens.css +39 -0
- package/skill/assets/styles/swiss-console/STYLE.md +107 -0
- package/skill/assets/styles/swiss-console/brand.md +37 -0
- package/skill/assets/styles/swiss-console/reference/animations.jsx +673 -0
- package/skill/assets/styles/swiss-console/reference/scenes.html +420 -0
- package/skill/assets/styles/swiss-console/sample/bullet.ts +122 -0
- package/skill/assets/styles/swiss-console/sample/content.ts +137 -0
- package/skill/assets/styles/swiss-console/sample/cta.ts +109 -0
- package/skill/assets/styles/swiss-console/sample/feature.ts +163 -0
- package/skill/assets/styles/swiss-console/sample/grid.ts +145 -0
- package/skill/assets/styles/swiss-console/sample/kinetic.ts +117 -0
- package/skill/assets/styles/swiss-console/sample/section.ts +127 -0
- package/skill/assets/styles/swiss-console/sample/stat.ts +148 -0
- package/skill/assets/styles/swiss-console/sample/title.ts +148 -0
- package/skill/assets/styles/swiss-console/sample/ui-showcase.ts +198 -0
- package/skill/assets/styles/swiss-console/tokens.css +39 -0
- package/skill/install/INSTALL.md +400 -0
- package/skill/references/audio/audio_plan.md +199 -0
- package/skill/references/audio/build.md +208 -0
- package/skill/references/audio/cue_template.md +219 -0
- package/skill/references/audio/ffmpeg_cookbook.md +267 -0
- package/skill/references/audio/music/music.md +171 -0
- package/skill/references/audio/music/providers/elevenlabs.md +170 -0
- package/skill/references/audio/music/providers/manual.md +140 -0
- package/skill/references/audio/music/providers/openverse.md +265 -0
- package/skill/references/audio/sfx/providers/elevenlabs.md +152 -0
- package/skill/references/audio/sfx/providers/manual.md +117 -0
- package/skill/references/audio/sfx/providers/openverse.md +243 -0
- package/skill/references/audio/sfx/sfx.md +149 -0
- package/skill/references/audio/styles.md +102 -0
- package/skill/references/audio/sync.md +237 -0
- package/skill/references/audio/voiceover/animation_sync.md +142 -0
- package/skill/references/audio/voiceover/provider_script.md +153 -0
- package/skill/references/audio/voiceover/providers/elevenlabs.md +288 -0
- package/skill/references/audio/voiceover/providers/manual.md +100 -0
- package/skill/references/audio/voiceover/script_writing.md +100 -0
- package/skill/references/audio/voiceover/style_intake.md +56 -0
- package/skill/references/audio/voiceover/sync_algorithm.md +167 -0
- package/skill/references/audio/voiceover.md +296 -0
- package/skill/references/audio.md +135 -0
- package/skill/references/authoring_segment.md +446 -0
- package/skill/references/create_or_edit_video.md +232 -0
- package/skill/references/dev_server.md +157 -0
- package/skill/references/export.md +145 -0
- package/skill/references/new_video.md +117 -0
- package/skill/references/project_structure.md +144 -0
- package/skill/references/setup.md +109 -0
- package/skill/references/setup_new_style.md +158 -0
- package/skill/references/styles.md +154 -0
- package/skill/references/testing.md +115 -0
- package/skill/references/types.md +240 -0
- package/src/cli/entry/components/copy_button.ts +42 -0
- package/src/cli/entry/components/download_modal.ts +204 -0
- package/src/cli/entry/components/empty_state.ts +55 -0
- package/src/cli/entry/components/hide_hud_tab.ts +37 -0
- package/src/cli/entry/components/icons.ts +31 -0
- package/src/cli/entry/components/top_bar.ts +69 -0
- package/src/cli/entry/components/video_card.ts +57 -0
- package/src/cli/entry/dev_frame.ts +189 -0
- package/src/cli/entry/entry_index.ts +16 -0
- package/src/cli/entry/entry_video.ts +24 -0
- package/src/cli/entry/index.html +12 -0
- package/src/cli/entry/parse_slug.ts +14 -0
- package/src/cli/entry/render.html +17 -0
- package/src/cli/entry/render_entry.ts +121 -0
- package/src/cli/entry/styles/base.css +45 -0
- package/src/cli/entry/styles/components.css +605 -0
- package/src/cli/entry/styles/tokens.css +44 -0
- package/src/cli/entry/video.html +22 -0
- package/src/cli/entry/views/homepage.ts +66 -0
- package/src/cli/entry/views/video_view.ts +286 -0
- package/src/cli/entry/virtual.d.ts +8 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# Install Videowright
|
|
2
|
+
|
|
3
|
+
*This file is an install script for coding agents (Claude Code, Codex, opencode). Read it top-to-bottom and execute each step.*
|
|
4
|
+
|
|
5
|
+
You are installing Videowright -- a library for composing animated explainer videos in HTML/CSS/JS. Follow these steps in order. Do not skip steps. Do not reorder.
|
|
6
|
+
|
|
7
|
+
Each step includes exact prompts to show the user. Use them verbatim -- do not rephrase.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Step 1: Folder check
|
|
12
|
+
|
|
13
|
+
Videowright expects to own its folder. It can live in a sub-folder of a larger repo, but it should not share a folder with another project.
|
|
14
|
+
|
|
15
|
+
Inspect the current working directory. Apply these rules in order:
|
|
16
|
+
|
|
17
|
+
1. **Empty folder, or only innocent files** (`README.md`, `LICENSE`, `.gitignore`, `.git/`, an empty or near-empty `package.json` with no meaningful dependencies): proceed without asking. This is the happy path.
|
|
18
|
+
|
|
19
|
+
2. **Already a Videowright project** (`videowright.config.ts` exists, or `package.json` has `videowright` in `dependencies` or `devDependencies`): proceed without asking. This is a re-install or repair.
|
|
20
|
+
|
|
21
|
+
3. **Has other project content** (source code, populated `package.json` with unrelated dependencies, framework config files, etc.): stop and ask the user exactly:
|
|
22
|
+
|
|
23
|
+
> This folder already contains another project. Videowright should own its own folder. Options:
|
|
24
|
+
> 1. Cancel and `cd` into a clean folder.
|
|
25
|
+
> 2. Install into a sub-folder of this project (recommended sub-folder name: `videos/`).
|
|
26
|
+
>
|
|
27
|
+
> Which would you like?
|
|
28
|
+
|
|
29
|
+
- If they pick **1**: stop the install. Tell the user to `cd` into a clean folder and re-run.
|
|
30
|
+
- If they pick **2**: confirm or adjust the sub-folder name (default `videos/`). Create the directory if it does not exist. `cd` into it for the remainder of the install. Remember: the instruction file (Step 6) is written to the **root** of the larger project, not the sub-folder.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Step 2: Agent detection
|
|
35
|
+
|
|
36
|
+
Detect which supported coding agents are installed. Run these commands separately (since `&&` short-circuits on failure). On macOS/Linux use `which`; on Windows use `where`:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# macOS / Linux
|
|
40
|
+
which claude
|
|
41
|
+
which codex
|
|
42
|
+
which opencode
|
|
43
|
+
|
|
44
|
+
# Windows (if not using WSL)
|
|
45
|
+
where claude
|
|
46
|
+
where codex
|
|
47
|
+
where opencode
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The agent you are running in is implicitly installed -- include it in the detected set even if `which` fails (e.g., it may not be on `PATH` inside the sandbox).
|
|
51
|
+
|
|
52
|
+
**Decision:**
|
|
53
|
+
|
|
54
|
+
- **Only one supported agent installed** (the current one): proceed without asking. You will install the skill and instruction file for this agent only.
|
|
55
|
+
|
|
56
|
+
- **Multiple supported agents installed**: ask the user exactly:
|
|
57
|
+
|
|
58
|
+
> I see you have [list of detected agents] installed. Should I set up Videowright for all of them, or just [current agent]?
|
|
59
|
+
> 1. Just [current agent].
|
|
60
|
+
> 2. All installed agents.
|
|
61
|
+
>
|
|
62
|
+
> Which?
|
|
63
|
+
|
|
64
|
+
Default suggestion is **1** (just the current agent). The user can re-run install in another agent later.
|
|
65
|
+
|
|
66
|
+
Record the chosen set of agents for Step 6.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Step 3: Package manager detection
|
|
71
|
+
|
|
72
|
+
Detect the package manager. Apply these rules in order:
|
|
73
|
+
|
|
74
|
+
1. **Lockfile exists**: `package-lock.json` -> use `npm`. `pnpm-lock.yaml` -> use `pnpm`. If `yarn.lock` or `bun.lockb` exists (but no npm/pnpm lockfile), warn the user:
|
|
75
|
+
> This project uses yarn/bun, which Videowright does not support. Would you like to proceed with npm or pnpm instead?
|
|
76
|
+
If they agree, continue to step 2 to pick npm or pnpm. If not, stop.
|
|
77
|
+
|
|
78
|
+
2. **No lockfile -- check availability** (use `which` on macOS/Linux, `where` on Windows):
|
|
79
|
+
```bash
|
|
80
|
+
# macOS / Linux
|
|
81
|
+
which npm
|
|
82
|
+
which pnpm
|
|
83
|
+
|
|
84
|
+
# Windows (if not using WSL)
|
|
85
|
+
where npm
|
|
86
|
+
where pnpm
|
|
87
|
+
```
|
|
88
|
+
- Only one installed: use it without asking.
|
|
89
|
+
- Both installed: ask the user exactly:
|
|
90
|
+
> Which package manager do you want to use? [npm] or [pnpm]?
|
|
91
|
+
>
|
|
92
|
+
> Default: npm.
|
|
93
|
+
- Neither installed: stop with this exact message:
|
|
94
|
+
> Videowright requires npm or pnpm. Install one and try again.
|
|
95
|
+
|
|
96
|
+
Record the chosen package manager as `<pm>` for the remaining steps.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Step 4: Package install
|
|
101
|
+
|
|
102
|
+
### 4a: Ensure package.json exists
|
|
103
|
+
|
|
104
|
+
If `package.json` does **not** exist in the current directory, write one with these fields:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"name": "my-videowright-project",
|
|
109
|
+
"version": "0.1.0",
|
|
110
|
+
"private": true,
|
|
111
|
+
"type": "module",
|
|
112
|
+
"scripts": {
|
|
113
|
+
"dev": "npx videowright dev",
|
|
114
|
+
"render": "npx videowright render"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Optionally rename the `"name"` field to match the current directory name (kebab-case).
|
|
120
|
+
|
|
121
|
+
The canonical source for this shape is `node_modules/videowright/skill/assets/install/package.json` (available after step 4b).
|
|
122
|
+
|
|
123
|
+
If `package.json` **does** exist:
|
|
124
|
+
|
|
125
|
+
1. Read the file and check for the `"type"` field.
|
|
126
|
+
2. If `"type"` is missing: add `"type": "module"` to the existing package.json. Do not overwrite other fields.
|
|
127
|
+
3. If `"type"` exists and equals `"module"`: no action needed.
|
|
128
|
+
4. If `"type"` exists with a value other than `"module"`: stop and tell the user exactly:
|
|
129
|
+
> Your package.json has `"type": "<current-value>"`. Videowright requires `"type": "module"` for ESM imports. Should I change it?
|
|
130
|
+
If the user agrees, update the field. If not, stop the install -- Videowright will not work without ESM.
|
|
131
|
+
5. Check for `"scripts"` and add `"dev"` and `"render"` entries if they do not already exist. Do not overwrite existing script entries.
|
|
132
|
+
|
|
133
|
+
### 4b: Install Videowright
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
<pm> install videowright
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 4c: Install dev toolchain
|
|
140
|
+
|
|
141
|
+
Install the dev tools that Videowright projects use. These mirror the core Videowright repo's own toolchain.
|
|
142
|
+
|
|
143
|
+
**Pin versions from the core package:** after step 4b, read `node_modules/videowright/package.json` and note the version ranges in its `devDependencies` for `vitest` and `@playwright/test`. Use those same version ranges when installing:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
<pm> install --save-dev vitest@<version-from-core> @playwright/test@<version-from-core>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Install latest for tools not in core:** `typescript` and `@biomejs/biome` are not listed in the core `videowright` package's `package.json`. Install the latest version of each:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
<pm> install --save-dev typescript @biomejs/biome
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
| Tool | Version source | Purpose |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `vitest` | Pin from core package.json | Unit tests for segment helpers |
|
|
158
|
+
| `@playwright/test` | Pin from core package.json | E2e/browser tests for video output |
|
|
159
|
+
| `typescript` | Latest | Type-checking for segments and config |
|
|
160
|
+
| `@biomejs/biome` | Latest | Lint + format (single tool) |
|
|
161
|
+
|
|
162
|
+
If a dev dependency is already present at a compatible version, skip it. If present at an incompatible version, warn the user and let them decide whether to upgrade.
|
|
163
|
+
|
|
164
|
+
### 4d: Ensure tsconfig.json exists
|
|
165
|
+
|
|
166
|
+
If `tsconfig.json` does **not** exist in the current directory, copy the template:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
cp node_modules/videowright/skill/assets/install/tsconfig.json tsconfig.json
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
If `tsconfig.json` **does** exist, leave it alone. Do not attempt to merge tsconfig files — the user's existing configuration takes precedence.
|
|
173
|
+
|
|
174
|
+
### 4e: Install Playwright browsers
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npx playwright install
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
This downloads the browser binaries Playwright needs for e2e testing and video export.
|
|
181
|
+
|
|
182
|
+
### 4f: Check and install ffmpeg
|
|
183
|
+
|
|
184
|
+
ffmpeg is required for video rendering (combining frames into the final video file). Check whether it is available on PATH:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# macOS / Linux
|
|
188
|
+
which ffmpeg
|
|
189
|
+
|
|
190
|
+
# Windows (if not using WSL)
|
|
191
|
+
where ffmpeg
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**If ffmpeg is found:** proceed to the next step without prompting.
|
|
195
|
+
|
|
196
|
+
**If ffmpeg is not found:** detect the platform, then check for a supported package manager to attempt auto-install.
|
|
197
|
+
|
|
198
|
+
**Platform detection:** on macOS/Linux, run `uname -s` — a result of `Darwin` means macOS, `Linux` means Linux. On Windows, skip this step (you already know). Then check for a package manager from the matching platform row(s) in the table below (first match wins):
|
|
199
|
+
|
|
200
|
+
| Platform | Package manager detection | Install command |
|
|
201
|
+
|---|---|---|
|
|
202
|
+
| macOS | `which brew` | `brew install ffmpeg` |
|
|
203
|
+
| Linux (Debian/Ubuntu) | `which apt` | `sudo apt update && sudo apt install -y ffmpeg` |
|
|
204
|
+
| Linux (Fedora/RHEL) | `which dnf` | `sudo dnf install -y ffmpeg-free` |
|
|
205
|
+
| Linux (Arch) | `which pacman` | `sudo pacman -S --noconfirm ffmpeg` |
|
|
206
|
+
| Windows | `where choco` | `choco install ffmpeg -y` |
|
|
207
|
+
| Windows | `where scoop` | `scoop install ffmpeg` |
|
|
208
|
+
| Windows | `where winget` | `winget install --id Gyan.FFmpeg -e --accept-source-agreements` |
|
|
209
|
+
|
|
210
|
+
Apply these rules in order:
|
|
211
|
+
|
|
212
|
+
1. **Recognized package manager found:** ask the user exactly:
|
|
213
|
+
|
|
214
|
+
> ffmpeg is required for video rendering but was not found on your PATH. I can install it for you using `<install-command>`. Proceed?
|
|
215
|
+
> 1. Yes, install ffmpeg.
|
|
216
|
+
> 2. No, I'll install it manually.
|
|
217
|
+
|
|
218
|
+
- If **yes**: run the install command. Then re-verify that `ffmpeg` is on PATH (re-run `which`/`where`). If it still cannot be found, tell the user the install may have failed and show the same manual install message as the "no" case below.
|
|
219
|
+
- If **no**: tell the user exactly:
|
|
220
|
+
|
|
221
|
+
> OK — please install ffmpeg manually and make sure it is on your PATH, then say "done" to continue.
|
|
222
|
+
>
|
|
223
|
+
> - macOS: `brew install ffmpeg` (install Homebrew from https://brew.sh if needed)
|
|
224
|
+
> - Linux: use your distribution's package manager (e.g., `sudo apt install ffmpeg`)
|
|
225
|
+
> - Windows: download from https://ffmpeg.org/download.html, or use `choco install ffmpeg` / `winget install ffmpeg`
|
|
226
|
+
|
|
227
|
+
Wait for the user to confirm, then re-verify that `ffmpeg` is on PATH. If still not found, repeat the message. Do not proceed until ffmpeg is confirmed available.
|
|
228
|
+
|
|
229
|
+
2. **No recognized package manager found:** tell the user exactly:
|
|
230
|
+
|
|
231
|
+
> ffmpeg is required for video rendering but was not found on your PATH, and I could not detect a supported package manager to install it automatically.
|
|
232
|
+
>
|
|
233
|
+
> Please install ffmpeg manually:
|
|
234
|
+
> - macOS: `brew install ffmpeg` (install Homebrew from https://brew.sh if needed)
|
|
235
|
+
> - Linux: use your distribution's package manager (e.g., `sudo apt install ffmpeg`)
|
|
236
|
+
> - Windows: download from https://ffmpeg.org/download.html, or use `choco install ffmpeg` / `winget install ffmpeg`
|
|
237
|
+
>
|
|
238
|
+
> After installing, make sure `ffmpeg` is on your PATH, then say "done" to continue.
|
|
239
|
+
|
|
240
|
+
Wait for the user to confirm, then re-verify that `ffmpeg` is on PATH. If still not found, repeat the message. Do not proceed until ffmpeg is confirmed available.
|
|
241
|
+
|
|
242
|
+
### 4g: Verify install
|
|
243
|
+
|
|
244
|
+
1. Confirm that `node_modules/videowright/` exists after installation. If it does not, surface the error to the user and stop.
|
|
245
|
+
2. Read `package.json` and verify that `"type"` is set to `"module"`. If it is not, the dev server will fail with `Cannot use import statement outside a module`. Fix it before proceeding.
|
|
246
|
+
3. Confirm that `tsconfig.json` exists.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Step 5: Skill installation (symlinks)
|
|
251
|
+
|
|
252
|
+
Create **both** of these symlinks at the install root (the Videowright project folder), regardless of which agent(s) the user chose in Step 2. This keeps the install idempotent and future-proof.
|
|
253
|
+
|
|
254
|
+
**Symlinks to create:**
|
|
255
|
+
|
|
256
|
+
| Symlink path | Target |
|
|
257
|
+
|---|---|
|
|
258
|
+
| `.claude/skills/videowright` | `node_modules/videowright/skill/` |
|
|
259
|
+
| `.agents/skills/videowright` | `node_modules/videowright/skill/` |
|
|
260
|
+
|
|
261
|
+
**Coverage:**
|
|
262
|
+
|
|
263
|
+
| Agent | Reads from |
|
|
264
|
+
|---|---|
|
|
265
|
+
| Claude Code | `.claude/skills/` |
|
|
266
|
+
| Codex | `.agents/skills/` |
|
|
267
|
+
| opencode | both `.claude/skills/` and `.agents/skills/` |
|
|
268
|
+
|
|
269
|
+
**How to create each symlink:**
|
|
270
|
+
|
|
271
|
+
Follow the symlink creation algorithm in Appendix B. In summary:
|
|
272
|
+
|
|
273
|
+
1. Create intermediate directories if they do not exist (e.g., `.claude/skills/`).
|
|
274
|
+
2. Compute the target as a **relative path** from the symlink's parent directory to `node_modules/videowright/skill/`. See Appendix B for examples.
|
|
275
|
+
3. If the symlink already exists and points to the correct target: leave it alone.
|
|
276
|
+
4. If the symlink exists but points elsewhere: ask the user before replacing.
|
|
277
|
+
5. If a real file or directory exists at the symlink path: ask the user before replacing.
|
|
278
|
+
6. Create the symlink:
|
|
279
|
+
- macOS/Linux: `ln -s <relative-target> <symlink-path>`
|
|
280
|
+
- Windows: `mklink /D <symlink-path> <relative-target>`
|
|
281
|
+
|
|
282
|
+
**Windows note:** If symlink creation fails on Windows, tell the user exactly:
|
|
283
|
+
|
|
284
|
+
> Symlink creation failed. On Windows, this usually means Developer Mode is off. Either enable Developer Mode (Settings > Privacy & security > For developers > Developer Mode) and re-run, or create the link manually with `mklink /D .claude\skills\videowright node_modules\videowright\skill` (run from an admin terminal). Then verify by running setup again.
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Step 6: Instruction file
|
|
289
|
+
|
|
290
|
+
Write or update the instruction file for each agent the user opted to install for in Step 2.
|
|
291
|
+
|
|
292
|
+
**File mapping:**
|
|
293
|
+
|
|
294
|
+
| Agent | Instruction file |
|
|
295
|
+
|---|---|
|
|
296
|
+
| Claude Code | `CLAUDE.md` |
|
|
297
|
+
| Codex | `AGENTS.md` |
|
|
298
|
+
| opencode | `AGENTS.md` |
|
|
299
|
+
|
|
300
|
+
If installing for multiple agents that need different files (e.g., Claude Code + Codex), write the **same content** into each file. Do not symlink between them.
|
|
301
|
+
|
|
302
|
+
**File location:** the instruction file is written at the **root** of the project. If Step 1 chose sub-folder mode, the instruction file goes in the parent (the larger repo's root), not in the sub-folder.
|
|
303
|
+
|
|
304
|
+
**Content:** use a marked region so re-installs are idempotent. Follow the marked-region writer algorithm in Appendix A.
|
|
305
|
+
|
|
306
|
+
The content to place inside the marked region depends on whether this is a root install or sub-folder install:
|
|
307
|
+
|
|
308
|
+
### Root install content:
|
|
309
|
+
|
|
310
|
+
```
|
|
311
|
+
<!-- videowright:start -->
|
|
312
|
+
*Auto-managed by Videowright installer. Edits inside this block will be overwritten on re-install. Add your own context outside the markers.*
|
|
313
|
+
|
|
314
|
+
This project is a [Videowright](https://github.com/scosman/videowright) project -- a library for composing animated explainer videos in HTML/CSS/JS.
|
|
315
|
+
|
|
316
|
+
For any video-related work, use the `videowright` skill (loaded automatically from `.claude/skills/videowright` or `.agents/skills/videowright`). It has full guidance on segments, voiceovers, styles, and the dev server.
|
|
317
|
+
|
|
318
|
+
Key paths:
|
|
319
|
+
- `videowright.config.ts` -- project config and default style.
|
|
320
|
+
- `videos/` -- one folder per video.
|
|
321
|
+
- `styles/` -- design tokens and shared styling.
|
|
322
|
+
- `segments/`, `components/`, `transitions/` -- shared building blocks.
|
|
323
|
+
<!-- videowright:end -->
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Sub-folder install content:
|
|
327
|
+
|
|
328
|
+
When Step 1 chose sub-folder mode (e.g., sub-folder `videos/`), use this complete block instead:
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
<!-- videowright:start -->
|
|
332
|
+
*Auto-managed by Videowright installer. Edits inside this block will be overwritten on re-install. Add your own context outside the markers.*
|
|
333
|
+
|
|
334
|
+
The folder `<subfolder>/` in this project is a [Videowright](https://github.com/scosman/videowright) project -- a library for composing animated explainer videos in HTML/CSS/JS.
|
|
335
|
+
|
|
336
|
+
For any video-related work, use the `videowright` skill (loaded automatically from `.claude/skills/videowright` or `.agents/skills/videowright`). It has full guidance on segments, voiceovers, styles, and the dev server.
|
|
337
|
+
|
|
338
|
+
Key paths:
|
|
339
|
+
- `<subfolder>/videowright.config.ts` -- project config and default style.
|
|
340
|
+
- `<subfolder>/videos/` -- one folder per video.
|
|
341
|
+
- `<subfolder>/styles/` -- design tokens and shared styling.
|
|
342
|
+
- `<subfolder>/segments/`, `<subfolder>/components/`, `<subfolder>/transitions/` -- shared building blocks.
|
|
343
|
+
<!-- videowright:end -->
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Replace `<subfolder>` with the actual sub-folder name chosen in Step 1.
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Step 7: Continue to setup
|
|
351
|
+
|
|
352
|
+
Tell the user exactly:
|
|
353
|
+
|
|
354
|
+
> Videowright installed. Now configuring the project.
|
|
355
|
+
|
|
356
|
+
Then immediately load [references/setup.md](../references/setup.md) and follow it. Do **not** wait for user input between install and setup — proceed directly.
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Appendix A: Marked-region writer algorithm
|
|
361
|
+
|
|
362
|
+
Given a target file path and the content string to place inside the markers:
|
|
363
|
+
|
|
364
|
+
1. **File does not exist**: create a new file containing exactly the full marked region as shown in Step 6 (including the start/end markers, the auto-managed note, and the content). For example:
|
|
365
|
+
```
|
|
366
|
+
<!-- videowright:start -->
|
|
367
|
+
*Auto-managed by Videowright installer. Edits inside this block will be overwritten on re-install. Add your own context outside the markers.*
|
|
368
|
+
|
|
369
|
+
... rest of content ...
|
|
370
|
+
<!-- videowright:end -->
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
2. **File exists**: read its contents and search for the pattern `<!-- videowright:start -->` ... `<!-- videowright:end -->`:
|
|
374
|
+
- **Match found**: replace everything from `<!-- videowright:start -->` through `<!-- videowright:end -->` (inclusive) with the new marked region. This is an idempotent re-install.
|
|
375
|
+
- **No match**: append the full marked region (start marker, auto-managed note, content, end marker -- exactly as shown in point 1) at the end of the file. If the file does not end with a newline, add two blank lines before the region; otherwise add one blank line.
|
|
376
|
+
|
|
377
|
+
3. **Never modify content outside the markers.**
|
|
378
|
+
|
|
379
|
+
## Appendix B: Symlink creation algorithm
|
|
380
|
+
|
|
381
|
+
Given a symlink path (e.g., `.claude/skills/videowright`) and a target directory (`node_modules/videowright/skill/`):
|
|
382
|
+
|
|
383
|
+
1. **Create intermediate directories**: ensure the parent directory of the symlink exists (e.g., `.claude/skills/`). Create with `mkdir -p` if needed.
|
|
384
|
+
|
|
385
|
+
2. **Compute relative target**: the symlink target must be a relative path from the symlink's parent directory to the target. Compute this dynamically based on the actual directory depth. Examples:
|
|
386
|
+
- **Root install**: symlink at `.claude/skills/videowright`, target at `node_modules/videowright/skill/` -- relative target is `../../node_modules/videowright/skill/`
|
|
387
|
+
- **Sub-folder install** (e.g., project in `videos/`): symlink at `videos/.claude/skills/videowright`, target at `videos/node_modules/videowright/skill/` -- relative target is `../../node_modules/videowright/skill/` (same, because both are relative to the sub-folder root)
|
|
388
|
+
|
|
389
|
+
3. **Check existing state**:
|
|
390
|
+
- If the path is a symlink pointing to the correct relative target: do nothing (idempotent).
|
|
391
|
+
- If the path is a symlink pointing to a different target: ask the user before replacing:
|
|
392
|
+
> `.claude/skills/videowright` currently points to `<old-target>`. Replace it with a link to `node_modules/videowright/skill/`?
|
|
393
|
+
- If the path is a real file or directory (not a symlink): ask the user before replacing.
|
|
394
|
+
- If the path does not exist: proceed to create.
|
|
395
|
+
|
|
396
|
+
4. **Create the symlink**:
|
|
397
|
+
- macOS/Linux: `ln -s <relative-target> <symlink-path>`
|
|
398
|
+
- Windows: `mklink /D <symlink-path> <relative-target>`
|
|
399
|
+
|
|
400
|
+
Apply this algorithm identically for both `.claude/skills/videowright` and `.agents/skills/videowright`.
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Audio Plan Format
|
|
2
|
+
|
|
3
|
+
## When this is loaded
|
|
4
|
+
|
|
5
|
+
You are authoring or editing an `audio_plan.md` file for a video. This reference specifies the format, the two-section structure, and the conventions the build and sync stages depend on.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
Every video with audio gets one `audio_plan.md` at `videos/<video-slug>/audio/audio_plan.md`. It describes the complete audio composition: which source assets are used, how they are sliced and placed in time, their volume curves and fades, and the ffmpeg command that renders the final mix.
|
|
10
|
+
|
|
11
|
+
The file has two sections:
|
|
12
|
+
|
|
13
|
+
1. **Plan** (top) -- the current intended audio composition. Overwritten as the mix evolves.
|
|
14
|
+
2. **Log** (bottom) -- append-only history of edits and renders. Never delete entries.
|
|
15
|
+
|
|
16
|
+
The build stage reads the Plan section to produce a rendered track. The sync stage reads the rendered track's snapshot to compute per-segment timing. The Log section is for human and agent reference only.
|
|
17
|
+
|
|
18
|
+
## Plan section
|
|
19
|
+
|
|
20
|
+
### Structure
|
|
21
|
+
|
|
22
|
+
```markdown
|
|
23
|
+
# Audio Plan
|
|
24
|
+
|
|
25
|
+
## Plan
|
|
26
|
+
|
|
27
|
+
<prose summary>
|
|
28
|
+
|
|
29
|
+
### Cue 1 -- <short name>
|
|
30
|
+
<labeled fields + ffmpeg snippet>
|
|
31
|
+
|
|
32
|
+
### Cue 2 -- <short name>
|
|
33
|
+
<labeled fields + ffmpeg snippet>
|
|
34
|
+
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
### Final mix command
|
|
38
|
+
|
|
39
|
+
<single ffmpeg invocation>
|
|
40
|
+
|
|
41
|
+
## Log
|
|
42
|
+
|
|
43
|
+
<append-only entries>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Prose summary
|
|
47
|
+
|
|
48
|
+
A 1-3 sentence description of the audio composition. It anchors what the mix is trying to achieve and helps when reviewing cue-level detail.
|
|
49
|
+
|
|
50
|
+
Examples:
|
|
51
|
+
|
|
52
|
+
> Music bed throughout. VO carries the demo (4.5-22s). Keyboard SFX over the terminal segment, brief whoosh on transitions.
|
|
53
|
+
|
|
54
|
+
> VO-only track. Single full-file voiceover placed at 0s.
|
|
55
|
+
|
|
56
|
+
### Cues
|
|
57
|
+
|
|
58
|
+
Cues are listed in playback order. Each cue uses the labeled-field template defined in [cue_template.md](cue_template.md). Every cue ends with an ffmpeg snippet that produces a labeled audio stream.
|
|
59
|
+
|
|
60
|
+
Number cues sequentially starting at 1. When cues are added or removed, renumber.
|
|
61
|
+
|
|
62
|
+
### Final mix command
|
|
63
|
+
|
|
64
|
+
After all cues, the plan includes a single complete ffmpeg invocation that:
|
|
65
|
+
|
|
66
|
+
1. Takes every input file referenced by the cues
|
|
67
|
+
2. Applies the per-cue filter fragments
|
|
68
|
+
3. Mixes them with `amix` (or equivalent)
|
|
69
|
+
4. Writes output to `{TRACK_OUT}`
|
|
70
|
+
|
|
71
|
+
The `{TRACK_OUT}` placeholder is replaced at build time with the actual output path (e.g., `audio/tracks/v3/track.mp3`).
|
|
72
|
+
|
|
73
|
+
The final mix command must be a **self-contained, runnable ffmpeg command** -- not a fragment. It should include all inputs, the complete filter graph, and the output path placeholder.
|
|
74
|
+
|
|
75
|
+
Example (VO-only, simplest case):
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
ffmpeg -y \
|
|
79
|
+
-i audio/originals/voiceovers/v1/audio.mp3 \
|
|
80
|
+
-c:a libmp3lame -q:a 2 \
|
|
81
|
+
{TRACK_OUT}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Example (VO + music with ducking):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
ffmpeg -y \
|
|
88
|
+
-i audio/originals/voiceovers/v1/audio.mp3 \
|
|
89
|
+
-i audio/originals/music/uplift_piano/audio.mp3 \
|
|
90
|
+
-filter_complex "
|
|
91
|
+
[0:a] atrim=0:22.5, asetpts=PTS-STARTPTS [vo];
|
|
92
|
+
[1:a] atrim=0:30, asetpts=PTS-STARTPTS,
|
|
93
|
+
volume='if(between(t,4.5,22),0.15,1)':eval=frame,
|
|
94
|
+
afade=t=in:st=0:d=0.5, afade=t=out:st=28:d=2 [music];
|
|
95
|
+
[vo][music] amix=inputs=2:duration=longest:normalize=0 [mix];
|
|
96
|
+
[mix] loudnorm=I=-14:TP=-1:LRA=11 [out]
|
|
97
|
+
" -map "[out]" -c:a libmp3lame -q:a 2 {TRACK_OUT}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Paths in the plan
|
|
101
|
+
|
|
102
|
+
All paths in the plan are **relative to the video folder** (the parent of `audio/`). This matches the working directory when the agent runs ffmpeg from the video folder.
|
|
103
|
+
|
|
104
|
+
Example: `audio/originals/voiceovers/v1/audio.mp3`, not an absolute path.
|
|
105
|
+
|
|
106
|
+
## Log section
|
|
107
|
+
|
|
108
|
+
The Log section is below the Plan section, separated by `## Log`. Entries are newest-first (most recent at the top, matching PLAN.md convention). Each entry records one discrete event.
|
|
109
|
+
|
|
110
|
+
### Render entry
|
|
111
|
+
|
|
112
|
+
```markdown
|
|
113
|
+
## YYYY-MM-DD HH:MM -- <summary of what changed>
|
|
114
|
+
**Change:** <what was modified in the plan>
|
|
115
|
+
**Why:** <user feedback or reason>
|
|
116
|
+
**Render:** ffmpeg ... -> audio/tracks/vN/track.mp3
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Activation entry
|
|
120
|
+
|
|
121
|
+
Written when the user approves a track and it becomes the default:
|
|
122
|
+
|
|
123
|
+
```markdown
|
|
124
|
+
## YYYY-MM-DD HH:MM -- Adopted vN as active track
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Discard entry
|
|
128
|
+
|
|
129
|
+
Written when the user discards a rendered track:
|
|
130
|
+
|
|
131
|
+
```markdown
|
|
132
|
+
## YYYY-MM-DD HH:MM -- Discarded vN
|
|
133
|
+
**Why:** <user feedback>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Edit entry
|
|
137
|
+
|
|
138
|
+
For plan-only changes (no render):
|
|
139
|
+
|
|
140
|
+
```markdown
|
|
141
|
+
## YYYY-MM-DD HH:MM -- <what changed>
|
|
142
|
+
**Change:** <description>
|
|
143
|
+
**Why:** <reason>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Free-text body below the structured fields is welcome for longer notes.
|
|
147
|
+
|
|
148
|
+
## VO-only shortcut
|
|
149
|
+
|
|
150
|
+
For videos with only a voiceover and no SFX or music, the audio plan is minimal:
|
|
151
|
+
|
|
152
|
+
```markdown
|
|
153
|
+
# Audio Plan
|
|
154
|
+
|
|
155
|
+
## Plan
|
|
156
|
+
|
|
157
|
+
VO-only track. Single full-file voiceover placed at 0s.
|
|
158
|
+
|
|
159
|
+
### Cue 1 -- VO (full file)
|
|
160
|
+
Source: audio/originals/voiceovers/v1/
|
|
161
|
+
Slice: full file
|
|
162
|
+
Place at: 0s
|
|
163
|
+
Volume: 100%
|
|
164
|
+
Fades: none
|
|
165
|
+
Notes: Full voiceover, see timing.json for word timings.
|
|
166
|
+
|
|
167
|
+
ffmpeg snippet:
|
|
168
|
+
[0:a] acopy [vo1]
|
|
169
|
+
|
|
170
|
+
### Final mix command
|
|
171
|
+
|
|
172
|
+
ffmpeg -y \
|
|
173
|
+
-i audio/originals/voiceovers/v1/audio.mp3 \
|
|
174
|
+
-c:a libmp3lame -q:a 2 \
|
|
175
|
+
{TRACK_OUT}
|
|
176
|
+
|
|
177
|
+
## Log
|
|
178
|
+
|
|
179
|
+
(No entries yet.)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
For VO-only videos, the plan is auto-emitted by the skill. The user does not need to understand the plan format -- it is created as part of the voiceover flow and consumed transparently by build and sync.
|
|
183
|
+
|
|
184
|
+
## Editing the plan
|
|
185
|
+
|
|
186
|
+
When the user requests changes to the audio mix:
|
|
187
|
+
|
|
188
|
+
1. Update the relevant cues in the Plan section (add, remove, or modify cues).
|
|
189
|
+
2. Update the final mix command to match the new cue set.
|
|
190
|
+
3. Renumber cues if needed.
|
|
191
|
+
4. Do **not** modify the Log section when editing the plan. Log entries are appended only at build time or when significant plan changes are recorded.
|
|
192
|
+
|
|
193
|
+
## Relationship to other files
|
|
194
|
+
|
|
195
|
+
- **`cue_template.md`** -- defines the per-cue field format
|
|
196
|
+
- **`build.md`** -- reads the plan to produce a rendered track
|
|
197
|
+
- **`sync.md`** -- reads the track's plan snapshot to compute timing
|
|
198
|
+
- **`ffmpeg_cookbook.md`** -- recipes for common ffmpeg operations used in cue snippets
|
|
199
|
+
- **`styles.md`** -- guidance on volume levels, ducking, and mix aesthetics
|