@openvidstudio/mcp-server 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.
Files changed (94) hide show
  1. package/dist/beats.d.ts +47 -0
  2. package/dist/beats.js +9 -0
  3. package/dist/capture.d.ts +116 -0
  4. package/dist/capture.js +148 -0
  5. package/dist/config.d.ts +58 -0
  6. package/dist/config.js +130 -0
  7. package/dist/paths.d.ts +20 -0
  8. package/dist/paths.js +57 -0
  9. package/dist/scenes/pngSize.d.ts +11 -0
  10. package/dist/scenes/pngSize.js +75 -0
  11. package/dist/scenes/templates.d.ts +42 -0
  12. package/dist/scenes/templates.js +468 -0
  13. package/dist/server.d.ts +16 -0
  14. package/dist/server.js +37 -0
  15. package/dist/stdio.d.ts +2 -0
  16. package/dist/stdio.js +33 -0
  17. package/dist/tools/captureScreenRecording.d.ts +28 -0
  18. package/dist/tools/captureScreenRecording.js +181 -0
  19. package/dist/tools/captureScreenshot.d.ts +34 -0
  20. package/dist/tools/captureScreenshot.js +148 -0
  21. package/dist/tools/contactSheet.d.ts +36 -0
  22. package/dist/tools/contactSheet.js +116 -0
  23. package/dist/tools/generateNarration.d.ts +54 -0
  24. package/dist/tools/generateNarration.js +185 -0
  25. package/dist/tools/importHiggsfieldClip.d.ts +41 -0
  26. package/dist/tools/importHiggsfieldClip.js +108 -0
  27. package/dist/tools/index.d.ts +13 -0
  28. package/dist/tools/index.js +47 -0
  29. package/dist/tools/initProject.d.ts +37 -0
  30. package/dist/tools/initProject.js +166 -0
  31. package/dist/tools/mcp.d.ts +33 -0
  32. package/dist/tools/mcp.js +36 -0
  33. package/dist/tools/planBeats.d.ts +40 -0
  34. package/dist/tools/planBeats.js +143 -0
  35. package/dist/tools/preflight.d.ts +30 -0
  36. package/dist/tools/preflight.js +170 -0
  37. package/dist/tools/qcExtractFrames.d.ts +25 -0
  38. package/dist/tools/qcExtractFrames.js +129 -0
  39. package/dist/tools/renderVideo.d.ts +43 -0
  40. package/dist/tools/renderVideo.js +120 -0
  41. package/dist/tools/scaffoldScene.d.ts +23 -0
  42. package/dist/tools/scaffoldScene.js +147 -0
  43. package/dist/tools/stitchComposition.d.ts +24 -0
  44. package/dist/tools/stitchComposition.js +230 -0
  45. package/dist/tools/validateBeats.d.ts +14 -0
  46. package/dist/tools/validateBeats.js +164 -0
  47. package/dist/tools/validateScenes.d.ts +31 -0
  48. package/dist/tools/validateScenes.js +191 -0
  49. package/dist/tools/writeBeatsFile.d.ts +20 -0
  50. package/dist/tools/writeBeatsFile.js +81 -0
  51. package/dist/util.d.ts +43 -0
  52. package/dist/util.js +163 -0
  53. package/docs/API.md +344 -0
  54. package/docs/CAPTURE.md +106 -0
  55. package/docs/HIGGSFIELD.md +118 -0
  56. package/docs/NARRATION.md +111 -0
  57. package/docs/OVERVIEW.md +112 -0
  58. package/docs/PIPELINE.md +173 -0
  59. package/docs/PLANNING.md +206 -0
  60. package/docs/SCRIPT.md +50 -0
  61. package/docs/STYLE.md +88 -0
  62. package/package.json +54 -0
  63. package/templates/default/CLAUDE.md +63 -0
  64. package/templates/default/openvidstudio-core/package.json +51 -0
  65. package/templates/default/openvidstudio-core/scripts/gen-sfx.sh +74 -0
  66. package/templates/default/openvidstudio-core/src/ChecklistPanel.tsx +97 -0
  67. package/templates/default/openvidstudio-core/src/CinematicScene.tsx +53 -0
  68. package/templates/default/openvidstudio-core/src/CodePanel.tsx +122 -0
  69. package/templates/default/openvidstudio-core/src/CursorActor.tsx +90 -0
  70. package/templates/default/openvidstudio-core/src/DeviceFrame.tsx +74 -0
  71. package/templates/default/openvidstudio-core/src/KineticText.tsx +142 -0
  72. package/templates/default/openvidstudio-core/src/RepoCta.tsx +128 -0
  73. package/templates/default/openvidstudio-core/src/TerminalReplay.tsx +263 -0
  74. package/templates/default/openvidstudio-core/src/camera.tsx +141 -0
  75. package/templates/default/openvidstudio-core/src/index.ts +60 -0
  76. package/templates/default/openvidstudio-core/src/look.tsx +90 -0
  77. package/templates/default/openvidstudio-core/src/motion.ts +50 -0
  78. package/templates/default/openvidstudio-core/src/sfx.tsx +106 -0
  79. package/templates/default/openvidstudio-core/src/tokens.ts +41 -0
  80. package/templates/default/package.json +31 -0
  81. package/templates/default/public/sfx/bell.wav +0 -0
  82. package/templates/default/public/sfx/blip.wav +0 -0
  83. package/templates/default/public/sfx/click.wav +0 -0
  84. package/templates/default/public/sfx/key_a.wav +0 -0
  85. package/templates/default/public/sfx/key_b.wav +0 -0
  86. package/templates/default/public/sfx/key_c.wav +0 -0
  87. package/templates/default/public/sfx/key_enter.wav +0 -0
  88. package/templates/default/public/sfx/music-bed.mp3 +0 -0
  89. package/templates/default/public/sfx/success.wav +0 -0
  90. package/templates/default/public/sfx/whoosh.wav +0 -0
  91. package/templates/default/remotion.config.ts +13 -0
  92. package/templates/default/src/Root.tsx +9 -0
  93. package/templates/default/src/index.ts +4 -0
  94. package/templates/default/tsconfig.json +16 -0
@@ -0,0 +1,206 @@
1
+ # PLANNING.md: guided intake to beats.json
2
+
3
+ This is step 0 of building any video with openvidstudio. Read this before
4
+ touching `beats.json`. It defines: the intake question set, how to handle
5
+ free-form pasted material instead, the per-feature capture-method decision
6
+ tree, the full `captureMethod` field spec, and the mandatory approval gate
7
+ before anything gets written to disk.
8
+
9
+ ## 1. Fixed intake question set
10
+
11
+ Ask the dev, in order, before drafting anything:
12
+
13
+ 1. **Product name and one-liner.** What is it, in one sentence?
14
+ 2. **3-6 features to demo.** The specific things the video should show,
15
+ not a full feature list; pick the ones that carry the pitch.
16
+ 3. **Target video length.** Total seconds (or a range); this bounds the
17
+ beat arc chosen in `PIPELINE.md` (Simple demo vs. Packed-hook,
18
+ multi-feature).
19
+ 4. **Higgsfield access: yes or no.** Determines whether `higgsfield` is an
20
+ available `captureMethod` for this video at all. If no, every "not
21
+ product UI" beat either gets dropped or reworked as `dom-demo`.
22
+ 5. **Brand info.** Colors, fonts, logo, if the project has its own and
23
+ wants it over openvidstudio's default palette/type (`STYLE.md`).
24
+ 6. **Existing assets to reference.** Screenshots, recordings, a deployed
25
+ URL, a design file; anything that saves a capture step later.
26
+
27
+ ## 2. Free-form pasted material
28
+
29
+ If the dev instead pastes a README, a feature list, a Slack thread, or
30
+ similar material, don't force the fixed question set on top of it. Read
31
+ the paste and extract the same six things from it instead:
32
+
33
+ - Product name/one-liner: usually the README's title plus its first
34
+ paragraph.
35
+ - Feature candidates: bullet lists, headers, or a "Features" section map
36
+ directly to feature candidates; pick 3-6 that carry the pitch, same as
37
+ question 2 above.
38
+ - Target length: often absent from a paste; ask this one directly if it's
39
+ missing, don't guess it.
40
+ - Higgsfield access: always ask directly; a paste never answers this.
41
+ - Brand info: look for a design-tokens file, a Tailwind config, a
42
+ `theme.ts`, or explicit brand colors mentioned in the paste; ask only
43
+ for what's genuinely missing.
44
+ - Existing assets: URLs, screenshot paths, or asset folders mentioned in
45
+ the paste count directly.
46
+
47
+ Only ask the dev to fill in whatever the paste didn't already answer. The
48
+ goal is one pass of the fixed question set's information, not necessarily
49
+ one pass of its literal questions.
50
+
51
+ ## 3. Per-feature capture-method decision tree
52
+
53
+ Run this once per feature/claim the video will make. It's meant to be
54
+ followed mechanically, not judged holistically.
55
+
56
+ 1. Does this claim describe real, working functionality in a running
57
+ instance of the product right now (not "will do," not roadmap, not
58
+ something a real screenshot would contradict)?
59
+ - No: go to step 4 (`dom-demo`).
60
+ - Yes: go to step 2.
61
+ 2. Is the important part of this feature a single held state (one screen,
62
+ one panel, nothing essential changes while the viewer watches), or does
63
+ understanding it require seeing something change over time (typing,
64
+ dragging, a live update, an animation intrinsic to the feature)?
65
+ - Single held state: `captureMethod: "screenshot"`. Capture per
66
+ `CAPTURE.md`.
67
+ - Needs visible change over time: go to step 3.
68
+ 3. Can that change be captured by actually interacting with the real,
69
+ running product on screen, within v1's fixed full-viewport scope (no
70
+ post-hoc DOM-rect cropping of a moving recording, see `PIPELINE.md`)?
71
+ - Yes: `captureMethod: "recording"`. Capture per `CAPTURE.md`'s
72
+ recording section.
73
+ - No, the motion needed isn't something the product's own UI can
74
+ produce at all (an atmosphere shot, a desk/hands shot, an abstract
75
+ visual metaphor with no real UI in it): go to step 4, but check
76
+ Higgsfield access from intake question 4 first. If access is "no,"
77
+ this beat either gets dropped or reworked as a still `dom-demo`
78
+ instead of the motion originally wanted.
79
+ 4. `dom-demo`: build a hand-coded panel using the project's real design
80
+ tokens/copy (question 5's brand info, or `STYLE.md`'s defaults if none
81
+ was given). Reuse real copy, real claim IDs, or real UI conventions
82
+ from an actual screenshot elsewhere in the same video where possible,
83
+ so it reads as a continuation, not an invention. Where a real adjacent
84
+ screenshot genuinely backs part of the claim, use the real capture for
85
+ that part and confine the constructed part to just the aspirational
86
+ connection. Never build a `dom-demo` that contradicts a real,
87
+ capturable page's own on-screen copy: if a real page says the opposite
88
+ of the claim, that's a sign the claim needs rewriting, not a signal to
89
+ avoid screenshotting that page.
90
+ - If step 3 routed here because Higgsfield access is "yes" and the
91
+ beat genuinely isn't product UI (atmosphere/b-roll), use
92
+ `captureMethod: "higgsfield"` instead; see `HIGGSFIELD.md`.
93
+
94
+ ## 4. The captureMethod field spec
95
+
96
+ Every beat's `visual` block carries a `captureMethod` field:
97
+
98
+ ```
99
+ "captureMethod": "screenshot" | "recording" | "dom-demo" | "higgsfield"
100
+ ```
101
+
102
+ Method-specific fields:
103
+
104
+ | Method | Extra fields | Notes |
105
+ |---|---|---|
106
+ | `screenshot` | `url`, `interactions` | `interactions` is an ordered array of steps (click/fill/select/hover/scroll/wait, the exact set `capture_screenshot`/`capture_screen_recording` replay) to reach the exact state the beat needs |
107
+ | `recording` | `url`, `interactions` | same shape as `screenshot`; the interactions happen while recording, not before |
108
+ | `dom-demo` | none | the beat's visual is authored directly in its scene file, no capture step |
109
+ | `higgsfield` | `higgsfieldPrompt` | the AI-generation prompt for the b-roll clip; must not request on-screen product text or real UI |
110
+
111
+ See section 6 below for a concrete `beats.json` fragment with one full,
112
+ working example of each of these four shapes.
113
+
114
+ ## 5. The mandatory approval gate
115
+
116
+ Once every beat has a decided `captureMethod` and the full `beats.json` is
117
+ drafted: show the dev the full file, not a summary, and get explicit
118
+ approval before persisting it. This applies even to a small, obviously
119
+ fine-looking draft.
120
+
121
+ The `write_beats_file` MCP tool will refuse to write anything
122
+ `validate_beats` hasn't passed, but that's schema/structural
123
+ validation, not dev approval. The human-approval step itself is a protocol
124
+ rule for the calling agent, not something any tool enforces. Skipping it
125
+ because the tool would technically allow the write is a protocol
126
+ violation.
127
+
128
+ ## 6. Worked example (fictional product, anonymized)
129
+
130
+ **Product:** "Loomcard," a spaced-repetition flashcard app for technical
131
+ interview prep.
132
+
133
+ **Intake answers (abbreviated):**
134
+ - One-liner: "Loomcard turns your notes into spaced-repetition flashcards
135
+ and schedules review so you actually remember them."
136
+ - Features to demo: card review flow, confidence-based scheduling that
137
+ adjusts in real time, CSV/Anki import (not wired up yet, a roadmap
138
+ item).
139
+ - Higgsfield access: yes.
140
+
141
+ **Resulting beats.json fragment** (hook / demo / differentiator / cta, one
142
+ of each `captureMethod` so the shapes above are all represented):
143
+
144
+ ```json
145
+ {
146
+ "fps": 30,
147
+ "title": "Loomcard",
148
+ "beats": [
149
+ {
150
+ "id": "hook",
151
+ "start": 0,
152
+ "duration": 180,
153
+ "vo": "Loomcard turns your notes into spaced-repetition flashcards, and schedules review so you actually remember them.",
154
+ "visual": {
155
+ "captureMethod": "higgsfield",
156
+ "higgsfieldPrompt": "slow push-in on a warm desk scene, hands resting near a closed notebook, soft morning light, no screens or readable text in frame, cinematic shallow depth of field"
157
+ }
158
+ },
159
+ {
160
+ "id": "demo-review",
161
+ "start": 180,
162
+ "duration": 120,
163
+ "vo": "Flip a card, and Loomcard scores your confidence on the spot.",
164
+ "visual": {
165
+ "captureMethod": "screenshot",
166
+ "url": "https://app.loomcard.example/review",
167
+ "interactions": [
168
+ { "type": "click", "selector": "[data-testid=flip-card]" },
169
+ { "type": "click", "selector": "[data-testid=confidence-4]" }
170
+ ]
171
+ }
172
+ },
173
+ {
174
+ "id": "demo-schedule",
175
+ "start": 300,
176
+ "duration": 240,
177
+ "vo": "That confidence score adjusts your next review date live, so easy cards fade back and hard ones come around sooner.",
178
+ "visual": {
179
+ "captureMethod": "recording",
180
+ "url": "https://app.loomcard.example/review",
181
+ "interactions": [
182
+ { "type": "click", "selector": "[data-testid=confidence-1]" },
183
+ { "type": "wait", "ms": 600 }
184
+ ]
185
+ }
186
+ },
187
+ {
188
+ "id": "cta",
189
+ "start": 540,
190
+ "duration": 180,
191
+ "vo": "Loomcard is free and open source. Star it, try it, or send a pull request.",
192
+ "visual": {
193
+ "captureMethod": "dom-demo"
194
+ }
195
+ }
196
+ ]
197
+ }
198
+ ```
199
+
200
+ Note the `demo-schedule` beat: the CSV/Anki import feature from intake was
201
+ dropped, not shown, because it isn't wired up yet and no real capture or
202
+ honest `dom-demo` was worth building for a roadmap item this early in the
203
+ pitch. A beat that claimed it anyway would have failed the
204
+ claim-obligates-visual rule (`SCRIPT.md`). The `cta` beat uses `dom-demo`
205
+ because `RepoCta` is a hand-authored scene built from real repo data, not
206
+ a captured screenshot of anything.
package/docs/SCRIPT.md ADDED
@@ -0,0 +1,50 @@
1
+ # SCRIPT.md: VO pacing and writing rules
2
+
3
+ VO for every video should sound like the same person wrote it: direct,
4
+ confident about what's actually shown, never claiming more than the visual
5
+ backs up.
6
+
7
+ ## Pace
8
+
9
+ Target **~2.3-2.9 words/sec**. This is edge-tts's natural reading pace at
10
+ default settings, the actual ratio observed across this pipeline's
11
+ production use, not a theoretical number. If you're writing VO for a beat
12
+ of known duration, word-count budget equals `duration_seconds * pace`;
13
+ stay inside that range rather than writing to a "feels about right" length
14
+ and hoping it fits.
15
+
16
+ ## Duration formula
17
+
18
+ When a beat's duration is being derived from its VO (rather than the other
19
+ way around):
20
+
21
+ ```
22
+ duration = (VO word count / pace) + pad
23
+ ```
24
+
25
+ Use a pad of **0.3-0.6s**. The pad exists so the visual doesn't cut the
26
+ instant speech ends: a beat that ends exactly when the last word does
27
+ reads as clipped, and a small buffer lets the shot breathe for a moment
28
+ before the cut.
29
+
30
+ ## The claim-obligates-visual rule
31
+
32
+ If a beat's VO asserts the product does something, the visual must back it
33
+ up: either a real capture (`screenshot`/`recording`) of the product
34
+ actually doing it, or an explicitly labeled `dom-demo` mockup built for a
35
+ feature that isn't wired up yet. Never let VO overclaim past what's on
36
+ screen. If the visual can't back a sentence, rewrite the sentence, don't
37
+ leave it in and hope no one checks.
38
+
39
+ This is the same rule `PIPELINE.md` states for beat authoring generally;
40
+ here it's specifically about VO, because VO is usually written first and
41
+ is where an overclaim first gets introduced. Use `PLANNING.md`'s
42
+ per-feature capture-method decision tree to decide, for each claim,
43
+ whether it needs a real capture or an honest `dom-demo`. Don't write a
44
+ claim the decision tree can't resolve to something real or
45
+ explicitly-labeled-constructed.
46
+
47
+ ## No em dashes
48
+
49
+ No em dashes in any VO line, ever, same writing rule as every other doc in
50
+ this pipeline. Use commas, periods, or a rewritten sentence instead.
package/docs/STYLE.md ADDED
@@ -0,0 +1,88 @@
1
+ # STYLE.md: Art Direction Bible
2
+
3
+ Binding rules for every video built with openvidstudio. If a scene violates
4
+ a rule here, it fails QC.
5
+
6
+ ## What good cinematography for this pipeline looks like (decoded)
7
+
8
+ 1. **Camera lives INSIDE the UI.** Never show a flat full-screen
9
+ screenshot. The camera is always zoomed into a region (120-250% scale),
10
+ slightly tilted (1-4 degrees rotateZ, 2-8 degrees rotateX/Y
11
+ perspective), and moving (push-in, drift, pan). UI is rendered oversized
12
+ on a stage; the camera crops into it.
13
+ 2. **Shallow depth of field.** One focal plane per shot. Everything else
14
+ (background layers, edge regions, sidebars) carries gaussian blur.
15
+ Focus can rack between layers mid-shot.
16
+ 3. **Low-key lighting.** Dark scenes: deep vignette, soft glow accents on
17
+ the key element (accent-colored text-shadow/box-shadow). Light scenes:
18
+ soft large-radius drop shadows, floating cards, generous negative
19
+ space.
20
+ 4. **Cursor is an actor.** Oversized cursor, eased movement (never
21
+ linear), click = ripple ring + glow pulse on the target. Buttons
22
+ visibly react.
23
+ 5. **The montage shot.** Isometric-tilted grid of floating UI windows,
24
+ depth-stacked, edges blurred, slow drift. Used for hooks/outros.
25
+ 6. **Warm/cool contrast.** Cool UI (blues, slate) against warm accent
26
+ lighting or warm desk tones.
27
+ 7. **Motion never stops.** Every shot has at least a subtle push-in (2-5%
28
+ scale over the shot). Static frame = dead frame = QC fail.
29
+
30
+ ## Hard rules
31
+
32
+ - NO linear easing. Ever. Use `@openvidstudio/core`'s `E.*` presets
33
+ (cinematic bezier / springs).
34
+ - Every scene wrapped in `CinematicScene` (grain + vignette + grade always
35
+ on).
36
+ - **On-screen text and UI is real by provenance, not by medium.** The
37
+ earlier version of this rule was "all text is DOM text," reasoned from
38
+ medium: anything not literally re-rendered as DOM inside the composition
39
+ wasn't trusted. That rule was a refinement waiting to happen: a genuine
40
+ screen recording of the real, running product isn't AI-hallucinated,
41
+ it's ground truth exactly like a screenshot is, so a medium-based rule
42
+ would have wrongly forbidden a legitimate capture method. The restated
43
+ rule: real product UI/text, whether DOM-rendered, screenshotted, or
44
+ screen-recorded, is always allowed on screen, because it's ground truth
45
+ by provenance. Screenshots may only appear inside `BrowserFrame`;
46
+ recordings composite as an `OffthreadVideo` inside a `Layer`, the same
47
+ camera-keyframe pattern. Both are captured per `CAPTURE.md`'s protocol
48
+ (a plain "set DPR to 2x" isn't enough on its own; the Playwright profile
49
+ can carry a per-origin zoom desync that silently shrinks/misframes an
50
+ uncompensated capture, and `CAPTURE.md`'s viewport-compensation plus
51
+ DOM-rect-crop steps are the actual fix). AI-generated clips (Higgsfield
52
+ or any future model) never carry on-screen product text or real UI:
53
+ b-roll/atmosphere only, see `HIGGSFIELD.md`.
54
+ - One focal point per shot. If two things matter, that's two shots.
55
+ - Text enters via mask reveal / clip-path wipe / per-word stagger, never
56
+ plain opacity fade.
57
+ - Cut rhythm: shots 1.5-5s. Hold longer only when content itself animates
58
+ (typing, install cascade).
59
+ - Terminal is always `TerminalReplay` (DOM), never screen-recorded HTML.
60
+ - SFX on every interaction: keystrokes (low volume 0.12-0.2), UI blips on
61
+ reveals, whoosh on camera moves/cuts, click ring + click sound together.
62
+ - Shot list per video lives in the video's own brief; camera keyframes
63
+ reference it.
64
+
65
+ ## Palette + type (defaults; per-video themes may override)
66
+
67
+ - Stage/dark bg: #0B0E14 to #11151F radial. Panel: #151A24. Border:
68
+ #232B3A.
69
+ - Text: #E6EAF2 primary, #8A94A6 secondary.
70
+ - Accent: #4E9EFF (cool blue) + #9D6BFF (violet), glow accents. Success:
71
+ #3ECF8E. Warn: #F5A623.
72
+ - Light scenes: bg #F4F6F9, cards #FFFFFF, shadow rgba(15,23,42,0.12)
73
+ large radius.
74
+ - Fonts: Inter (UI), JetBrains Mono (terminal/code) via
75
+ `@remotion/google-fonts`.
76
+ - Grain: 4-6% opacity, animated (re-seeded translate per frame). Vignette:
77
+ 25-40% edge darkening.
78
+
79
+ ## Deferred (do not attempt in pure Remotion)
80
+
81
+ - Live-action beats (desk/keyboard shots, ambient texture): text-free, so
82
+ these are the Higgsfield/AI-footage slot; see `HIGGSFIELD.md`. Still skip
83
+ by default: design scenes so they aren't needed unless a brief
84
+ specifically calls for a live-action beat, and never let an AI-generated
85
+ clip carry on-screen product text or real UI.
86
+ - Music beds (added with VO in post, or looped under a baked-in VO mix,
87
+ see `SCRIPT.md`). Chromatic aberration + real bloom passes (perf;
88
+ revisit).
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@openvidstudio/mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server exposing openvidstudio's mechanical pipeline tools: project scaffolding, beats validation, scene stubs, composition stitching, render, QC frame extraction, and zoom-compensated screenshot/screen-recording capture.",
5
+ "license": "Apache-2.0",
6
+ "type": "commonjs",
7
+ "bin": {
8
+ "openvidstudio-mcp": "dist/stdio.js"
9
+ },
10
+ "main": "./dist/server.js",
11
+ "types": "./dist/server.d.ts",
12
+ "files": [
13
+ "dist",
14
+ "templates",
15
+ "docs"
16
+ ],
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.30.0",
19
+ "playwright": "^1.48.0",
20
+ "sharp": "^0.33.5",
21
+ "zod": "^4.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "@types/node": "^22.10.5",
25
+ "typescript": "5.9.3"
26
+ },
27
+ "scripts": {
28
+ "build": "node scripts/copy-template.mjs && node scripts/copy-docs.mjs && tsc",
29
+ "prepublishOnly": "npm run build",
30
+ "typecheck": "tsc --noEmit",
31
+ "test": "node scripts/manual-test.mjs"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/AnayDhawan/openvidstudio.git",
39
+ "directory": "packages/mcp-server"
40
+ },
41
+ "homepage": "https://github.com/AnayDhawan/openvidstudio#readme",
42
+ "bugs": {
43
+ "url": "https://github.com/AnayDhawan/openvidstudio/issues"
44
+ },
45
+ "keywords": [
46
+ "mcp",
47
+ "model-context-protocol",
48
+ "remotion",
49
+ "playwright",
50
+ "video",
51
+ "demo-video",
52
+ "claude"
53
+ ]
54
+ }
@@ -0,0 +1,63 @@
1
+ # CLAUDE.md: this project's video pipeline
2
+
3
+ This project was scaffolded with openvidstudio: a Remotion + Playwright
4
+ video-generation add-on driven via MCP tools. If you're an AI coding agent
5
+ about to build a video for this project, read `PLANNING.md` first. That's
6
+ step 0, before you touch `beats.json` or write a single scene.
7
+
8
+ ## Docs
9
+
10
+ `init_project` copies these into this project's own `docs/` directory
11
+ when it scaffolds the project shell (it never overwrites a file you've
12
+ already edited, so a second `init_project` call for a second video won't
13
+ clobber local edits here). If a doc listed below is missing, re-run
14
+ `init_project` rather than guessing where it lives.
15
+
16
+ - `./docs/PLANNING.md`: start here. Guided intake to beats.json protocol,
17
+ capture-method decision tree, the mandatory approval gate.
18
+ - `./docs/PIPELINE.md`: beats.json, scenes, composition, QC loop.
19
+ - `./docs/STYLE.md`: binding art-direction rules.
20
+ - `./docs/CAPTURE.md`: real-screenshot protocol.
21
+ - `./docs/SCRIPT.md`: VO pacing and writing rules.
22
+ - `./docs/OVERVIEW.md`: conceptual overview; read this if you're unsure
23
+ why any of the rules below exist.
24
+ - `./docs/HIGGSFIELD.md`: AI b-roll tier protocol.
25
+ - `./docs/API.md`: every prop of every `@openvidstudio/core` component. Read
26
+ this instead of opening the library source.
27
+ - `./docs/NARRATION.md`: voice, music and sound effects, and why generated
28
+ voiceover usually sounds synthetic.
29
+
30
+ ## Rules a scene-writing agent must never violate
31
+
32
+ These are QC-fail rules, not defaults, pulled from `STYLE.md` and
33
+ `PIPELINE.md` and restated here because they're the ones most likely to get
34
+ silently broken while writing a scene:
35
+
36
+ - **No linear easing, ever.** Use the eased/spring presets
37
+ `@openvidstudio/core` exports from its motion helpers. A static,
38
+ non-eased move fails QC.
39
+ - **Every scene wrapped in `CinematicScene`.** No screen ever renders
40
+ outside it (grain, vignette, and grade are always on).
41
+ - **Motion never stops.** Every shot needs at least a subtle push-in. A
42
+ frozen frame is a QC fail.
43
+ - **No em dashes**, on screen or in VO, anywhere.
44
+
45
+ ## Before you hand-write a scene
46
+
47
+ `scaffold_scene` emits a scene that renders, using that beat's own copy and
48
+ duration. Start from it and edit the content rather than composing a scene
49
+ from primitives: it already has correct camera keyframes, a safe content
50
+ width, and the right shape for the beat's capture method.
51
+
52
+ Then run `validate_scenes`. The commonest mistake in this pipeline is
53
+ invisible: content laid out at full stage width gets cropped once the camera
54
+ pushes in, and the render does not warn.
55
+
56
+ ## Components
57
+
58
+ Reach for `@openvidstudio/core`'s components before building anything new:
59
+ `CinematicScene`, `CameraRig`/`Layer`, `BrowserFrame`, `TerminalReplay`,
60
+ `CodePanel`, `ChecklistPanel`, `CursorActor`, `RepoCta`,
61
+ `TitleSlam`/`Caption`. Only build a new component when a beat truly needs
62
+ one, then keep it generic: it's a candidate for `@openvidstudio/core`
63
+ itself, not just this project.
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@openvidstudio/core",
3
+ "version": "0.1.0",
4
+ "description": "Camera rig, motion, SFX, look pass, and scene components shared by every openvidstudio video project.",
5
+ "license": "Apache-2.0",
6
+ "type": "commonjs",
7
+ "main": "src/index.ts",
8
+ "types": "src/index.ts",
9
+ "files": [
10
+ "src",
11
+ "scripts",
12
+ "public"
13
+ ],
14
+ "dependencies": {
15
+ "@remotion/google-fonts": "^4.0.490"
16
+ },
17
+ "peerDependencies": {
18
+ "react": "19.2.3",
19
+ "react-dom": "19.2.3",
20
+ "remotion": "4.0.490"
21
+ },
22
+ "devDependencies": {
23
+ "@types/react": "19.2.7",
24
+ "react": "19.2.3",
25
+ "react-dom": "19.2.3",
26
+ "remotion": "4.0.490",
27
+ "typescript": "5.9.3"
28
+ },
29
+ "scripts": {
30
+ "typecheck": "tsc --noEmit"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/AnayDhawan/openvidstudio.git",
38
+ "directory": "packages/core"
39
+ },
40
+ "homepage": "https://github.com/AnayDhawan/openvidstudio#readme",
41
+ "bugs": {
42
+ "url": "https://github.com/AnayDhawan/openvidstudio/issues"
43
+ },
44
+ "keywords": [
45
+ "remotion",
46
+ "video",
47
+ "demo-video",
48
+ "screencast",
49
+ "mcp"
50
+ ]
51
+ }
@@ -0,0 +1,74 @@
1
+ #!/bin/bash
2
+ # Generate synthesized UI SFX into public/sfx/ (no licensing, fully reproducible).
3
+ # Swap any file for a real recorded pack later, sfx.tsx API stays identical.
4
+ set -e
5
+ cd "$(dirname "$0")/.."
6
+ mkdir -p public/sfx
7
+
8
+ # Mechanical key thocks: filtered brown-noise bursts, 3 pitch variations
9
+ ffmpeg -v error -y -f lavfi -i "anoisesrc=d=0.06:c=brown:a=0.9" \
10
+ -af "highpass=f=180,lowpass=f=2400,afade=t=in:d=0.004,afade=t=out:st=0.025:d=0.035,volume=3.2" \
11
+ public/sfx/key_a.wav
12
+ ffmpeg -v error -y -f lavfi -i "anoisesrc=d=0.055:c=brown:a=0.9:seed=7" \
13
+ -af "highpass=f=200,lowpass=f=1900,afade=t=in:d=0.004,afade=t=out:st=0.022:d=0.033,volume=3.4" \
14
+ public/sfx/key_b.wav
15
+ ffmpeg -v error -y -f lavfi -i "anoisesrc=d=0.065:c=brown:a=0.9:seed=23" \
16
+ -af "highpass=f=160,lowpass=f=2900,afade=t=in:d=0.004,afade=t=out:st=0.028:d=0.037,volume=3.0" \
17
+ public/sfx/key_c.wav
18
+
19
+ # Click: sharp short tick
20
+ ffmpeg -v error -y -f lavfi -i "anoisesrc=d=0.03:c=white:a=0.8" \
21
+ -af "highpass=f=1400,lowpass=f=6500,afade=t=in:d=0.002,afade=t=out:st=0.01:d=0.02,volume=2.2" \
22
+ public/sfx/click.wav
23
+
24
+ # Whoosh: bandpassed pink noise swell
25
+ ffmpeg -v error -y -f lavfi -i "anoisesrc=d=0.55:c=pink:a=0.8" \
26
+ -af "bandpass=f=650:w=500,afade=t=in:d=0.18,afade=t=out:st=0.25:d=0.3,volume=2.6" \
27
+ public/sfx/whoosh.wav
28
+
29
+ # Blip: soft sine tick for UI reveals
30
+ ffmpeg -v error -y -f lavfi -i "sine=frequency=740:duration=0.07" \
31
+ -af "afade=t=in:d=0.008,afade=t=out:st=0.03:d=0.04,volume=0.9" \
32
+ public/sfx/blip.wav
33
+
34
+ # Success: rising two-tone
35
+ ffmpeg -v error -y \
36
+ -f lavfi -i "sine=frequency=660:duration=0.09" \
37
+ -f lavfi -i "sine=frequency=990:duration=0.14" \
38
+ -filter_complex "[0]afade=t=out:st=0.05:d=0.04[a];[1]afade=t=in:d=0.01,afade=t=out:st=0.08:d=0.06[b];[a][b]concat=n=2:v=0:a=1,volume=0.9" \
39
+ public/sfx/success.wav
40
+
41
+ echo "SFX generated:"
42
+ ls public/sfx/
43
+
44
+ # Bell: struck metallic tone, harmonic stack with a long decay
45
+ ffmpeg -v error -y \
46
+ -f lavfi -i "sine=frequency=1568:duration=1.6" \
47
+ -f lavfi -i "sine=frequency=2350:duration=1.6" \
48
+ -f lavfi -i "sine=frequency=3136:duration=1.6" \
49
+ -filter_complex "[0]volume=1.0[a];[1]volume=0.45[b];[2]volume=0.22[c];[a][b][c]amix=inputs=3:normalize=0,afade=t=in:d=0.004,afade=t=out:st=0.12:d=1.45,volume=1.2" \
50
+ public/sfx/bell.wav
51
+
52
+ # Enter key: deeper, heavier thock than a letter key
53
+ ffmpeg -v error -y -f lavfi -i "anoisesrc=d=0.085:c=brown:a=0.95:seed=41" \
54
+ -af "highpass=f=110,lowpass=f=1500,afade=t=in:d=0.004,afade=t=out:st=0.03:d=0.05,volume=3.6" \
55
+ public/sfx/key_enter.wav
56
+
57
+ # Music bed: slow ambient pad, two detuned sines under a filtered noise wash.
58
+ # Synthesized rather than licensed, so a generated video carries no third-party
59
+ # audio rights. 60s, loop it for longer videos.
60
+ ffmpeg -v error -y \
61
+ -f lavfi -i "sine=frequency=110:duration=60" \
62
+ -f lavfi -i "sine=frequency=164.81:duration=60" \
63
+ -f lavfi -i "sine=frequency=220.5:duration=60" \
64
+ -f lavfi -i "anoisesrc=d=60:c=pink:a=0.06" \
65
+ -filter_complex "\
66
+ [0]volume=0.34,tremolo=f=0.11:d=0.30[p1];\
67
+ [1]volume=0.20,tremolo=f=0.13:d=0.26[p2];\
68
+ [2]volume=0.13,tremolo=f=0.17:d=0.35[p3];\
69
+ [3]lowpass=f=900,volume=0.5[air];\
70
+ [p1][p2][p3][air]amix=inputs=4:normalize=0,\
71
+ lowpass=f=2600,afade=t=in:d=3,afade=t=out:st=56:d=4,volume=0.5" \
72
+ -c:a libmp3lame -q:a 5 public/sfx/music-bed.mp3
73
+
74
+ echo "generated: $(ls public/sfx | wc -l) files in public/sfx/"