@vosjs/studio-core 0.45.1 → 0.46.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 CHANGED
@@ -35,7 +35,7 @@ The shared layers lower as one engine `stack` entry, `STUDIO_ENTRY_ID` (`'vosso.
35
35
 
36
36
  ## Time and space conventions
37
37
 
38
- - **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. An overlay may instead name a recorder step as its time (`anchor: { step, media?, at?, offset? }`): the lowering starts it where that step plays in the cut (`resolveOverlayAnchors`, `resolveAnchor`, `sourceMomentToOutput`), its `start` the fallback, and fills a text layer's `{elapsed}` from the step's recorded off-camera wait (`formatElapsed`). `ratedSegments`, `effectiveSegments`, `docOutputDuration` and `outputRangeToSource` are the remaps.
38
+ - **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, click effects and the ranges in which the drawn cursor is off (`cursor.off: [{ in, out? }]`, an absent `out` running to the end of the film; `cursorOffAlpha` is the rule) are anchored in output time, so a title keeps its perceived length through a speed change. An overlay may instead name a recorder step as its time (`anchor: { step, media?, at?, offset? }`): the lowering starts it where that step plays in the cut (`resolveOverlayAnchors`, `resolveAnchor`, `sourceMomentToOutput`), its `start` the fallback, and fills a text layer's `{elapsed}` from the step's recorded off-camera wait (`formatElapsed`). `ratedSegments`, `effectiveSegments`, `docOutputDuration` and `outputRangeToSource` are the remaps.
39
39
  - **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`.
40
40
  - **Camera styles.** `ZOOM_STYLES` names six camera personalities (`glide`, the default, then `focus`, `cinema`, `snappy`, `cut`, `none`); a style parametrizes the planner, the camera motion and the tilt track's tempo, and `doc.zoomParams` layers per-document overrides. `keynote` and `drift` are retired names (`RETIRED_ZOOM_STYLES`) that resolve to `glide` + medium tilt and `cinema` + subtle tilt, and `migrateHostedDoc` rewrites them on read. Every style's chain gap sits above its pump-free floor (`pumpFreeChainGap`), and the lowering fits a ramp longer than its span to the room it has, never below `RAMP_FLOOR`.
41
41
  - **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); `cardVisibleExtent` and `cardOverscanFor` are how far a posed card is seen past the frame, which is what the card layer's canvas and plane grow by (so a lean over zoomed footage never shows the texture's edge); `computeCardLayout` and `docCardLayout` are the host-side mirror of the program's card math, pinned to it by tests.
@@ -51,20 +51,20 @@ The shared layers lower as one engine `stack` entry, `STUDIO_ENTRY_ID` (`'vosso.
51
51
 
52
52
  ## Exports by area
53
53
 
54
- | Area | Exports |
55
- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
56
- | Ingest | `projectFromArtifact`, `normalizeCaptureSpace`, `deriveViewportCrop`, `docToCropSpace`, `docToFullSpace`, `CAPTURE_COVERAGE_MIN`, `WINDOW_FOCUS_MIN` |
57
- | Document | `StudioDoc`, `ProjectDoc`, `ProgramAnchorDoc`, `anchorKindOf`, `isRecordingDoc`, `isProgramDoc`, `DOC_SCHEMA_VERSION`, `migrateHostedDoc`, `DEFAULT_FRAME_STYLE`, `BASE_FRAME_STYLE`, the constants (`ZOOM_LEVELS`, `TILT_DEG_MAX`, …) |
58
- | Planners | `planAutoZoom`, `planAutoSpeed`, `planAutoTilt`, `smoothCursor`, `idleGaps`, `scrollRuns`, `rejectSpan`, `isRejected`, `withoutRejected` |
59
- | Camera styles | `ZOOM_STYLES`, `ZOOM_STYLE_OPTIONS`, `DEFAULT_ZOOM_STYLE`, `resolveZoomStyle`, `RETIRED_ZOOM_STYLES`, `pumpFreeChainGap` |
60
- | Lowering | `lowerStudioDoc`, `lowerProgramDoc`, `lowerToComposition`, `zoomTrackFromDoc`, `tiltTrackFromDoc`, `camTrackFromDoc`, `motionTrack`, `followFocusEvents`, `extractClicks`, `cursorIdleFade`, `ratedSegments`, `resolveOverlayAnchors`, `STUDIO_ENTRY_ID`, `studioEntry`, `studioLayerData` |
61
- | Layout | `computeCardLayout`, `docCardLayout`, `focusBounds`, `clampFocus`, `camBubbleRectAt`, `overlayRect`, `overlayHit`, `CARD_FOV`, `CARD_Z`, `planeSizeAtDepth`, `recommendedExportResolution` |
62
- | Text | `TEXT_PRESETS`, `OVERLAY_FONT_FACES`, `resolveOverlayStyle`, `resolveOverlayBox`, `resolveText3dAsset` |
63
- | Audio | `studioAudioPlan`, `clipEnvelope`, `duckCurve`, `computePeaks`, `computeMicRms`, `voiceKey`, `musicBedClip`, `refillAudioBeds` |
64
- | Backdrops | `withBackdrop`, `backdropMedia` |
65
- | Digest | `momentsFromDoc`, `planForDigest`, `buildDigest`, `sceneChanges`, `zoomCoversRect`, `zoomWindow`, `cropBox`, `frameGeometry`, `STYLE_FIELDS`, `copyStyle`, `pickStyle`, `DIGEST_VERSION` |
66
- | Destinations | `DESTINATIONS`, `destinationById`, `destinationsForChannel`, `exportSizeFor`, `resolveExportSize`, `ASPECT_RATIOS` |
67
- | Timeline lanes | `videoLane`, `micLane`, `camLane`, `zoomLane`, `tiltLane`, `camMoveLane`, `speedLane`, `overlaysLane`, `objectsLane`, `audioLane`; range actions `outputRangeToSource`, `removeSourceRange`, `setSpeedInRange`, `zoomSpanForRange` |
54
+ | Area | Exports |
55
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
56
+ | Ingest | `projectFromArtifact`, `normalizeCaptureSpace`, `deriveViewportCrop`, `docToCropSpace`, `docToFullSpace`, `CAPTURE_COVERAGE_MIN`, `WINDOW_FOCUS_MIN` |
57
+ | Document | `StudioDoc`, `ProjectDoc`, `ProgramAnchorDoc`, `anchorKindOf`, `isRecordingDoc`, `isProgramDoc`, `DOC_SCHEMA_VERSION`, `migrateHostedDoc`, `DEFAULT_FRAME_STYLE`, `BASE_FRAME_STYLE`, the constants (`ZOOM_LEVELS`, `TILT_DEG_MAX`, …) |
58
+ | Planners | `planAutoZoom`, `planAutoSpeed`, `planAutoTilt`, `smoothCursor`, `idleGaps`, `scrollRuns`, `rejectSpan`, `isRejected`, `withoutRejected` |
59
+ | Camera styles | `ZOOM_STYLES`, `ZOOM_STYLE_OPTIONS`, `DEFAULT_ZOOM_STYLE`, `resolveZoomStyle`, `RETIRED_ZOOM_STYLES`, `pumpFreeChainGap` |
60
+ | Lowering | `lowerStudioDoc`, `lowerProgramDoc`, `lowerToComposition`, `zoomTrackFromDoc`, `tiltTrackFromDoc`, `camTrackFromDoc`, `motionTrack`, `followFocusEvents`, `extractClicks`, `cursorIdleFade`, `cursorOffAlpha`, `ratedSegments`, `resolveOverlayAnchors`, `STUDIO_ENTRY_ID`, `studioEntry`, `studioLayerData` |
61
+ | Layout | `computeCardLayout`, `docCardLayout`, `focusBounds`, `clampFocus`, `camBubbleRectAt`, `overlayRect`, `overlayHit`, `CARD_FOV`, `CARD_Z`, `planeSizeAtDepth`, `recommendedExportResolution` |
62
+ | Text | `TEXT_PRESETS`, `OVERLAY_FONT_FACES`, `resolveOverlayStyle`, `resolveOverlayBox`, `resolveText3dAsset` |
63
+ | Audio | `studioAudioPlan`, `clipEnvelope`, `duckCurve`, `computePeaks`, `computeMicRms`, `voiceKey`, `musicBedClip`, `refillAudioBeds` |
64
+ | Backdrops | `withBackdrop`, `backdropMedia` |
65
+ | Digest | `momentsFromDoc`, `planForDigest`, `buildDigest`, `sceneChanges`, `zoomCoversRect`, `zoomWindow`, `cropBox`, `frameGeometry`, `STYLE_FIELDS`, `copyStyle`, `pickStyle`, `DIGEST_VERSION` |
66
+ | Destinations | `DESTINATIONS`, `destinationById`, `destinationsForChannel`, `exportSizeFor`, `resolveExportSize`, `ASPECT_RATIOS` |
67
+ | Timeline lanes | `videoLane`, `micLane`, `camLane`, `zoomLane`, `tiltLane`, `camMoveLane`, `speedLane`, `overlaysLane`, `objectsLane`, `audioLane`; range actions `outputRangeToSource`, `removeSourceRange`, `setSpeedInRange`, `zoomSpanForRange` |
68
68
 
69
69
  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`.
70
70
 
package/dist/index.d.ts CHANGED
@@ -1021,6 +1021,28 @@ interface CursorStyle {
1021
1021
  style: 'default' | 'dot' | 'ring' | 'arrow';
1022
1022
  hideWhenIdle: boolean;
1023
1023
  clickFx: ClickFxStyle;
1024
+ /**
1025
+ * Time ranges in which the drawn cursor is off, in OUTPUT seconds (the
1026
+ * timeline the viewer sees, like overlays: a hide stays where it was put
1027
+ * through trims and speed changes). The track still drives cursor-follow
1028
+ * zoom and click effects, as with `visible: false`. The dot fades out over
1029
+ * a short beat before `in` and back in after `out`, so the range itself is
1030
+ * fully hidden. Overlapping ranges read as their union. Absent = the cursor
1031
+ * is never hidden by time.
1032
+ */
1033
+ off?: CursorOff[];
1034
+ }
1035
+ /**
1036
+ * One range in which the drawn cursor is hidden (`CursorStyle.off`), in
1037
+ * OUTPUT seconds. An absent `out` hides it to the end of the film. `from`
1038
+ * marks a range something else placed (`'endcard'`: the end card's), which
1039
+ * that thing replaces or removes on its next pass; a range without one is a
1040
+ * person's and is never touched by a re-plan.
1041
+ */
1042
+ interface CursorOff {
1043
+ in: number;
1044
+ out?: number;
1045
+ from?: string;
1024
1046
  }
1025
1047
  /**
1026
1048
  * Click-effect styling. Clicks are extracted
@@ -1868,6 +1890,12 @@ interface HtmlOverlayClip extends OverlayClipBase {
1868
1890
  * timeline's clock in the preview and in every export chunk alike. One
1869
1891
  * rasterize per frame while on screen. Absent = a still, byte-identical
1870
1892
  * to before the field existed.
1893
+ *
1894
+ * Move the LAYER with `motion` poses, never its text with CSS: the
1895
+ * browser places text on whole device pixels each time it rasterizes, so
1896
+ * text a keyframe drifts or scales slowly steps a pixel at a time beside
1897
+ * shapes that glide. A layer with a motion track is drawn from one raster
1898
+ * of each picture and moves by resampling it, which glides.
1871
1899
  */
1872
1900
  live?: boolean;
1873
1901
  /** Values for a live layer's `{{data.<name>}}` placeholders. */
@@ -3380,7 +3408,11 @@ declare function zoomCoversRect(span: {
3380
3408
 
3381
3409
  declare const STYLE_FIELDS: readonly ["zoomStyle", "zoomParams", "speedParams", "tiltStyle", "frame", "cursor", "cam", "export"];
3382
3410
  type StyleField = (typeof STYLE_FIELDS)[number];
3383
- /** The style fields present on a doc, deep-cloned. */
3411
+ /**
3412
+ * The style fields present on a doc, deep-cloned. The cursor's `off`
3413
+ * ranges are left out: they are moments of one cut (output seconds), never
3414
+ * a look another take can wear.
3415
+ */
3384
3416
  declare function pickStyle(doc: ProjectDoc): Partial<Pick<ProjectDoc, StyleField>>;
3385
3417
  interface CopyStyleOptions {
3386
3418
  /**
@@ -3491,9 +3523,11 @@ declare function clipsFrom(doc: Pick<ProjectDoc, 'overlays' | 'objects' | 'audio
3491
3523
  audio: AudioClip[];
3492
3524
  };
3493
3525
  /**
3494
- * The document without the clips a template placed. The card's `anim` is
3495
- * the card's own once set, so it stays; a caller that wants the card still
3496
- * clears it. Returns the same object when nothing came from `from`.
3526
+ * The document without the clips a template placed, its freezes, and the
3527
+ * cursor-off ranges stamped with the same `from`. The card's `anim` is the
3528
+ * card's own once set, so it stays; a caller that wants the card still
3529
+ * clears it. A range a person wrote (no `from`) is never touched. Returns
3530
+ * the same object when nothing came from `from`.
3497
3531
  */
3498
3532
  declare function dropTemplate(doc: ProjectDoc, from: string): ProjectDoc;
3499
3533
  /**
@@ -5550,6 +5584,29 @@ interface CursorFadeKey {
5550
5584
  */
5551
5585
  declare function cursorIdleFade(track: CursorTrack, o: CursorIdleOptions): CursorFadeKey[];
5552
5586
 
5587
+ /**
5588
+ * Time ranges in which the drawn cursor is off (`doc.cursor.off`), read at
5589
+ * OUTPUT time. One rule for every place the cursor is drawn: the primary
5590
+ * card (any media it plays), the dot carried across a transition, and a
5591
+ * layer card's own cursor. A pure function of `t`, so a frame stays a pure
5592
+ * function of time, and the ranges ride the document's data (a live edit).
5593
+ *
5594
+ * The fades sit OUTSIDE a range: the dot fades out over `CURSOR_OFF_FADE`
5595
+ * before `in` and back in over the same after `out`, so every moment inside
5596
+ * the range is fully hidden. A range at 0 is hidden from the first frame
5597
+ * (nothing before it to fade over), and one with no `out` never returns.
5598
+ */
5599
+
5600
+ /** Seconds the dot takes to leave before a range and return after it. */
5601
+ declare const CURSOR_OFF_FADE = 0.15;
5602
+ /**
5603
+ * The cursor's opacity factor at OUTPUT time `t`, 0..1: 1 away from every
5604
+ * range, 0 inside one, a linear ramp over the fade beside each edge. A range
5605
+ * whose `in` is not a finite number, or whose `out` is present and not past
5606
+ * its `in`, hides nothing (the lint names both).
5607
+ */
5608
+ declare function cursorOffAlpha(off: readonly CursorOff[] | null | undefined, t: number): number;
5609
+
5553
5610
  /** Anticipation lead — effects start this many output seconds before the click. */
5554
5611
  declare const CLICK_FX_PRE = 0.06;
5555
5612
  /** Base effect durations in output seconds (× the intensity's `dur`). */
@@ -5964,4 +6021,4 @@ declare function rejectSpan(rejected: RejectedSpan[] | undefined, lane: Rejected
5964
6021
  anchor?: StepAnchor;
5965
6022
  }, note?: string): RejectedSpan;
5966
6023
 
5967
- export { ASPECT_RATIOS, AUDIO_PLAN_STEP, type AnchorKind, type AnchorMiss, type AnchorResolution, type Anim, type AnimKind, type AnimSide, type AnimStep, type AppliedTemplate, type ApplyTemplateOptions, type AspectRatioOption, type AudioClip, type AudioLoudness, type AudioPlanPoint, type AudioPlanTrack, BACKGROUND_Z, BASE_FRAME_STYLE, type Backdrop, type BackgroundMedia, type BakeResult, type BakedText3dAsset, type BakedText3dMaterial, type BrowserBarStyle, type BuildDigestInput, CALLOUT_DEFAULT_BODY_PX, CALLOUT_SHAPES, CALLOUT_TYPE_RATIO, CAMERA_CENTRE_RAMP, CAMERA_COVER_MIN, CAMERA_FAR, CAMERA_NEAR, CAM_CHAIN_GAP, CAM_EASE, CAM_PAN, CAM_PAN_EASE, CAM_RAMP_IN, CAM_RAMP_OUT, CAM_SIZE_MAX, CAM_SIZE_MIN, CAM_SPAN_MIN, CAPTURE_COVERAGE_MIN, CARD_EDGE_OVERDRAW, CARD_ENTER_KINDS, CARD_EXIT_KINDS, CARD_FADE_SECONDS, CARD_FOV, CARD_Z, CHANGE_FLOOR, CHANGE_GRID, CHANGE_LEAD, CHANGE_OFFSETS, CHANNEL_SPECS_HASH, CHANNEL_SPECS_VERIFIED, CLICK_FX_INTENSITY, CLICK_FX_PRE, CLICK_HIGHLIGHT_FADE, CLICK_HOLD_MS, CLICK_PAIR_MAX, CLICK_PULSE_DUR, CLICK_RECT_MAX_FRAC, CLICK_RIPPLE_DUR, CLICK_SYNTH_RELEASE, CLUSTER_FILL, CROP_MAX_PX, CROP_MIN_FRAC, CROP_MIN_PX, CROP_PAD, CURSOR_IDLE_EPS_FRAC, CURSOR_IDLE_FADE_IN, CURSOR_IDLE_FADE_OUT, CURSOR_IDLE_HOLD, type CalloutBox, type CalloutClipOptions, type CalloutLook, type CalloutRegister, type CalloutShape, type CalloutWords, type CamBubbleRect, type CamPoseSpan, type CamStyle, type CameraModel, type CaptureNormalization, type CardLayout, type ChangeSample, type ChangeWitness, type ChangedRegion, type ClickFxStyle, type ClipGain, type ClipGainBasis, type CopiedLayout, type CopyLayoutOptions, type CopyStyleOptions, type CursorEvent, type CursorFadeKey, type CursorIdleOptions, type CursorStyle, type CursorTrack, DARK_GROUND, DEFAULT_BROWSER_BAR, DEFAULT_CAM_POSE, DEFAULT_CAM_STYLE, DEFAULT_CLICK_FX, DEFAULT_CURSOR_STYLE, DEFAULT_DUCK, DEFAULT_FRAME_STYLE, DEFAULT_SPEED_PARAMS, DEFAULT_TILT_POSE, DEFAULT_ZOOM_LEVEL, DEFAULT_ZOOM_STYLE, DESIGN_FRAME_WIDTH, DESTINATIONS, DIGEST_CROP_MAX, DIGEST_FULL_MAX, DIGEST_VERSION, DOC_FEATURES, DOC_SCHEMA_VERSION, DRAG_FIT_LEVEL, DRAG_MIN_S, DRAG_MIN_TRAVEL_FRAC, type Destination, type Digest, type DigestImageRef, type DigestPlan, type DigestTakeFacts, type DocFeature, type DocSegment, type Drag, type DuckOptions, ELAPSED_PLACEHOLDER, END_CARD_FROM, END_CARD_RECEDE, END_CARD_SECONDS, ENTRANCE_SECONDS, EXPORT_RESOLUTION_OPTIONS, EXPORT_SHORT_EDGE, type EndCard, type EnvelopePoint, type ExportResolution, type ExtractClickOptions, FOLLOW_RECENTER, FOLLOW_SAFE_RATIO, FOOTAGE_FRAME_STYLE, FRAME_BORDER_COLOR_DEFAULT, FRAME_BORDER_DEFAULT, FRAME_BORDER_WIDTH_DEFAULT, FREEZE_DEFAULT_SECONDS, FREEZE_SECONDS_MAX, FREEZE_SECONDS_MIN, type FocusBounds, type FollowEvent, type FollowOptions, type FrameEntrance, type FrameGeometry, type FrameStyle, type FreezeExtent, type FreezeSpan, HOLD_DRIFT_MAX, HOUSE_GRADIENT, HOUSE_REGISTER, HTML_LAYER_FOREIGN_FIELDS, HTML_LAYER_MAX_BYTES, HTML_LAYER_SVG_CODE, HTML_LAYER_WARN_BYTES, HTML_STARTERS, type HtmlLayerFace, type HtmlLayerInlineFace, type HtmlLayerPayload, type HtmlLayerProblem, type HtmlLayerProblemCode, type HtmlLayerSource, type HtmlOverlayClip, type HtmlOverlayFont, type HtmlStarter, IDLE_KINDS, type IdleKind, type IngestOptions, LAYER_CARD_SHADOW, LAYOUT_FRAME_FIELDS, LOOK_KINDS, type LayerCard, type LayoutParts, type Look, type LookBrand, type LookKind, type LookPlacement, type LowerProgramOptions, type LoweredAudioClip, type LoweredClick, type LoweredComposition, type LoweredZoomSpan, type LumaGrid, MEDIA_ENTER_KINDS, MEDIA_EXIT_KINDS, MEDIA_FRAME_KEYS, MEDIA_KEY_PREFIX, MINIMAL_BAR_THEMES, MOTION_DELTA, MOTION_EASE, type Media, type MediaFrame, type MediaFrameKey, type MediaOverlayClip, type MediaSegment, type MicRms, type MinimalBarTheme, type Moment, type MomentKind, type MomentsOptions, type MotionKey, type MotionPose, type MotionPose3D, type MusicBedInput, NORMALIZE_MAX_LIFT_DB, NORMALIZE_MAX_LUFS, NORMALIZE_MIN_LUFS, NORMALIZE_PEAK_CEILING_DB, type NormRect, OBJECT_DEFAULT_SCALE, OVERLAY_FONT_FACES, OVERLAY_LINE_HEIGHT, OVERLAY_MEDIA_DEFAULT_RADIUS, OVERLAY_MEDIA_DEFAULT_WIDTH, OVERLAY_MIN_DURATION, OVERLAY_SCALE_MAX, OVERLAY_SIZE_MAX, OVERLAY_SIZE_MIN, OVERLAY_TRANSITION_DUR, OVERLAY_Z, type ObjectAnimation, type ObjectAsset, type ObjectClip, type ObjectPrimitiveShape, type OutputExtent, type OverlayAnchor, type OverlayClip, type OverlayFontFace, type OverlayKind, type OverlayPin, type OverlayPresetStyle, type OverlayRect, type OverlayTransform, type OverlayTransition, PIN_GAP, PIN_MARGIN, PLATE_GROUND, PLAYBACK_ACTIVITY, PRIMARY_MEDIA, PROGRAM_RETIME, PUMP_REST, type PeerStepSpan, type PeerTrack, type PinCandidate, type PinCarry, type PinMark, type PinPlacement, type PinPlacementInput, type PinReferent, type PinSide, type PinSideResolved, type PlanOptions, type PlanTiltOptions, type PlaneSize, type ProgramAnchorDoc, type ProgramTweenEdit, type ProjectDoc, type PxRect, REJECT_OVERLAP, REPLAY_EPS, REST_TILT_ID, RETIRED_ZOOM_STYLES, type RecordingArtifact, type RecordingMeta, type RecordingNotice, type RecordingOutput, type RecordingPageMedia, type RecordingSkip, type Rect, type RejectedLane, type RejectedSpan, type ReplayedSpan, type ResolvedOverlayBox, type ResolvedOverlayStyle, type Rgb, SCENE_MOTION, SCENE_QUIET, SEGMENT_ENTER_KINDS, SEGMENT_EXIT_KINDS, SPEED_RATE_MAX, SPEED_RATE_MIN, SPEED_SPAN_MIN, STAGE_CLIP_PREFIX, STILL_DEFAULT, STUDIO_ENTRY_ID, STYLE_FIELDS, type SegmentExtent, type SmoothOptions, type SmoothPoint, type SpeedParams, type SpeedSpan, type StepAnchor, type StepSpan, type StudioAudioPlan, type StudioDoc, type StudioEntry, type StyleField, type StyledText, TEXT3D_DEPTH_DEFAULT, TEXT3D_DEPTH_MAX, TEXT3D_DEPTH_MIN, TEXT_ENTER_KINDS, TEXT_EXIT_KINDS, TEXT_PRESETS, TILT_AUTO_DEAD_ZONE, TILT_AUTO_MIN, TILT_CHAIN_GAP, TILT_DEG_MAX, TILT_EASE, TILT_INTENSITY_MAX, TILT_PAN, TILT_PAN_EASE, TILT_RAMP_IN, TILT_RAMP_OUT, TILT_SPAN_MIN, TILT_UI_DEG_MAX, TRANSITION_SECONDS, TRANSITION_SECONDS_MAX, TRANSITION_SECONDS_MIN, TRANSITION_SPEED_MULT, type TemplateAnchor, type Text3dMaterial, type TextFxDirection, type TextFxKind, type TextFxSpec, type TextFxUnit, type TextOverlayBox, type TextOverlayClip, type TextOverlayPreset, type TextOverlayStroke, type TiltPersonality, type TiltSpan, type TiltStyleName, type TraceFileKind, type TraceOptions, type TraceResult, type TranscriptSegment, type Transition, type TransitionKind, type TransitionMove, type TransitionOut, type TransitionSpeed, type UsedFeature, WINDOW_FOCUS_MIN, ZOOM_CHAIN_GAP, ZOOM_EASE, ZOOM_LEVELS, ZOOM_LEVEL_MAX, ZOOM_LEVEL_MIN, ZOOM_PAN, ZOOM_PAN_EASE, ZOOM_RAMP_IN, ZOOM_RAMP_IN_OVERLAP, ZOOM_RAMP_OUT, ZOOM_SPAN_MIN, ZOOM_STYLES, ZOOM_STYLE_OPTIONS, type ZipEntry, type ZoomScreen, type ZoomSpan, type ZoomStyleName, type ZoomStyleParams, type ZoomView, type ZoomWindow, ambientDrift, anchorKindOf, anchorSourceDuration, anchoredClip, animStep, applyLook, applyTemplate, aspectRatioValue, audioLane, backdropMedia, bakeDocFeatures, boldWeightFor, buildDigest, calloutBox, calloutClip, calloutGroundOf, calloutLook, calloutSource, camBubbleRect, camBubbleRectAt, camLane, camMoveLane, camRectFromPose, camRestPose, camTrackFromDoc, cameraCentring, cameraModel, cameraRestWindows, cameraRests, cameraSpanExtents, cardEnter, cardExit, cardFields, cardInset, cardPointToScreen, cardPoseTrack, changedRegion, clampCamFrac, clampCamSize, clampFocus, clampFreezeSeconds, clampSpeedRate, clampTiltDeg, clampZoomLevel, clipEnvelope, clipGain, clipLength, clipsFrom, compareVersions, computeCardLayout, computeMicRms, computePeaks, copyLayout, copyStyle, cropBox, cssFamilies, cssWeights, cursorFromCsv, cursorFromPlaywrightTrace, cursorFromRecords, cursorFromTrace, cursorIdleFade, deltaE, deriveViewportCrop, destinationById, destinationsForChannel, docCardLayout, docFeatures, docFreezes, docMediaList, docOutputDuration, docRestTime, docStillTime, docToCropSpace, docToFullSpace, docTransitions, docZoomTrack, dragsFromTrack, dropTemplate, duckCurve, effectiveSegments, elapsedFor, endCardClips, enterKey, enterOf, entranceAt, entranceEnd, entranceSeconds, envelopeAt, envelopeValueAt, exitKey, exitOf, exitSeconds, expandEndCard, expectedFrameSize, exportSizeFor, extractClicks, featuresNewerThan, findStep, focusBounds, focusForViewportCentre, followFocusEvents, formatElapsed, frameGeometry, freezeLane, freezeOutputExtents, hasElapsed, hasReplay, hexToRgb, hexToRgbTriplet, houseLook, htmlLayerBleed, htmlLayerBleedFor, htmlLayerFaces, htmlLayerKey, htmlLayerLabel, htmlLayerPayload, htmlLayerPictureBox, htmlLayerProblems, htmlLayerSvg, htmlLayerText, htmlLayerUnhostedFamilies, htmlLayerWidth, htmlStarterClip, idleGaps, idleKey, isKeyedOverlay, isLookKind, isLoweredRecording, isMusicBed, isPlayback, isProgramDoc, isRecordingDoc, isRejected, isStageClip, isUnitStep, lastLayerEnd, layerMedia, layerStart, layoutOf, levelForFocusFraction, liveZoomStyleName, longestOutputExtent, lookFromBrand, lookKindForGround, loudnessMatches, lowerProgramDoc, lowerStudioDoc, lowerToComposition, marksEmphasis, mediaAtOutput, mediaDuration, mediaFrame, mediaKey, mediaRef, mediaRefId, mediaSource, micLane, migrateHostedDoc, migrateMotion, migrateText, migrateTextClip, migrateZoomStyle, momentOutputs, momentsFromDoc, motionTrack, musicBedClip, nextMediaId, normalizeCaptureSpace, objectMotionBase, objectMotionPoseAt, objectsLane, outputDurationOf, outputEnd, outputRangeToSource, overlapFraction, overlayFaceFor, overlayFontFaces, overlayFontString, overlayFxSpec, overlayHit, overlayLines, overlayMotionBase, overlayMotionPoseAt, overlayPinPoseAt, overlayPlainText, overlayRect, overlaysLane, ownFreezes, pageDisplayUrl, parseCssColour, parsePoseId, pickChange, pickStyle, pinBox, pinCandidates, pinPlacement, pinRectOnScreen, pinReferent, pinReferentAt, placeFreezes, planAutoSpeed, planAutoTilt, planAutoZoom, planForDigest, planeSizeAtDepth, platformBarKind, playwrightTraceEntry, programDuration, programStillTime, projectFromArtifact, pumpFreeChainGap, ratedSegments, recommendedExportResolution, refillAudioBeds, rejectSpan, relativeLuminance, removeSourceRange, removeSpeedInRange, replayFlags, replayedSeconds, resolveAnchor, resolveExportSize, resolveOverlayAnchors, resolveOverlayBox, resolveOverlayStyle, resolvePins, resolveText3dAsset, resolveZoomStyle, restLeanOf, restSpansThroughTransitions, rgbToHex, sameMedia, sceneChanges, scrollRuns, segmentOutputExtents, outputLen as segmentOutputLen, segmentStarts, setSpeedInRange, slideSide, smoothCursor, snapRunWeight, sourceMomentToOutput, spanOutputExtent, spanOutputExtents, speedLane, stepElapsedMs, stepMomentToOutput, studioAudioPlan, studioEntry, studioLayerData, styledTextOf, textRunsOf, tiltLane, tiltTrackFromDoc, traceKindOf, transitionMult, transitionSeconds, unionFitLevel, unionRect, videoLane, voiceKey, wellFormedXml, withBackdrop, withFreezes, withHolds, withoutRejected, wrapProgramLength, zipEntries, zipEntryBytes, zoomCoversRect, zoomLane, zoomSpanForRange, zoomTrackFromDoc, zoomView, zoomViewport, zoomWindow };
6024
+ export { ASPECT_RATIOS, AUDIO_PLAN_STEP, type AnchorKind, type AnchorMiss, type AnchorResolution, type Anim, type AnimKind, type AnimSide, type AnimStep, type AppliedTemplate, type ApplyTemplateOptions, type AspectRatioOption, type AudioClip, type AudioLoudness, type AudioPlanPoint, type AudioPlanTrack, BACKGROUND_Z, BASE_FRAME_STYLE, type Backdrop, type BackgroundMedia, type BakeResult, type BakedText3dAsset, type BakedText3dMaterial, type BrowserBarStyle, type BuildDigestInput, CALLOUT_DEFAULT_BODY_PX, CALLOUT_SHAPES, CALLOUT_TYPE_RATIO, CAMERA_CENTRE_RAMP, CAMERA_COVER_MIN, CAMERA_FAR, CAMERA_NEAR, CAM_CHAIN_GAP, CAM_EASE, CAM_PAN, CAM_PAN_EASE, CAM_RAMP_IN, CAM_RAMP_OUT, CAM_SIZE_MAX, CAM_SIZE_MIN, CAM_SPAN_MIN, CAPTURE_COVERAGE_MIN, CARD_EDGE_OVERDRAW, CARD_ENTER_KINDS, CARD_EXIT_KINDS, CARD_FADE_SECONDS, CARD_FOV, CARD_Z, CHANGE_FLOOR, CHANGE_GRID, CHANGE_LEAD, CHANGE_OFFSETS, CHANNEL_SPECS_HASH, CHANNEL_SPECS_VERIFIED, CLICK_FX_INTENSITY, CLICK_FX_PRE, CLICK_HIGHLIGHT_FADE, CLICK_HOLD_MS, CLICK_PAIR_MAX, CLICK_PULSE_DUR, CLICK_RECT_MAX_FRAC, CLICK_RIPPLE_DUR, CLICK_SYNTH_RELEASE, CLUSTER_FILL, CROP_MAX_PX, CROP_MIN_FRAC, CROP_MIN_PX, CROP_PAD, CURSOR_IDLE_EPS_FRAC, CURSOR_IDLE_FADE_IN, CURSOR_IDLE_FADE_OUT, CURSOR_IDLE_HOLD, CURSOR_OFF_FADE, type CalloutBox, type CalloutClipOptions, type CalloutLook, type CalloutRegister, type CalloutShape, type CalloutWords, type CamBubbleRect, type CamPoseSpan, type CamStyle, type CameraModel, type CaptureNormalization, type CardLayout, type ChangeSample, type ChangeWitness, type ChangedRegion, type ClickFxStyle, type ClipGain, type ClipGainBasis, type CopiedLayout, type CopyLayoutOptions, type CopyStyleOptions, type CursorEvent, type CursorFadeKey, type CursorIdleOptions, type CursorOff, type CursorStyle, type CursorTrack, DARK_GROUND, DEFAULT_BROWSER_BAR, DEFAULT_CAM_POSE, DEFAULT_CAM_STYLE, DEFAULT_CLICK_FX, DEFAULT_CURSOR_STYLE, DEFAULT_DUCK, DEFAULT_FRAME_STYLE, DEFAULT_SPEED_PARAMS, DEFAULT_TILT_POSE, DEFAULT_ZOOM_LEVEL, DEFAULT_ZOOM_STYLE, DESIGN_FRAME_WIDTH, DESTINATIONS, DIGEST_CROP_MAX, DIGEST_FULL_MAX, DIGEST_VERSION, DOC_FEATURES, DOC_SCHEMA_VERSION, DRAG_FIT_LEVEL, DRAG_MIN_S, DRAG_MIN_TRAVEL_FRAC, type Destination, type Digest, type DigestImageRef, type DigestPlan, type DigestTakeFacts, type DocFeature, type DocSegment, type Drag, type DuckOptions, ELAPSED_PLACEHOLDER, END_CARD_FROM, END_CARD_RECEDE, END_CARD_SECONDS, ENTRANCE_SECONDS, EXPORT_RESOLUTION_OPTIONS, EXPORT_SHORT_EDGE, type EndCard, type EnvelopePoint, type ExportResolution, type ExtractClickOptions, FOLLOW_RECENTER, FOLLOW_SAFE_RATIO, FOOTAGE_FRAME_STYLE, FRAME_BORDER_COLOR_DEFAULT, FRAME_BORDER_DEFAULT, FRAME_BORDER_WIDTH_DEFAULT, FREEZE_DEFAULT_SECONDS, FREEZE_SECONDS_MAX, FREEZE_SECONDS_MIN, type FocusBounds, type FollowEvent, type FollowOptions, type FrameEntrance, type FrameGeometry, type FrameStyle, type FreezeExtent, type FreezeSpan, HOLD_DRIFT_MAX, HOUSE_GRADIENT, HOUSE_REGISTER, HTML_LAYER_FOREIGN_FIELDS, HTML_LAYER_MAX_BYTES, HTML_LAYER_SVG_CODE, HTML_LAYER_WARN_BYTES, HTML_STARTERS, type HtmlLayerFace, type HtmlLayerInlineFace, type HtmlLayerPayload, type HtmlLayerProblem, type HtmlLayerProblemCode, type HtmlLayerSource, type HtmlOverlayClip, type HtmlOverlayFont, type HtmlStarter, IDLE_KINDS, type IdleKind, type IngestOptions, LAYER_CARD_SHADOW, LAYOUT_FRAME_FIELDS, LOOK_KINDS, type LayerCard, type LayoutParts, type Look, type LookBrand, type LookKind, type LookPlacement, type LowerProgramOptions, type LoweredAudioClip, type LoweredClick, type LoweredComposition, type LoweredZoomSpan, type LumaGrid, MEDIA_ENTER_KINDS, MEDIA_EXIT_KINDS, MEDIA_FRAME_KEYS, MEDIA_KEY_PREFIX, MINIMAL_BAR_THEMES, MOTION_DELTA, MOTION_EASE, type Media, type MediaFrame, type MediaFrameKey, type MediaOverlayClip, type MediaSegment, type MicRms, type MinimalBarTheme, type Moment, type MomentKind, type MomentsOptions, type MotionKey, type MotionPose, type MotionPose3D, type MusicBedInput, NORMALIZE_MAX_LIFT_DB, NORMALIZE_MAX_LUFS, NORMALIZE_MIN_LUFS, NORMALIZE_PEAK_CEILING_DB, type NormRect, OBJECT_DEFAULT_SCALE, OVERLAY_FONT_FACES, OVERLAY_LINE_HEIGHT, OVERLAY_MEDIA_DEFAULT_RADIUS, OVERLAY_MEDIA_DEFAULT_WIDTH, OVERLAY_MIN_DURATION, OVERLAY_SCALE_MAX, OVERLAY_SIZE_MAX, OVERLAY_SIZE_MIN, OVERLAY_TRANSITION_DUR, OVERLAY_Z, type ObjectAnimation, type ObjectAsset, type ObjectClip, type ObjectPrimitiveShape, type OutputExtent, type OverlayAnchor, type OverlayClip, type OverlayFontFace, type OverlayKind, type OverlayPin, type OverlayPresetStyle, type OverlayRect, type OverlayTransform, type OverlayTransition, PIN_GAP, PIN_MARGIN, PLATE_GROUND, PLAYBACK_ACTIVITY, PRIMARY_MEDIA, PROGRAM_RETIME, PUMP_REST, type PeerStepSpan, type PeerTrack, type PinCandidate, type PinCarry, type PinMark, type PinPlacement, type PinPlacementInput, type PinReferent, type PinSide, type PinSideResolved, type PlanOptions, type PlanTiltOptions, type PlaneSize, type ProgramAnchorDoc, type ProgramTweenEdit, type ProjectDoc, type PxRect, REJECT_OVERLAP, REPLAY_EPS, REST_TILT_ID, RETIRED_ZOOM_STYLES, type RecordingArtifact, type RecordingMeta, type RecordingNotice, type RecordingOutput, type RecordingPageMedia, type RecordingSkip, type Rect, type RejectedLane, type RejectedSpan, type ReplayedSpan, type ResolvedOverlayBox, type ResolvedOverlayStyle, type Rgb, SCENE_MOTION, SCENE_QUIET, SEGMENT_ENTER_KINDS, SEGMENT_EXIT_KINDS, SPEED_RATE_MAX, SPEED_RATE_MIN, SPEED_SPAN_MIN, STAGE_CLIP_PREFIX, STILL_DEFAULT, STUDIO_ENTRY_ID, STYLE_FIELDS, type SegmentExtent, type SmoothOptions, type SmoothPoint, type SpeedParams, type SpeedSpan, type StepAnchor, type StepSpan, type StudioAudioPlan, type StudioDoc, type StudioEntry, type StyleField, type StyledText, TEXT3D_DEPTH_DEFAULT, TEXT3D_DEPTH_MAX, TEXT3D_DEPTH_MIN, TEXT_ENTER_KINDS, TEXT_EXIT_KINDS, TEXT_PRESETS, TILT_AUTO_DEAD_ZONE, TILT_AUTO_MIN, TILT_CHAIN_GAP, TILT_DEG_MAX, TILT_EASE, TILT_INTENSITY_MAX, TILT_PAN, TILT_PAN_EASE, TILT_RAMP_IN, TILT_RAMP_OUT, TILT_SPAN_MIN, TILT_UI_DEG_MAX, TRANSITION_SECONDS, TRANSITION_SECONDS_MAX, TRANSITION_SECONDS_MIN, TRANSITION_SPEED_MULT, type TemplateAnchor, type Text3dMaterial, type TextFxDirection, type TextFxKind, type TextFxSpec, type TextFxUnit, type TextOverlayBox, type TextOverlayClip, type TextOverlayPreset, type TextOverlayStroke, type TiltPersonality, type TiltSpan, type TiltStyleName, type TraceFileKind, type TraceOptions, type TraceResult, type TranscriptSegment, type Transition, type TransitionKind, type TransitionMove, type TransitionOut, type TransitionSpeed, type UsedFeature, WINDOW_FOCUS_MIN, ZOOM_CHAIN_GAP, ZOOM_EASE, ZOOM_LEVELS, ZOOM_LEVEL_MAX, ZOOM_LEVEL_MIN, ZOOM_PAN, ZOOM_PAN_EASE, ZOOM_RAMP_IN, ZOOM_RAMP_IN_OVERLAP, ZOOM_RAMP_OUT, ZOOM_SPAN_MIN, ZOOM_STYLES, ZOOM_STYLE_OPTIONS, type ZipEntry, type ZoomScreen, type ZoomSpan, type ZoomStyleName, type ZoomStyleParams, type ZoomView, type ZoomWindow, ambientDrift, anchorKindOf, anchorSourceDuration, anchoredClip, animStep, applyLook, applyTemplate, aspectRatioValue, audioLane, backdropMedia, bakeDocFeatures, boldWeightFor, buildDigest, calloutBox, calloutClip, calloutGroundOf, calloutLook, calloutSource, camBubbleRect, camBubbleRectAt, camLane, camMoveLane, camRectFromPose, camRestPose, camTrackFromDoc, cameraCentring, cameraModel, cameraRestWindows, cameraRests, cameraSpanExtents, cardEnter, cardExit, cardFields, cardInset, cardPointToScreen, cardPoseTrack, changedRegion, clampCamFrac, clampCamSize, clampFocus, clampFreezeSeconds, clampSpeedRate, clampTiltDeg, clampZoomLevel, clipEnvelope, clipGain, clipLength, clipsFrom, compareVersions, computeCardLayout, computeMicRms, computePeaks, copyLayout, copyStyle, cropBox, cssFamilies, cssWeights, cursorFromCsv, cursorFromPlaywrightTrace, cursorFromRecords, cursorFromTrace, cursorIdleFade, cursorOffAlpha, deltaE, deriveViewportCrop, destinationById, destinationsForChannel, docCardLayout, docFeatures, docFreezes, docMediaList, docOutputDuration, docRestTime, docStillTime, docToCropSpace, docToFullSpace, docTransitions, docZoomTrack, dragsFromTrack, dropTemplate, duckCurve, effectiveSegments, elapsedFor, endCardClips, enterKey, enterOf, entranceAt, entranceEnd, entranceSeconds, envelopeAt, envelopeValueAt, exitKey, exitOf, exitSeconds, expandEndCard, expectedFrameSize, exportSizeFor, extractClicks, featuresNewerThan, findStep, focusBounds, focusForViewportCentre, followFocusEvents, formatElapsed, frameGeometry, freezeLane, freezeOutputExtents, hasElapsed, hasReplay, hexToRgb, hexToRgbTriplet, houseLook, htmlLayerBleed, htmlLayerBleedFor, htmlLayerFaces, htmlLayerKey, htmlLayerLabel, htmlLayerPayload, htmlLayerPictureBox, htmlLayerProblems, htmlLayerSvg, htmlLayerText, htmlLayerUnhostedFamilies, htmlLayerWidth, htmlStarterClip, idleGaps, idleKey, isKeyedOverlay, isLookKind, isLoweredRecording, isMusicBed, isPlayback, isProgramDoc, isRecordingDoc, isRejected, isStageClip, isUnitStep, lastLayerEnd, layerMedia, layerStart, layoutOf, levelForFocusFraction, liveZoomStyleName, longestOutputExtent, lookFromBrand, lookKindForGround, loudnessMatches, lowerProgramDoc, lowerStudioDoc, lowerToComposition, marksEmphasis, mediaAtOutput, mediaDuration, mediaFrame, mediaKey, mediaRef, mediaRefId, mediaSource, micLane, migrateHostedDoc, migrateMotion, migrateText, migrateTextClip, migrateZoomStyle, momentOutputs, momentsFromDoc, motionTrack, musicBedClip, nextMediaId, normalizeCaptureSpace, objectMotionBase, objectMotionPoseAt, objectsLane, outputDurationOf, outputEnd, outputRangeToSource, overlapFraction, overlayFaceFor, overlayFontFaces, overlayFontString, overlayFxSpec, overlayHit, overlayLines, overlayMotionBase, overlayMotionPoseAt, overlayPinPoseAt, overlayPlainText, overlayRect, overlaysLane, ownFreezes, pageDisplayUrl, parseCssColour, parsePoseId, pickChange, pickStyle, pinBox, pinCandidates, pinPlacement, pinRectOnScreen, pinReferent, pinReferentAt, placeFreezes, planAutoSpeed, planAutoTilt, planAutoZoom, planForDigest, planeSizeAtDepth, platformBarKind, playwrightTraceEntry, programDuration, programStillTime, projectFromArtifact, pumpFreeChainGap, ratedSegments, recommendedExportResolution, refillAudioBeds, rejectSpan, relativeLuminance, removeSourceRange, removeSpeedInRange, replayFlags, replayedSeconds, resolveAnchor, resolveExportSize, resolveOverlayAnchors, resolveOverlayBox, resolveOverlayStyle, resolvePins, resolveText3dAsset, resolveZoomStyle, restLeanOf, restSpansThroughTransitions, rgbToHex, sameMedia, sceneChanges, scrollRuns, segmentOutputExtents, outputLen as segmentOutputLen, segmentStarts, setSpeedInRange, slideSide, smoothCursor, snapRunWeight, sourceMomentToOutput, spanOutputExtent, spanOutputExtents, speedLane, stepElapsedMs, stepMomentToOutput, studioAudioPlan, studioEntry, studioLayerData, styledTextOf, textRunsOf, tiltLane, tiltTrackFromDoc, traceKindOf, transitionMult, transitionSeconds, unionFitLevel, unionRect, videoLane, voiceKey, wellFormedXml, withBackdrop, withFreezes, withHolds, withoutRejected, wrapProgramLength, zipEntries, zipEntryBytes, zoomCoversRect, zoomLane, zoomSpanForRange, zoomTrackFromDoc, zoomView, zoomViewport, zoomWindow };
package/dist/index.js CHANGED
@@ -1515,6 +1515,8 @@ var DESIGN_FRAME_WIDTH = 1920;
1515
1515
  var HTML_LAYER_WARN_BYTES = 32e3;
1516
1516
  var HTML_LAYER_MAX_BYTES = 128e3;
1517
1517
  var HTML_LAYER_LIVE_HZ = 60;
1518
+ var HTML_LAYER_RASTER_SCALE = 2;
1519
+ var HTML_LAYER_RASTER_MAX_AREA = 4096 * 4096;
1518
1520
  var HTML_LAYER_ASSET_HOST = "https://assets.vos.so/";
1519
1521
  function splitTopLevel(value) {
1520
1522
  const out = [];
@@ -5298,6 +5300,35 @@ function push(keys, t, a) {
5298
5300
  keys.push({ t: rt, a });
5299
5301
  }
5300
5302
 
5303
+ // src/lower/cursorOff.ts
5304
+ var CURSOR_OFF_FADE = 0.15;
5305
+ function cursorOffAlpha(off, t) {
5306
+ let a = 1;
5307
+ if (!Array.isArray(off)) return a;
5308
+ for (const r of off) {
5309
+ if (!r || typeof r.in !== "number" || !Number.isFinite(r.in)) continue;
5310
+ if (r.out !== void 0 && !(typeof r.out === "number" && r.out > r.in))
5311
+ continue;
5312
+ const out = r.out === void 0 ? Infinity : r.out;
5313
+ const k = t < r.in ? (r.in - t) / CURSOR_OFF_FADE : t > out ? (t - out) / CURSOR_OFF_FADE : 0;
5314
+ if (k < a) a = k;
5315
+ }
5316
+ return a < 0 ? 0 : a > 1 ? 1 : a;
5317
+ }
5318
+ var CURSOR_OFF_CODE = `function cxoAlpha(cxoL, cxoT) {
5319
+ var cxoA = 1
5320
+ if (!cxoL || !cxoL.length) return cxoA
5321
+ for (var cxoI = 0; cxoI < cxoL.length; cxoI++) {
5322
+ var cxoR = cxoL[cxoI]
5323
+ if (!cxoR || typeof cxoR.in !== 'number' || !isFinite(cxoR.in)) continue
5324
+ if (cxoR.out !== undefined && !(typeof cxoR.out === 'number' && cxoR.out > cxoR.in)) continue
5325
+ var cxoO = cxoR.out === undefined ? Infinity : cxoR.out
5326
+ var cxoK = cxoT < cxoR.in ? (cxoR.in - cxoT) / ${CURSOR_OFF_FADE} : cxoT > cxoO ? (cxoT - cxoO) / ${CURSOR_OFF_FADE} : 0
5327
+ if (cxoK < cxoA) cxoA = cxoK
5328
+ }
5329
+ return cxoA < 0 ? 0 : cxoA > 1 ? 1 : cxoA
5330
+ }`;
5331
+
5301
5332
  // src/lower/studioEntry.ts
5302
5333
  import { timelineRuntimeCode } from "@vosjs/timeline/bundle";
5303
5334
 
@@ -5705,6 +5736,8 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
5705
5736
  var TL = globalThis.__vosTimeline
5706
5737
  var t = ctx.time || 0
5707
5738
  var s = H / 1080 // scale design-px controls to comp px
5739
+ // The take's cursor-off ranges (a layer card's cursor reads them at t).
5740
+ ${CURSOR_OFF_CODE}
5708
5741
  var ns = window.__vos__ || {}
5709
5742
  var playing = ns.isPaused === false
5710
5743
  // The styled-text layout (the engine's text/layout.ts, generated), installed once:
@@ -5834,6 +5867,35 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
5834
5867
  else { cc.beginPath(); cc.rect(x, y, w, h) }
5835
5868
  }
5836
5869
 
5870
+ // A moving html layer's raster: its picture drawn ONCE at the largest size
5871
+ // its track reaches (so a pose only ever scales it down), into one canvas
5872
+ // per clip, redrawn only when a new picture lands or the frame's size
5873
+ // changes. A still layer in motion rasterizes once; a live one once per
5874
+ // picture, as before.
5875
+ function hlRaster(ol, el, nw, nh) {
5876
+ if (typeof document === 'undefined') return el
5877
+ var hlPk = ol.scale
5878
+ var hlKs = ol.track.keyframes
5879
+ for (var hlKi = 0; hlKi < hlKs.length; hlKi++) if (hlKs[hlKi].value[2] > hlPk) hlPk = hlKs[hlKi].value[2]
5880
+ var hlBW = ol.w * W * hlPk
5881
+ var hlBH = hlBW * nh / nw
5882
+ var hlSS = Math.min(${HTML_LAYER_RASTER_SCALE}, Math.sqrt(${HTML_LAYER_RASTER_MAX_AREA} / Math.max(1, hlBW * hlBH)))
5883
+ var hlRW = Math.max(1, Math.floor(hlBW * hlSS))
5884
+ var hlRH = Math.max(1, Math.floor(hlBH * hlSS))
5885
+ var hlRs = ns.htmlRaster || (ns.htmlRaster = {})
5886
+ var hlR = hlRs[ol.id]
5887
+ if (!hlR) hlR = hlRs[ol.id] = { c: document.createElement('canvas'), el: null }
5888
+ if (hlR.el !== el || hlR.c.width !== hlRW || hlR.c.height !== hlRH) {
5889
+ if (hlR.c.width !== hlRW) hlR.c.width = hlRW
5890
+ if (hlR.c.height !== hlRH) hlR.c.height = hlRH
5891
+ var hlX = hlR.c.getContext('2d')
5892
+ hlX.clearRect(0, 0, hlRW, hlRH)
5893
+ try { hlX.drawImage(el, 0, 0, hlRW, hlRH) } catch (e) { return el }
5894
+ hlR.el = el
5895
+ }
5896
+ return hlR.c
5897
+ }
5898
+
5837
5899
  // Text overlays: visibility signature + "a transition is animating".
5838
5900
  // During a hold the drawn pixels are static, so the signature alone drives
5839
5901
  // redraws (position/text/style edits change it \u2014 live SET_DATA); during
@@ -5894,6 +5956,7 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
5894
5956
  if (ns.htmlKeys) delete ns.htmlKeys[hlK]
5895
5957
  if (ns.htmlWant) delete ns.htmlWant[hlK]
5896
5958
  if (ns.htmlErrors) delete ns.htmlErrors[hlK]
5959
+ if (ns.htmlRaster) delete ns.htmlRaster[hlK]
5897
5960
  }
5898
5961
  }
5899
5962
  // A styled layer's cached layout leaves with its clip.
@@ -6110,7 +6173,15 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
6110
6173
  }
6111
6174
  ovC.save()
6112
6175
  rr(-olDW / 2, -olDH / 2, olDW, olDH, olRad, ovC); ovC.clip()
6113
- try { ovC.drawImage(olEl, -olDW / 2, -olDH / 2, olDW, olDH) } catch (e) {}
6176
+ // A MOVING html layer is drawn from a raster of its picture, never from
6177
+ // the picture itself: the browser rasterizes an SVG image afresh at
6178
+ // every draw transform and places text on whole device pixels as it
6179
+ // does, so text under a slow move or scale held still and then jumped
6180
+ // a pixel while the shapes beside it glided. A fixed raster moves by
6181
+ // resampling, every frame.
6182
+ var olSrc = ol.html && ol.track ? hlRaster(ol, olEl, olNW, olNH) : olEl
6183
+ if (olSrc !== olEl) ovC.imageSmoothingQuality = 'high'
6184
+ try { ovC.drawImage(olSrc, -olDW / 2, -olDH / 2, olDW, olDH) } catch (e) {}
6114
6185
  ovC.restore()
6115
6186
  if (ol.border && ol.border.width > 0) {
6116
6187
  ovC.strokeStyle = ol.border.color || '#ffffff'
@@ -6735,10 +6806,14 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
6735
6806
  }
6736
6807
  var lcPts = lcCu.pts, lcPX = lcPts[0].x, lcPY = lcPts[0].y
6737
6808
  for (var lcp = 0; lcp < lcPts.length; lcp++) { if (lcPts[lcp].t <= lcT) { lcPX = lcPts[lcp].x; lcPY = lcPts[lcp].y } }
6738
- lcX.save()
6739
- lcX.fillStyle = 'rgba(255,255,255,0.95)'; lcX.strokeStyle = 'rgba(0,0,0,0.4)'; lcX.lineWidth = 2 * lcS
6740
- lcX.beginPath(); lcX.arc(lcX0 + (lcPX / (lcSp.w || lcNW)) * lcW, lcMY + (lcPY / (lcSp.h || lcNH)) * lcMH, lcSize, 0, Math.PI * 2); lcX.fill(); lcX.stroke()
6741
- lcX.restore()
6809
+ // the take's cursor-off ranges, at OUTPUT time like the primary's
6810
+ var lcOffA = cxoAlpha(lcCu.off, t)
6811
+ if (lcOffA > 0.01) {
6812
+ lcX.save()
6813
+ lcX.fillStyle = 'rgba(255,255,255,' + (0.95 * lcOffA) + ')'; lcX.strokeStyle = 'rgba(0,0,0,' + (0.4 * lcOffA) + ')'; lcX.lineWidth = 2 * lcS
6814
+ lcX.beginPath(); lcX.arc(lcX0 + (lcPX / (lcSp.w || lcNW)) * lcW, lcMY + (lcPY / (lcSp.h || lcNH)) * lcMH, lcSize, 0, Math.PI * 2); lcX.fill(); lcX.stroke()
6815
+ lcX.restore()
6816
+ }
6742
6817
  }
6743
6818
  lcX.restore()
6744
6819
  if (lcO.border && lcO.border.width > 0) {
@@ -8381,6 +8456,11 @@ var ON_FRAME = `(ctx, content, dt) => {
8381
8456
  }
8382
8457
  cc.restore()
8383
8458
  }
8459
+ // The ranges the cursor is off (cursorStyle.off), read at OUTPUT time:
8460
+ // one factor for every place the dot is drawn below (the card, any media
8461
+ // it plays, the dot across a boundary). 1 when nothing is off.
8462
+ ${CURSOR_OFF_CODE}
8463
+ var cxoF = cxoAlpha(d.cursorStyle && d.cursorStyle.off, t)
8384
8464
 
8385
8465
  // The card paints in PASSES: the ghost first (the outgoing clip's last
8386
8466
  // frame on its own canvas, while a boundary is crossing), then the live
@@ -8872,7 +8952,8 @@ var ON_FRAME = `(ctx, content, dt) => {
8872
8952
  // cursor (SOURCE-anchored samples, read at the on-screen source moment).
8873
8953
  // The dot is the only thing cursorStyle.visible hides \u2014 the track still drives
8874
8954
  // cursor-follow zoom, and click effects draw above on their own switch.
8875
- // Undefined reads as visible so pre-toggle docs are unchanged.
8955
+ // Undefined reads as visible so pre-toggle docs are unchanged. The ranges
8956
+ // in cursorStyle.off hide the dot the same way, by time (cxoF).
8876
8957
  var cur = (actM ? actM.cursor : d.cursor) || []
8877
8958
  if (cur.length && !(d.cursorStyle && d.cursorStyle.visible === false)) {
8878
8959
  var px = cur[0].x, py = cur[0].y
@@ -8907,8 +8988,8 @@ var ON_FRAME = `(ctx, content, dt) => {
8907
8988
  }
8908
8989
  if (tpG) trQa = [tqX, tqY]
8909
8990
  else { trQb = [tqX, tqY]; trQs = curSize * ckPress; trQw = s2 }
8910
- } else if (cuA > 0.01) {
8911
- drawCur(c, ax, ay, curSize * ckPress, cuA, 2 * s2)
8991
+ } else if (cuA * cxoF > 0.01) {
8992
+ drawCur(c, ax, ay, curSize * ckPress, cuA * cxoF, 2 * s2)
8912
8993
  }
8913
8994
  }
8914
8995
  if (fitCover) c.restore()
@@ -9070,7 +9151,7 @@ var ON_FRAME = `(ctx, content, dt) => {
9070
9151
  tqX2 = tqOut ? tqAx : tqBx; tqY2 = tqOut ? tqAy : tqBy
9071
9152
  }
9072
9153
  var tqR = trQs || (((d.cursorStyle && d.cursorStyle.size) || 24) * s * 0.5)
9073
- if (tqOn) drawCur(ovC, tqX2, tqY2, tqR, 1, 2 * (trQw || s))
9154
+ if (tqOn && cxoF > 0.01) drawCur(ovC, tqX2, tqY2, tqR, cxoF, 2 * (trQw || s))
9074
9155
  }
9075
9156
  ov.sig = ovSig
9076
9157
  ov.active = camActiveNow || !!trOut || pqLive
@@ -9321,7 +9402,10 @@ function studioLayerData(input, duration, pins) {
9321
9402
  })),
9322
9403
  space: { w: lm.meta.width, h: lm.meta.height },
9323
9404
  size: rec.cursor.size,
9324
- clicks
9405
+ clicks,
9406
+ // The take's cursor-off ranges (OUTPUT time),
9407
+ // only when there are any.
9408
+ ...rec.cursor.off?.length ? { off: rec.cursor.off } : {}
9325
9409
  }
9326
9410
  };
9327
9411
  })() : {};
@@ -10306,6 +10390,7 @@ function pickStyle(doc) {
10306
10390
  const v = doc[k];
10307
10391
  if (v !== void 0) out[k] = structuredClone(v);
10308
10392
  }
10393
+ if (out.cursor) delete out.cursor.off;
10309
10394
  return out;
10310
10395
  }
10311
10396
  function copyStyle(from, to, opts = {}) {
@@ -10324,6 +10409,9 @@ function copyStyle(from, to, opts = {}) {
10324
10409
  }
10325
10410
  next.export = merged;
10326
10411
  }
10412
+ const ownOff = to.cursor?.off;
10413
+ if (ownOff && next.cursor)
10414
+ next.cursor = { ...next.cursor, off: structuredClone(ownOff) };
10327
10415
  const styled = next;
10328
10416
  return opts.layout ? copyLayout(from, styled, { keys: opts.keys }).doc : styled;
10329
10417
  }
@@ -10467,13 +10555,19 @@ function clipsFrom(doc, from) {
10467
10555
  function dropTemplate(doc, from) {
10468
10556
  const has = clipsFrom(doc, from);
10469
10557
  const freezes = (doc.freeze ?? []).some((f) => f.from === from);
10470
- if (!has.overlays.length && !has.objects.length && !has.audio.length && !freezes)
10558
+ const cursorOff = (doc.cursor?.off ?? []).some((r) => r?.from === from);
10559
+ if (!has.overlays.length && !has.objects.length && !has.audio.length && !freezes && !cursorOff)
10471
10560
  return doc;
10472
10561
  const out = { ...doc };
10473
10562
  if (doc.overlays) out.overlays = doc.overlays.filter((o) => o.from !== from);
10474
10563
  if (doc.objects) out.objects = doc.objects.filter((o) => o.from !== from);
10475
10564
  out.audio = doc.audio.filter((a) => a.from !== from);
10476
10565
  if (doc.freeze) out.freeze = doc.freeze.filter((f) => f.from !== from);
10566
+ if (cursorOff) {
10567
+ const off = (doc.cursor.off ?? []).filter((r) => r?.from !== from);
10568
+ const { off: _off, ...cursor } = doc.cursor;
10569
+ out.cursor = off.length ? { ...cursor, off } : cursor;
10570
+ }
10477
10571
  return out;
10478
10572
  }
10479
10573
  function applyTemplate(template, take, opts) {
@@ -12617,6 +12711,14 @@ var DOC_FEATURES = [
12617
12711
  name: "clips whose camera rests",
12618
12712
  before: "would play the zooms, tilts and cam moves over those clips as if the camera were not resting",
12619
12713
  uses: (doc) => isRecordingDoc(doc) ? doc.segments.filter((s) => s && s.camera === "rest").length : 0
12714
+ },
12715
+ {
12716
+ id: "cursor-off",
12717
+ since: "0.46.0",
12718
+ name: "cursor-off ranges",
12719
+ before: "would draw the cursor through them",
12720
+ // Nothing older can hide the cursor by time, so there is no bake.
12721
+ uses: (doc) => isRecordingDoc(doc) && doc.cursor && Array.isArray(doc.cursor.off) ? doc.cursor.off.length : 0
12620
12722
  }
12621
12723
  ];
12622
12724
  function compareVersions(a, b) {
@@ -12765,6 +12867,7 @@ export {
12765
12867
  CURSOR_IDLE_FADE_IN,
12766
12868
  CURSOR_IDLE_FADE_OUT,
12767
12869
  CURSOR_IDLE_HOLD,
12870
+ CURSOR_OFF_FADE,
12768
12871
  DARK_GROUND,
12769
12872
  DECORATION_THICKNESS_EM,
12770
12873
  DEFAULT_BROWSER_BAR,
@@ -12967,6 +13070,7 @@ export {
12967
13070
  cursorFromRecords,
12968
13071
  cursorFromTrace,
12969
13072
  cursorIdleFade,
13073
+ cursorOffAlpha,
12970
13074
  decorationRect,
12971
13075
  deltaE,
12972
13076
  deriveViewportCrop,