@vosjs/studio-core 0.45.2 → 0.47.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
@@ -4,6 +4,8 @@ import { Segment, KeyframeTrack } from '@vosjs/timeline';
4
4
  export { Segment } from '@vosjs/timeline';
5
5
  import { TimelineEdit } from '@vosjs/shared/timelineEdits';
6
6
  import { LaneAdapter } from '@vosjs/editor';
7
+ import { FilmSummary } from '@vosjs/shared/music';
8
+ export { FilmSummary } from '@vosjs/shared/music';
7
9
 
8
10
  /**
9
11
  * Zoom/pan camera styles — named strategy
@@ -1021,6 +1023,28 @@ interface CursorStyle {
1021
1023
  style: 'default' | 'dot' | 'ring' | 'arrow';
1022
1024
  hideWhenIdle: boolean;
1023
1025
  clickFx: ClickFxStyle;
1026
+ /**
1027
+ * Time ranges in which the drawn cursor is off, in OUTPUT seconds (the
1028
+ * timeline the viewer sees, like overlays: a hide stays where it was put
1029
+ * through trims and speed changes). The track still drives cursor-follow
1030
+ * zoom and click effects, as with `visible: false`. The dot fades out over
1031
+ * a short beat before `in` and back in after `out`, so the range itself is
1032
+ * fully hidden. Overlapping ranges read as their union. Absent = the cursor
1033
+ * is never hidden by time.
1034
+ */
1035
+ off?: CursorOff[];
1036
+ }
1037
+ /**
1038
+ * One range in which the drawn cursor is hidden (`CursorStyle.off`), in
1039
+ * OUTPUT seconds. An absent `out` hides it to the end of the film. `from`
1040
+ * marks a range something else placed (`'endcard'`: the end card's), which
1041
+ * that thing replaces or removes on its next pass; a range without one is a
1042
+ * person's and is never touched by a re-plan.
1043
+ */
1044
+ interface CursorOff {
1045
+ in: number;
1046
+ out?: number;
1047
+ from?: string;
1024
1048
  }
1025
1049
  /**
1026
1050
  * Click-effect styling. Clicks are extracted
@@ -3386,7 +3410,11 @@ declare function zoomCoversRect(span: {
3386
3410
 
3387
3411
  declare const STYLE_FIELDS: readonly ["zoomStyle", "zoomParams", "speedParams", "tiltStyle", "frame", "cursor", "cam", "export"];
3388
3412
  type StyleField = (typeof STYLE_FIELDS)[number];
3389
- /** The style fields present on a doc, deep-cloned. */
3413
+ /**
3414
+ * The style fields present on a doc, deep-cloned. The cursor's `off`
3415
+ * ranges are left out: they are moments of one cut (output seconds), never
3416
+ * a look another take can wear.
3417
+ */
3390
3418
  declare function pickStyle(doc: ProjectDoc): Partial<Pick<ProjectDoc, StyleField>>;
3391
3419
  interface CopyStyleOptions {
3392
3420
  /**
@@ -3497,9 +3525,11 @@ declare function clipsFrom(doc: Pick<ProjectDoc, 'overlays' | 'objects' | 'audio
3497
3525
  audio: AudioClip[];
3498
3526
  };
3499
3527
  /**
3500
- * The document without the clips a template placed. The card's `anim` is
3501
- * the card's own once set, so it stays; a caller that wants the card still
3502
- * clears it. Returns the same object when nothing came from `from`.
3528
+ * The document without the clips a template placed, its freezes, and the
3529
+ * cursor-off ranges stamped with the same `from`. The card's `anim` is the
3530
+ * card's own once set, so it stays; a caller that wants the card still
3531
+ * clears it. A range a person wrote (no `from`) is never touched. Returns
3532
+ * the same object when nothing came from `from`.
3503
3533
  */
3504
3534
  declare function dropTemplate(doc: ProjectDoc, from: string): ProjectDoc;
3505
3535
  /**
@@ -5556,6 +5586,29 @@ interface CursorFadeKey {
5556
5586
  */
5557
5587
  declare function cursorIdleFade(track: CursorTrack, o: CursorIdleOptions): CursorFadeKey[];
5558
5588
 
5589
+ /**
5590
+ * Time ranges in which the drawn cursor is off (`doc.cursor.off`), read at
5591
+ * OUTPUT time. One rule for every place the cursor is drawn: the primary
5592
+ * card (any media it plays), the dot carried across a transition, and a
5593
+ * layer card's own cursor. A pure function of `t`, so a frame stays a pure
5594
+ * function of time, and the ranges ride the document's data (a live edit).
5595
+ *
5596
+ * The fades sit OUTSIDE a range: the dot fades out over `CURSOR_OFF_FADE`
5597
+ * before `in` and back in over the same after `out`, so every moment inside
5598
+ * the range is fully hidden. A range at 0 is hidden from the first frame
5599
+ * (nothing before it to fade over), and one with no `out` never returns.
5600
+ */
5601
+
5602
+ /** Seconds the dot takes to leave before a range and return after it. */
5603
+ declare const CURSOR_OFF_FADE = 0.15;
5604
+ /**
5605
+ * The cursor's opacity factor at OUTPUT time `t`, 0..1: 1 away from every
5606
+ * range, 0 inside one, a linear ramp over the fade beside each edge. A range
5607
+ * whose `in` is not a finite number, or whose `out` is present and not past
5608
+ * its `in`, hides nothing (the lint names both).
5609
+ */
5610
+ declare function cursorOffAlpha(off: readonly CursorOff[] | null | undefined, t: number): number;
5611
+
5559
5612
  /** Anticipation lead — effects start this many output seconds before the click. */
5560
5613
  declare const CLICK_FX_PRE = 0.06;
5561
5614
  /** Base effect durations in output seconds (× the intensity's `dur`). */
@@ -5970,4 +6023,41 @@ declare function rejectSpan(rejected: RejectedSpan[] | undefined, lane: Rejected
5970
6023
  anchor?: StepAnchor;
5971
6024
  }, note?: string): RejectedSpan;
5972
6025
 
5973
- 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 };
6026
+ /**
6027
+ * A film as the music ranking reads it: its output length, the
6028
+ * instants a beat should land on, the moment the music should open up,
6029
+ * whether a voice plays. Built from the document here, where the document
6030
+ * is known, and handed to `@vosjs/shared/music`'s `rankBeds`, which never
6031
+ * reads one; the CLI's `vos music pick` and the studio's Sound panel read
6032
+ * the same summary, so one rule says what a cut is.
6033
+ *
6034
+ * A recording's cuts are its layers' starts (a caption landed on a step,
6035
+ * a callout), its segment boundaries (a join, a page change, a freeze) and
6036
+ * the page changes the recorder marked; its payoff is the last step the
6037
+ * script marks `"zoom": true`, else the last cut. A program's cuts are its
6038
+ * scene labels (`tl.addLabel`), its payoff the last scene. Pure.
6039
+ */
6040
+
6041
+ interface FilmSummaryOptions {
6042
+ /** Stable identity: the vos id, else the take directory's name. */
6043
+ seed: string;
6044
+ /** The payoff, output seconds, when the person said it (`--at`). */
6045
+ payoff?: number;
6046
+ /** Override what the document says about a voice. */
6047
+ voice?: boolean;
6048
+ mood?: string;
6049
+ words?: string;
6050
+ like?: string[];
6051
+ fadeIn?: boolean;
6052
+ }
6053
+ /** The scene labels a program declares, output seconds, in order. */
6054
+ declare function programSceneTimes(config: Record<string, unknown>): number[];
6055
+ /**
6056
+ * The film summary of a document. `seed` is the caller's (a vos id when
6057
+ * the take is on vos.so, else its directory's name).
6058
+ */
6059
+ declare function filmSummaryOf(doc: StudioDoc, opts: FilmSummaryOptions): FilmSummary;
6060
+ /** The library slugs a document's audio clips play, for a project's `like`. */
6061
+ declare function musicSlugsOfDoc(doc: Pick<StudioDoc, 'audio'>): string[];
6062
+
6063
+ 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 FilmSummaryOptions, 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, filmSummaryOf, 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, musicSlugsOfDoc, 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, programSceneTimes, 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
@@ -5300,6 +5300,35 @@ function push(keys, t, a) {
5300
5300
  keys.push({ t: rt, a });
5301
5301
  }
5302
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
+
5303
5332
  // src/lower/studioEntry.ts
5304
5333
  import { timelineRuntimeCode } from "@vosjs/timeline/bundle";
5305
5334
 
@@ -5707,6 +5736,8 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
5707
5736
  var TL = globalThis.__vosTimeline
5708
5737
  var t = ctx.time || 0
5709
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}
5710
5741
  var ns = window.__vos__ || {}
5711
5742
  var playing = ns.isPaused === false
5712
5743
  // The styled-text layout (the engine's text/layout.ts, generated), installed once:
@@ -6775,10 +6806,14 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
6775
6806
  }
6776
6807
  var lcPts = lcCu.pts, lcPX = lcPts[0].x, lcPY = lcPts[0].y
6777
6808
  for (var lcp = 0; lcp < lcPts.length; lcp++) { if (lcPts[lcp].t <= lcT) { lcPX = lcPts[lcp].x; lcPY = lcPts[lcp].y } }
6778
- lcX.save()
6779
- lcX.fillStyle = 'rgba(255,255,255,0.95)'; lcX.strokeStyle = 'rgba(0,0,0,0.4)'; lcX.lineWidth = 2 * lcS
6780
- 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()
6781
- 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
+ }
6782
6817
  }
6783
6818
  lcX.restore()
6784
6819
  if (lcO.border && lcO.border.width > 0) {
@@ -8421,6 +8456,11 @@ var ON_FRAME = `(ctx, content, dt) => {
8421
8456
  }
8422
8457
  cc.restore()
8423
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)
8424
8464
 
8425
8465
  // The card paints in PASSES: the ghost first (the outgoing clip's last
8426
8466
  // frame on its own canvas, while a boundary is crossing), then the live
@@ -8912,7 +8952,8 @@ var ON_FRAME = `(ctx, content, dt) => {
8912
8952
  // cursor (SOURCE-anchored samples, read at the on-screen source moment).
8913
8953
  // The dot is the only thing cursorStyle.visible hides \u2014 the track still drives
8914
8954
  // cursor-follow zoom, and click effects draw above on their own switch.
8915
- // 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).
8916
8957
  var cur = (actM ? actM.cursor : d.cursor) || []
8917
8958
  if (cur.length && !(d.cursorStyle && d.cursorStyle.visible === false)) {
8918
8959
  var px = cur[0].x, py = cur[0].y
@@ -8947,8 +8988,8 @@ var ON_FRAME = `(ctx, content, dt) => {
8947
8988
  }
8948
8989
  if (tpG) trQa = [tqX, tqY]
8949
8990
  else { trQb = [tqX, tqY]; trQs = curSize * ckPress; trQw = s2 }
8950
- } else if (cuA > 0.01) {
8951
- 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)
8952
8993
  }
8953
8994
  }
8954
8995
  if (fitCover) c.restore()
@@ -9110,7 +9151,7 @@ var ON_FRAME = `(ctx, content, dt) => {
9110
9151
  tqX2 = tqOut ? tqAx : tqBx; tqY2 = tqOut ? tqAy : tqBy
9111
9152
  }
9112
9153
  var tqR = trQs || (((d.cursorStyle && d.cursorStyle.size) || 24) * s * 0.5)
9113
- 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))
9114
9155
  }
9115
9156
  ov.sig = ovSig
9116
9157
  ov.active = camActiveNow || !!trOut || pqLive
@@ -9361,7 +9402,10 @@ function studioLayerData(input, duration, pins) {
9361
9402
  })),
9362
9403
  space: { w: lm.meta.width, h: lm.meta.height },
9363
9404
  size: rec.cursor.size,
9364
- 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 } : {}
9365
9409
  }
9366
9410
  };
9367
9411
  })() : {};
@@ -10346,6 +10390,7 @@ function pickStyle(doc) {
10346
10390
  const v = doc[k];
10347
10391
  if (v !== void 0) out[k] = structuredClone(v);
10348
10392
  }
10393
+ if (out.cursor) delete out.cursor.off;
10349
10394
  return out;
10350
10395
  }
10351
10396
  function copyStyle(from, to, opts = {}) {
@@ -10364,6 +10409,9 @@ function copyStyle(from, to, opts = {}) {
10364
10409
  }
10365
10410
  next.export = merged;
10366
10411
  }
10412
+ const ownOff = to.cursor?.off;
10413
+ if (ownOff && next.cursor)
10414
+ next.cursor = { ...next.cursor, off: structuredClone(ownOff) };
10367
10415
  const styled = next;
10368
10416
  return opts.layout ? copyLayout(from, styled, { keys: opts.keys }).doc : styled;
10369
10417
  }
@@ -10507,13 +10555,19 @@ function clipsFrom(doc, from) {
10507
10555
  function dropTemplate(doc, from) {
10508
10556
  const has = clipsFrom(doc, from);
10509
10557
  const freezes = (doc.freeze ?? []).some((f) => f.from === from);
10510
- 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)
10511
10560
  return doc;
10512
10561
  const out = { ...doc };
10513
10562
  if (doc.overlays) out.overlays = doc.overlays.filter((o) => o.from !== from);
10514
10563
  if (doc.objects) out.objects = doc.objects.filter((o) => o.from !== from);
10515
10564
  out.audio = doc.audio.filter((a) => a.from !== from);
10516
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
+ }
10517
10571
  return out;
10518
10572
  }
10519
10573
  function applyTemplate(template, take, opts) {
@@ -12657,6 +12711,14 @@ var DOC_FEATURES = [
12657
12711
  name: "clips whose camera rests",
12658
12712
  before: "would play the zooms, tilts and cam moves over those clips as if the camera were not resting",
12659
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
12660
12722
  }
12661
12723
  ];
12662
12724
  function compareVersions(a, b) {
@@ -12753,6 +12815,116 @@ function rejectSpan(rejected, lane, span, note) {
12753
12815
  if (note) entry.note = note;
12754
12816
  return entry;
12755
12817
  }
12818
+
12819
+ // src/filmSummary.ts
12820
+ var CUT_MERGE = 0.25;
12821
+ var r32 = (v) => Math.round(v * 1e3) / 1e3;
12822
+ var isMusicOrEffect = (key) => /\/music\/[^/?#]+\.mp3(?:[?#]|$)/.test(key) || /\/audio-sfx\//.test(key);
12823
+ function programSceneTimes(config) {
12824
+ const code = JSON.stringify(config);
12825
+ const times = /* @__PURE__ */ new Set();
12826
+ for (const m of code.matchAll(
12827
+ /addLabel\(\s*(?:\\"|['`])[^'`"\\]*(?:\\"|['`])\s*,\s*([\d.]+)/g
12828
+ )) {
12829
+ const t = Number(m[1]);
12830
+ if (Number.isFinite(t) && t > 0) times.add(r32(t));
12831
+ }
12832
+ return [...times].sort((a, b) => a - b);
12833
+ }
12834
+ function markedSteps(source) {
12835
+ const steps = source.script?.steps;
12836
+ if (!Array.isArray(steps)) return [];
12837
+ const out = [];
12838
+ steps.forEach((s, i) => {
12839
+ if (!s || typeof s !== "object") return;
12840
+ const step = s;
12841
+ if (step.zoom === true) out.push(typeof step.id === "string" ? step.id : i);
12842
+ });
12843
+ return out;
12844
+ }
12845
+ function tidy(cuts, duration) {
12846
+ const sorted = cuts.filter((t) => Number.isFinite(t) && t > CUT_MERGE && t < duration - 0.05).map(r32).sort((a, b) => a - b);
12847
+ const out = [];
12848
+ for (const t of sorted) {
12849
+ if (!out.length || t - out[out.length - 1] > CUT_MERGE) out.push(t);
12850
+ }
12851
+ return out;
12852
+ }
12853
+ function filmSummaryOf(doc, opts) {
12854
+ const duration = r32(docOutputDuration(doc));
12855
+ const cuts = [];
12856
+ let payoff = opts.payoff;
12857
+ let voice = opts.voice ?? false;
12858
+ if (isRecordingDoc(doc)) {
12859
+ const rated = ratedSegments(doc);
12860
+ let t = 0;
12861
+ for (const s of rated) {
12862
+ const rate = s.rate && s.rate > 0 ? s.rate : 1;
12863
+ t += (s.out - s.in) / rate;
12864
+ cuts.push(t);
12865
+ }
12866
+ for (const clip of doc.overlays ?? []) {
12867
+ const start = layerStart(clip, doc, rated);
12868
+ if (start !== null) cuts.push(start);
12869
+ }
12870
+ let lastMarked = null;
12871
+ for (const { id, source } of docMediaList(doc)) {
12872
+ for (const step of source.meta.steps ?? []) {
12873
+ if (step.navigated && typeof step.tEnd === "number") {
12874
+ const out = sourceMomentToOutput(rated, step.tEnd, id || void 0);
12875
+ if (out !== null) cuts.push(out);
12876
+ }
12877
+ }
12878
+ for (const step of markedSteps(source)) {
12879
+ const r = resolveAnchor(
12880
+ doc,
12881
+ { step, ...id ? { media: id } : {} },
12882
+ rated
12883
+ );
12884
+ if (r.start !== null) {
12885
+ cuts.push(r.start);
12886
+ if (lastMarked === null || r.start > lastMarked) lastMarked = r.start;
12887
+ }
12888
+ }
12889
+ }
12890
+ if (payoff === void 0 && lastMarked !== null) payoff = lastMarked;
12891
+ if (opts.voice === void 0) {
12892
+ voice = voiceKey(doc) !== null || (doc.audio ?? []).some((a) => !isMusicOrEffect(a.key));
12893
+ }
12894
+ } else {
12895
+ const scenes = programSceneTimes(doc.program.config);
12896
+ cuts.push(...scenes);
12897
+ if (payoff === void 0 && scenes.length)
12898
+ payoff = scenes[scenes.length - 1];
12899
+ if (opts.voice === void 0) {
12900
+ voice = (doc.audio ?? []).some((a) => !isMusicOrEffect(a.key));
12901
+ }
12902
+ }
12903
+ const tidied = tidy(cuts, duration);
12904
+ if (payoff === void 0 && tidied.length) payoff = tidied[tidied.length - 1];
12905
+ if (payoff !== void 0 && !(payoff > 0 && payoff < duration)) {
12906
+ payoff = void 0;
12907
+ }
12908
+ return {
12909
+ duration,
12910
+ ...payoff !== void 0 ? { payoff: r32(payoff) } : {},
12911
+ cuts: tidied,
12912
+ voice,
12913
+ ...opts.mood ? { mood: opts.mood } : {},
12914
+ ...opts.words ? { words: opts.words } : {},
12915
+ seed: opts.seed,
12916
+ ...opts.like?.length ? { like: opts.like } : {},
12917
+ ...opts.fadeIn ? { fadeIn: true } : {}
12918
+ };
12919
+ }
12920
+ function musicSlugsOfDoc(doc) {
12921
+ const out = /* @__PURE__ */ new Set();
12922
+ for (const a of doc.audio ?? []) {
12923
+ const m = /\/music\/([a-z0-9][a-z0-9-]*)\.mp3(?:[?#]|$)/.exec(a.key);
12924
+ if (m) out.add(m[1]);
12925
+ }
12926
+ return [...out].sort();
12927
+ }
12756
12928
  export {
12757
12929
  ASPECT_RATIOS,
12758
12930
  AUDIO_PLAN_STEP,
@@ -12805,6 +12977,7 @@ export {
12805
12977
  CURSOR_IDLE_FADE_IN,
12806
12978
  CURSOR_IDLE_FADE_OUT,
12807
12979
  CURSOR_IDLE_HOLD,
12980
+ CURSOR_OFF_FADE,
12808
12981
  DARK_GROUND,
12809
12982
  DECORATION_THICKNESS_EM,
12810
12983
  DEFAULT_BROWSER_BAR,
@@ -13007,6 +13180,7 @@ export {
13007
13180
  cursorFromRecords,
13008
13181
  cursorFromTrace,
13009
13182
  cursorIdleFade,
13183
+ cursorOffAlpha,
13010
13184
  decorationRect,
13011
13185
  deltaE,
13012
13186
  deriveViewportCrop,
@@ -13045,6 +13219,7 @@ export {
13045
13219
  exportSizeFor,
13046
13220
  extractClicks,
13047
13221
  featuresNewerThan,
13222
+ filmSummaryOf,
13048
13223
  findStep,
13049
13224
  focusBounds,
13050
13225
  focusForViewportCentre,
@@ -13117,6 +13292,7 @@ export {
13117
13292
  momentsFromDoc,
13118
13293
  motionTrack,
13119
13294
  musicBedClip,
13295
+ musicSlugsOfDoc,
13120
13296
  nextMediaId,
13121
13297
  normalizeCaptureSpace,
13122
13298
  normalizeRuns,
@@ -13162,6 +13338,7 @@ export {
13162
13338
  platformBarKind,
13163
13339
  playwrightTraceEntry,
13164
13340
  programDuration,
13341
+ programSceneTimes,
13165
13342
  programStillTime,
13166
13343
  projectFromArtifact,
13167
13344
  pumpFreeChainGap,