@vosjs/studio-core 0.4.0 → 0.4.1
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 +69 -52
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,69 +1,86 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @vosjs/studio-core
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
screen recording into an editable, re-renderable video: the `ProjectDoc` schema,
|
|
5
|
-
the element-aware auto-zoom planner, and the lowering that compiles a doc down to
|
|
6
|
-
a vos composition.
|
|
3
|
+
> The document model of a screen recording: the `ProjectDoc` schema, the planners that read a cursor track (auto-zoom, speed, tilt), the digest that lets an agent see a recording, and the lowering from a document to a vos program.
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@vosjs/studio-core)
|
|
6
|
+
[](https://github.com/vosjs/vos/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
Part of [vos](https://github.com/vosjs/vos), the open programmatic video engine behind [vos.so](https://vos.so). This package holds the opinions that turn raw footage plus a cursor track into an editable, re-renderable video. It is pure logic: no DOM, no React, no engine import at run time (`@vosjs/core` is a peer for types). The generic editing mechanics (patch store, edit classifier, bridge client, view-model math) live in [`@vosjs/editor`](../editor); the time math in [`@vosjs/timeline`](../timeline). The `vos` CLI and the vos.so studio both build on this package, so a document cut on the command line opens in the studio with every span intact.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pnpm add @vosjs/studio-core
|
|
14
|
+
```
|
|
13
15
|
|
|
14
16
|
## The pipeline
|
|
15
17
|
|
|
16
18
|
```
|
|
17
|
-
RecordingArtifact ──projectFromArtifact──▶ ProjectDoc ──
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
RecordingArtifact ──projectFromArtifact──▶ ProjectDoc ──lowerStudioDoc──▶ { config, data, stack, duration }
|
|
20
|
+
(footage + cursor track) normalize capture space, (doc.json: the constant program + ctx.data,
|
|
21
|
+
plan zoom / speed / tilt editable surface) so every edit is live
|
|
20
22
|
```
|
|
21
23
|
|
|
22
|
-
- **`projectFromArtifact(artifact)`**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
24
|
+
- **`projectFromArtifact(artifact, videoUrl, { frame? })`** builds the initial `ProjectDoc` from a recording: normalize the capture space (`normalizeCaptureSpace`; a viewport crop for window takes via `deriveViewportCrop`, fail-closed below `CAPTURE_COVERAGE_MIN`), then seed the automatic spans. Returns `{ doc, videoUrl }`.
|
|
25
|
+
- **The planners** read the cursor track, never the pixels. `planAutoZoom(track, { width, height, style?, params? })` emits `source: 'auto'` zoom spans from click clusters (`z…`), typing sessions (`k…`) and dwells (`d…`); `planAutoSpeed` proposes speed-ups over idle gaps and scroll runs; `planAutoTilt` leans the card toward each zoom's focus. Every planner honors the wand contract: `source: 'manual'` spans are never touched, and a deleted proposal stays deleted (`rejectSpan` writes `doc.rejected`, `isRejected` filters the next plan).
|
|
26
|
+
- **`lowerStudioDoc(doc)`** lowers a document to a constant vos program plus a `ctx.data` payload. Zoom, tilt and cam-motion spans expand into output-time keyframe tracks; trims, speed, cursor follow, click effects and audio envelopes all bake into data. Because the program string is constant, edits replay live through `SET_DATA` and `SET_DURATION`; nothing recompiles for a retime or a zoom tweak. `lowerToComposition` is the recording-only path underneath it.
|
|
27
|
+
|
|
28
|
+
## Two documents, one editor
|
|
29
|
+
|
|
30
|
+
`StudioDoc = ProjectDoc | ProgramAnchorDoc`, discriminated on `source`. A `ProjectDoc` is a recording: footage, `segments` (the kept source spans), `zoom`, `speed`, `tilt`, `camMotion`, the frame and cursor styles, plus the shared layers. A `ProgramAnchorDoc` is a vos program that gained the same shared layers (text, image and video overlays, 3D objects, audio clips, speed spans, a tween-retime overlay) without those being written into its config. `anchorKindOf`, `isRecordingDoc` and `isProgramDoc` read the discriminator; `lowerProgramDoc` lowers the program kind. Hosted documents carry `docSchemaVersion` (`DOC_SCHEMA_VERSION`, currently 2) and are upgraded on read with `migrateHostedDoc`.
|
|
31
|
+
|
|
32
|
+
The shared layers lower as one engine `stack` entry, `STUDIO_ENTRY_ID` (`'vosso.studio'`), with its own data (`studioLayerData`), so either document kind hosts them and the engine's `SET_DATA { target }` updates them alone. `studioAudioPlan` turns the entry's audio clips and duck curve into the plan `@vosjs/core/audio` mixes.
|
|
33
|
+
|
|
34
|
+
## Time and space conventions
|
|
35
|
+
|
|
36
|
+
- **Seconds everywhere.** Zoom, speed, tilt and cam-motion spans and the cursor samples are anchored in source time, so they follow footage through trims. Overlays, audio clips and click effects are anchored in output time, so a title keeps its perceived length through a speed change. `ratedSegments`, `effectiveSegments`, `docOutputDuration` and `outputRangeToSource` are the remaps.
|
|
37
|
+
- **Normalized coordinates.** A zoom's `cx`/`cy` and an overlay's `transform.x`/`y` are fractions of the frame in `[0, 1]`, never pixels, so a document survives an aspect-ratio switch. `focusBounds` and `clampFocus` keep a focus inside the card at a given `level`.
|
|
38
|
+
- **Camera styles.** `ZOOM_STYLES` names eight camera personalities (`glide`, the default, then `focus`, `cinema`, `snappy`, `cut`, `keynote`, `drift`, `none`); a style parametrizes both the planner and the camera motion, and `doc.zoomParams` layers per-document overrides.
|
|
39
|
+
- **The stage.** `CARD_FOV`, `CARD_Z`, `OVERLAY_Z`, `BACKGROUND_Z` and `planeSizeAtDepth` define the frustum-filling planes the program draws (background, the tiltable card, the overlay); `computeCardLayout` and `docCardLayout` are the host-side mirror of the program's card math, pinned to it by tests.
|
|
40
|
+
- **Backdrops.** `withBackdrop(frame, backdrop)` and `backdropMedia` put a looping video or a still behind the card, output-anchored modulo its duration. The package carries the mechanism and `BASE_FRAME_STYLE`; which loop a host opens on is the host's choice.
|
|
41
|
+
|
|
42
|
+
## Seeing a recording: the digest
|
|
43
|
+
|
|
44
|
+
`momentsFromDoc`, `sceneChanges` and `buildDigest` derive the moments of a recording from its cursor track (click clusters, typing sessions, scroll runs, dwells, idle gaps, head, tail, frame-diff scene changes), each with source and output extents, a normalized focus rectangle a zoom span can copy, and the ids of the planner's proposals over it. `zoomCoversRect` and `zoomWindow` are the framing lint that closes the loop. The CLI's `vos digest` writes it as `digest.json` beside footage frames and crops; `STYLE_FIELDS`, `copyStyle` and `pickStyle` carry a signed-off document's look onto the next take.
|
|
45
|
+
|
|
46
|
+
## Destinations
|
|
47
|
+
|
|
48
|
+
`DESTINATIONS` is the table of launch destinations (store listings, Product Hunt, social, OG cards, README loops) with exact pixel sizes, byte and duration ceilings, generated from `channel-specs.json` in `@vosjs/cli` and hash-gated by a test. `destinationById`, `destinationsForChannel`, `exportSizeFor(ratio, resolution)` and `resolveExportSize` size an export; `ExportResolution` is `720p | 1080p | 2k | 4k`.
|
|
49
|
+
|
|
50
|
+
## Exports by area
|
|
51
|
+
|
|
52
|
+
| Area | Exports |
|
|
53
|
+
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
54
|
+
| Ingest | `projectFromArtifact`, `normalizeCaptureSpace`, `deriveViewportCrop`, `docToCropSpace`, `docToFullSpace`, `CAPTURE_COVERAGE_MIN`, `WINDOW_FOCUS_MIN` |
|
|
55
|
+
| Document | `StudioDoc`, `ProjectDoc`, `ProgramAnchorDoc`, `anchorKindOf`, `isRecordingDoc`, `isProgramDoc`, `DOC_SCHEMA_VERSION`, `migrateHostedDoc`, `DEFAULT_FRAME_STYLE`, `BASE_FRAME_STYLE`, the constants (`ZOOM_LEVELS`, `TILT_DEG_MAX`, …) |
|
|
56
|
+
| Planners | `planAutoZoom`, `planAutoSpeed`, `planAutoTilt`, `smoothCursor`, `idleGaps`, `scrollRuns`, `rejectSpan`, `isRejected`, `withoutRejected` |
|
|
57
|
+
| Camera styles | `ZOOM_STYLES`, `ZOOM_STYLE_OPTIONS`, `DEFAULT_ZOOM_STYLE`, `resolveZoomStyle` |
|
|
58
|
+
| Lowering | `lowerStudioDoc`, `lowerProgramDoc`, `lowerToComposition`, `zoomTrackFromDoc`, `tiltTrackFromDoc`, `camTrackFromDoc`, `motionTrack`, `followFocusEvents`, `extractClicks`, `cursorIdleFade`, `ratedSegments`, `STUDIO_ENTRY_ID`, `studioEntry`, `studioLayerData` |
|
|
59
|
+
| Layout | `computeCardLayout`, `docCardLayout`, `focusBounds`, `clampFocus`, `camBubbleRectAt`, `overlayRect`, `overlayHit`, `CARD_FOV`, `CARD_Z`, `planeSizeAtDepth`, `recommendedExportResolution` |
|
|
60
|
+
| Text | `TEXT_PRESETS`, `OVERLAY_FONT_FACES`, `resolveOverlayStyle`, `resolveOverlayBox`, `resolveText3dAsset` |
|
|
61
|
+
| Audio | `studioAudioPlan`, `clipEnvelope`, `duckCurve`, `computePeaks`, `computeMicRms`, `voiceKey`, `musicBedClip`, `refillAudioBeds` |
|
|
62
|
+
| Backdrops | `withBackdrop`, `backdropMedia` |
|
|
63
|
+
| Digest | `momentsFromDoc`, `planForDigest`, `buildDigest`, `sceneChanges`, `zoomCoversRect`, `zoomWindow`, `cropBox`, `frameGeometry`, `STYLE_FIELDS`, `copyStyle`, `pickStyle`, `DIGEST_VERSION` |
|
|
64
|
+
| Destinations | `DESTINATIONS`, `destinationById`, `destinationsForChannel`, `exportSizeFor`, `resolveExportSize`, `ASPECT_RATIOS` |
|
|
65
|
+
| Timeline lanes | `videoLane`, `micLane`, `camLane`, `zoomLane`, `tiltLane`, `camMoveLane`, `speedLane`, `overlaysLane`, `objectsLane`, `audioLane`; range actions `outputRangeToSource`, `removeSourceRange`, `setSpeedInRange`, `zoomSpanForRange` |
|
|
66
|
+
|
|
67
|
+
The full document shape is in [`src/types.ts`](src/types.ts); the JSON Schema that ships to users is [`doc.schema.json`](../cli/schema/doc.schema.json) in `@vosjs/cli`.
|
|
49
68
|
|
|
50
69
|
## Design rules
|
|
51
70
|
|
|
52
|
-
- **Never bake
|
|
53
|
-
|
|
54
|
-
- **
|
|
55
|
-
be a pure function of `t`, so cursor follow, click effects, and zoom are all
|
|
56
|
-
computed from the doc up front.
|
|
57
|
-
- **Source-anchored spans.** Zoom and speed spans are anchored in source time and
|
|
58
|
-
follow footage through trims; the lowering remaps them to output time.
|
|
71
|
+
- **Never bake a document value into the program string.** The program is a structural hash; all editable state travels in `ctx.data`. Baking a value breaks live editing.
|
|
72
|
+
- **Lowering is deterministic.** No stateful springs, no wall clock: `seek(t)` is a pure function of `t`, so cursor follow, click effects and zoom are computed from the document up front.
|
|
73
|
+
- **Perception reads the recording, never the composition.** The planners and the digest read the cursor track and the footage; they never inspect a rendered frame.
|
|
59
74
|
|
|
60
75
|
## Development
|
|
61
76
|
|
|
62
77
|
```bash
|
|
63
|
-
pnpm --filter @
|
|
64
|
-
pnpm --filter @
|
|
78
|
+
pnpm --filter @vosjs/studio-core test
|
|
79
|
+
pnpm --filter @vosjs/studio-core typecheck
|
|
65
80
|
```
|
|
66
81
|
|
|
67
|
-
The
|
|
68
|
-
|
|
69
|
-
|
|
82
|
+
The test suite pins the invariants that are easy to break: the capture-space fail-closed matrix, zoom keyframe expansion, click extraction, layout-to-program parity, byte-identical lowering when a feature is absent, and the destinations hash. Extend it when touching the lowering.
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
[MIT](https://github.com/vosjs/vos/blob/main/LICENSE) © vosso
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vosjs/studio-core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "The studio's editing model: the ProjectDoc schema, the element-aware auto-zoom planner and cursor smoothing, the lowering from a document to a vos composition, and the timeline lane adapters. Generic editing mechanisms live in @vosjs/editor.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "vosso",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
],
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@vosjs/editor": "^1.3.
|
|
31
|
-
"@vosjs/shared": "^0.4.
|
|
32
|
-
"@vosjs/timeline": "^0.4.
|
|
30
|
+
"@vosjs/editor": "^1.3.1",
|
|
31
|
+
"@vosjs/shared": "^0.4.1",
|
|
32
|
+
"@vosjs/timeline": "^0.4.1"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"@vosjs/core": ">=0.10.0 <0.24.0"
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"tsup": "^8.5.0",
|
|
41
41
|
"typescript": "^5",
|
|
42
42
|
"vitest": "^3.0.0",
|
|
43
|
-
"@vosjs/core": "^0.23.
|
|
43
|
+
"@vosjs/core": "^0.23.2"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|