@vibeo/cli 0.3.4 → 0.4.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.
@@ -0,0 +1,348 @@
1
+ # Vibeo Editor (`@vibeo/editor`)
2
+
3
+ ## Overview
4
+
5
+ `@vibeo/editor` is a visual video editing studio for Vibeo. It provides a dark-themed, multi-track timeline editor with canvas preview, property editing, drag-and-drop clip manipulation, audio waveforms, subtitle editing, and export controls.
6
+
7
+ **When to use**: When you need a visual editing interface for Vibeo compositions, or when building a custom video editor UI on top of Vibeo.
8
+
9
+ ---
10
+
11
+ ## Quick Start
12
+
13
+ ### CLI (recommended)
14
+
15
+ ```bash
16
+ # Open the editor for a Vibeo project
17
+ bunx @vibeo/cli editor --entry src/index.tsx
18
+
19
+ # With custom port
20
+ bunx @vibeo/cli editor --entry src/index.tsx --port 8080
21
+ ```
22
+
23
+ In a scaffolded project (`bunx @vibeo/cli create my-video`), just run:
24
+
25
+ ```bash
26
+ bun run editor
27
+ ```
28
+
29
+ ### Programmatic
30
+
31
+ ```tsx
32
+ import { Editor } from "@vibeo/editor";
33
+
34
+ const compositions = [
35
+ {
36
+ id: "MyComp",
37
+ name: "My Composition",
38
+ component: MyVideoComponent,
39
+ width: 1920,
40
+ height: 1080,
41
+ fps: 30,
42
+ durationInFrames: 300,
43
+ },
44
+ ];
45
+
46
+ function App() {
47
+ return <Editor compositions={compositions} />;
48
+ }
49
+ ```
50
+
51
+ ---
52
+
53
+ ## API Reference
54
+
55
+ ### `Editor`
56
+
57
+ The root editor component. Renders the full editor UI.
58
+
59
+ ```tsx
60
+ <Editor compositions={compositions} />
61
+ ```
62
+
63
+ **Props:**
64
+ - `compositions` — Array of composition entries:
65
+ - `id: string` — unique composition identifier
66
+ - `name: string` — display name
67
+ - `component: React.ComponentType` — the React component to render
68
+ - `width: number` — composition width in pixels
69
+ - `height: number` — composition height in pixels
70
+ - `fps: number` — frames per second
71
+ - `durationInFrames: number` — total duration in frames
72
+
73
+ ### `EditorProvider`
74
+
75
+ Context provider wrapping the editor state. Use if you need to embed editor components individually.
76
+
77
+ ```tsx
78
+ import { EditorProvider } from "@vibeo/editor";
79
+
80
+ <EditorProvider>
81
+ {/* editor components */}
82
+ </EditorProvider>
83
+ ```
84
+
85
+ ---
86
+
87
+ ## Editor Layout
88
+
89
+ ```
90
+ ┌─────────────────────────────────────────────────────────────┐
91
+ │ Toolbar: [⟲ Undo] [⟳ Redo] CompositionName 100% │
92
+ ├──────────┬─────────────────────────────────┬────────────────┤
93
+ │ SCENES │ │ PROPERTIES │
94
+ │ & TRACKS │ Canvas Preview │ Canvas: W × H │
95
+ │ │ (live composition with │ Duration: N │
96
+ │ 🎬 Scene1│ checkerboard background) │ FPS: 30 │
97
+ │ 🎵 Audio │ │ │
98
+ │ 📝 Subs │ │ EXPORT │
99
+ │ │ │ Codec: H.264 │
100
+ │ [+Add] ├──── |◀ ▶ ▶| 00:00 / 03:33 1x ──│ [Render video] │
101
+ ├──────────┴─────────────────────────────────┴────────────────┤
102
+ │ Timeline: ruler with time markers [- zoom +] │
103
+ │ Track 1: [████ Scene A ████][████ Scene B ████] │
104
+ │ Track 2: [████████ Audio Track ████████] │
105
+ │ Track 3: [Sub1] [Sub2] [Sub3] │
106
+ │ ▲ playhead cursor (draggable) │
107
+ └─────────────────────────────────────────────────────────────┘
108
+ ```
109
+
110
+ ### Panels
111
+
112
+ | Panel | Location | Purpose |
113
+ |-------|----------|---------|
114
+ | Toolbar | Top | Undo/redo, composition name, zoom % |
115
+ | Scene List | Left sidebar | Track list with visibility/mute toggles, "+ Add Track" |
116
+ | Canvas | Center top | Live preview of active composition |
117
+ | Playback Controls | Center middle | Play/pause, frame step, timecode, rate, loop |
118
+ | Timeline | Center bottom | Multi-track clip editor with ruler and playhead |
119
+ | Properties | Right sidebar | Editable props for selected clip, composition info, export |
120
+
121
+ All panels are resizable via drag handles between them.
122
+
123
+ ---
124
+
125
+ ## State Management
126
+
127
+ The editor uses `useReducer` with an immutable state model and undo/redo history.
128
+
129
+ ### EditorState
130
+
131
+ ```ts
132
+ interface EditorState {
133
+ tracks: Track[];
134
+ selectedTrackId: string | null;
135
+ selectedClipId: string | null;
136
+ playing: boolean;
137
+ frame: number;
138
+ fps: number;
139
+ durationInFrames: number;
140
+ compositionWidth: number;
141
+ compositionHeight: number;
142
+ playbackRate: number;
143
+ zoom: number;
144
+ scrollX: number;
145
+ }
146
+ ```
147
+
148
+ ### Track & Clip Types
149
+
150
+ ```ts
151
+ type TrackType = "scene" | "audio" | "subtitle";
152
+
153
+ interface Track {
154
+ id: string;
155
+ name: string;
156
+ type: TrackType;
157
+ clips: Clip[];
158
+ visible: boolean;
159
+ muted: boolean;
160
+ }
161
+
162
+ interface Clip {
163
+ id: string;
164
+ trackId: string;
165
+ name: string;
166
+ from: number; // start frame
167
+ durationInFrames: number;
168
+ type: TrackType;
169
+ data: any; // type-specific data
170
+ }
171
+ ```
172
+
173
+ ### Actions
174
+
175
+ | Action | Description |
176
+ |--------|-------------|
177
+ | `ADD_TRACK` | Add a new track (scene/audio/subtitle) |
178
+ | `REMOVE_TRACK` | Remove a track and all its clips |
179
+ | `ADD_CLIP` | Add a clip to a track |
180
+ | `REMOVE_CLIP` | Remove a clip |
181
+ | `MOVE_CLIP` | Change a clip's `from` position |
182
+ | `RESIZE_CLIP` | Change a clip's `from` and/or `durationInFrames` |
183
+ | `SELECT_CLIP` | Select a clip (highlights in timeline, shows in properties) |
184
+ | `SET_FRAME` | Set the current playhead frame |
185
+ | `SET_PLAYING` | Toggle playback |
186
+ | `SET_ZOOM` | Set timeline zoom level |
187
+ | `UNDO` | Undo last action |
188
+ | `REDO` | Redo undone action |
189
+
190
+ ---
191
+
192
+ ## Timeline
193
+
194
+ ### Clip Colors
195
+
196
+ | Type | Color | Hex |
197
+ |------|-------|-----|
198
+ | Scene | Purple | `#8b5cf6` |
199
+ | Audio | Green | `#22c55e` |
200
+ | Subtitle | Yellow | `#eab308` |
201
+
202
+ ### Timeline Math
203
+
204
+ ```
205
+ pixelsPerFrame = basePixelsPerFrame * zoom (base = 2)
206
+ clipLeft = clip.from * pixelsPerFrame
207
+ clipWidth = clip.durationInFrames * pixelsPerFrame
208
+ cursorLeft = currentFrame * pixelsPerFrame
209
+ totalWidth = durationInFrames * pixelsPerFrame
210
+ ```
211
+
212
+ ### Drag-and-Drop
213
+
214
+ - **Move clip**: drag the clip body to change its `from` position
215
+ - **Resize clip**: drag left/right edges to trim `from`/`durationInFrames`
216
+ - **Minimum**: 1 frame
217
+ - **Snap**: rounds to nearest integer frame
218
+
219
+ ---
220
+
221
+ ## Keyboard Shortcuts
222
+
223
+ | Key | Action |
224
+ |-----|--------|
225
+ | Space | Play / Pause |
226
+ | ArrowLeft | Previous frame |
227
+ | ArrowRight | Next frame |
228
+ | Shift+ArrowLeft | -10 frames |
229
+ | Shift+ArrowRight | +10 frames |
230
+ | Cmd/Ctrl+Z | Undo |
231
+ | Cmd/Ctrl+Shift+Z | Redo |
232
+ | Delete / Backspace | Remove selected clip |
233
+ | Escape | Deselect |
234
+ | ? | Show keyboard shortcuts |
235
+
236
+ ---
237
+
238
+ ## Dark Theme
239
+
240
+ All colors are defined in `@vibeo/editor/theme/colors`:
241
+
242
+ | Token | Value | Usage |
243
+ |-------|-------|-------|
244
+ | `bg` | `#0d1117` | Darkest background |
245
+ | `surface` | `#161b22` | Panel backgrounds |
246
+ | `surfaceHover` | `#1c2333` | Hover states |
247
+ | `border` | `#30363d` | Borders |
248
+ | `text` | `#e6edf3` | Primary text |
249
+ | `textMuted` | `#7d8590` | Secondary text |
250
+ | `accent` | `#58a6ff` | Playhead, selection, focus rings |
251
+ | `scene` | `#8b5cf6` | Scene clip color |
252
+ | `audio` | `#22c55e` | Audio clip color |
253
+ | `subtitle` | `#eab308` | Subtitle clip color |
254
+ | `danger` | `#f85149` | Delete, errors |
255
+
256
+ ---
257
+
258
+ ## Common Patterns
259
+
260
+ ### Adding a scene track with a clip
261
+
262
+ ```ts
263
+ dispatch({ type: "ADD_TRACK", payload: { id: "track-1", name: "Main Scene", type: "scene" } });
264
+ dispatch({
265
+ type: "ADD_CLIP",
266
+ payload: {
267
+ id: "clip-1",
268
+ trackId: "track-1",
269
+ name: "Intro",
270
+ from: 0,
271
+ durationInFrames: 90,
272
+ type: "scene",
273
+ data: { component: IntroScene },
274
+ },
275
+ });
276
+ ```
277
+
278
+ ### Adding an audio track
279
+
280
+ ```ts
281
+ dispatch({ type: "ADD_TRACK", payload: { id: "track-2", name: "Background Music", type: "audio" } });
282
+ dispatch({
283
+ type: "ADD_CLIP",
284
+ payload: {
285
+ id: "clip-2",
286
+ trackId: "track-2",
287
+ name: "Music",
288
+ from: 0,
289
+ durationInFrames: 300,
290
+ type: "audio",
291
+ data: { src: "/music.mp3", volume: 0.8 },
292
+ },
293
+ });
294
+ ```
295
+
296
+ ### Adding subtitle cues
297
+
298
+ ```ts
299
+ dispatch({ type: "ADD_TRACK", payload: { id: "track-3", name: "Subtitles", type: "subtitle" } });
300
+ dispatch({
301
+ type: "ADD_CLIP",
302
+ payload: {
303
+ id: "sub-1",
304
+ trackId: "track-3",
305
+ name: "Welcome",
306
+ from: 15,
307
+ durationInFrames: 75,
308
+ type: "subtitle",
309
+ data: { text: "Welcome to the demo", fontSize: 36, color: "white", position: "bottom" },
310
+ },
311
+ });
312
+ ```
313
+
314
+ ---
315
+
316
+ ## Gotchas
317
+
318
+ 1. **Editor creates its own providers** — it wraps content in `VibeoRoot`, `TimelineProvider`, etc. Don't nest it inside another `VibeoRoot` manually.
319
+
320
+ 2. **Compositions must export a `Root` function** — the CLI editor command imports `{ Root }` from your entry file to register compositions.
321
+
322
+ 3. **The editor renders the Player internally** — it uses `@vibeo/player` to show the canvas preview. Frame sync is handled automatically.
323
+
324
+ 4. **Undo/redo is state-level** — every dispatched action pushes to the history stack. `UNDO`/`REDO` actions navigate the stack.
325
+
326
+ 5. **Timeline zoom range** — 0.1x to 10x. Default is 1x where `pixelsPerFrame = 2`.
327
+
328
+ 6. **Audio waveform** — rendered as canvas bars inside audio clips. If audio analysis isn't available, shows flat placeholder bars.
329
+
330
+ 7. **Subtitle inline editing** — double-click a subtitle cue in the timeline to edit text inline. Press Escape or click outside to save.
331
+
332
+ ---
333
+
334
+ ## LLM & Agent Integration
335
+
336
+ ```bash
337
+ # Get CLI docs including editor command
338
+ bunx @vibeo/cli --llms
339
+
340
+ # Get editor command schema
341
+ bunx @vibeo/cli editor --schema
342
+
343
+ # Install skills for all LLM tools
344
+ bunx @vibeo/cli install-skills
345
+
346
+ # Run as MCP server (includes editor command)
347
+ bunx @vibeo/cli --mcp
348
+ ```