@vosjs/studio-core 0.33.2 → 0.34.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/dist/index.d.ts CHANGED
@@ -139,6 +139,14 @@ interface ZoomStyleParams {
139
139
  ease: string;
140
140
  /** connected-pan + follow-recenter ease. */
141
141
  panEase: string;
142
+ /**
143
+ * A slow push through a held zoom: the level grows by this fraction per
144
+ * second of hold (a dolly, not a cut), so a long caption beat is a camera
145
+ * that is still moving rather than a still. Capped at HOLD_DRIFT_MAX of
146
+ * the landed level; a span that follows the cursor already moves and
147
+ * never drifts. Absent or 0 = the camera parks, byte-identically.
148
+ */
149
+ holdDrift?: number;
142
150
  /** recenter when the cursor exits this central fraction of the crop. */
143
151
  followSafeRatio: number;
144
152
  /** seconds the camera takes to glide to a recentered focus. */
@@ -152,6 +160,8 @@ interface ZoomStyleParams {
152
160
  /** The style's tilt personality — see TiltPersonality. */
153
161
  tilt: TiltPersonality;
154
162
  }
163
+ /** The most a hold's drift adds to the landed level, as a fraction of it. */
164
+ declare const HOLD_DRIFT_MAX = 0.15;
155
165
  /**
156
166
  * The shortest rest between a zoom-out and the next zoom-in that reads as
157
167
  * a rest rather than a pump (seconds).
@@ -1218,6 +1228,13 @@ interface AnimStep {
1218
1228
  * page turns forward).
1219
1229
  */
1220
1230
  side?: AnimSide;
1231
+ /**
1232
+ * The CARD's enter only: OUTPUT seconds the card waits before it enters.
1233
+ * The ground plays alone until then (a film that opens on its title), and
1234
+ * the card arrives from nothing rather than from its softened first pose.
1235
+ * Absent = 0: the card is on screen from the first frame.
1236
+ */
1237
+ at?: number;
1221
1238
  }
1222
1239
  interface Anim {
1223
1240
  enter?: AnimKind | AnimStep;
@@ -4301,12 +4318,21 @@ declare const END_CARD_FROM = "endcard";
4301
4318
  type Step = {
4302
4319
  kind: string;
4303
4320
  seconds?: number;
4321
+ at?: number;
4304
4322
  } | null | undefined;
4305
4323
  /** The card's enter step, from its `anim` (a migrated doc carries nothing else). */
4306
4324
  declare function cardEnter(frame: Pick<FrameStyle, 'anim'>): AnimStep | null;
4307
4325
  /** The card's exit step, from its `anim`. */
4308
4326
  declare function cardExit(frame: Pick<FrameStyle, 'anim'>): AnimStep | null;
4309
4327
  declare function entranceSeconds(e: Step): number;
4328
+ /**
4329
+ * When the card's entrance BEGINS, output seconds: its `at`, clamped to
4330
+ * 0..30. The ground plays alone until then. 0 for a card with no entrance,
4331
+ * whose `at` would have nothing to delay.
4332
+ */
4333
+ declare function entranceAt(e: Step): number;
4334
+ /** When the card has finished entering, output seconds: `at` plus its length. */
4335
+ declare function entranceEnd(e: Step): number;
4310
4336
  /** The exit's length: its own seconds, else the house length of its kind. */
4311
4337
  declare function exitSeconds(e: Step): number;
4312
4338
  /** A freeze's place on the output timeline (its start and its seconds). */
@@ -5098,4 +5124,4 @@ declare function rejectSpan(rejected: RejectedSpan[] | undefined, lane: Rejected
5098
5124
  anchor?: StepAnchor;
5099
5125
  }, note?: string): RejectedSpan;
5100
5126
 
5101
- export { ASPECT_RATIOS, AUDIO_PLAN_STEP, type AnchorKind, type Anim, type AnimKind, type AnimSide, type AnimStep, type AppliedTemplate, type ApplyTemplateOptions, type AspectRatioOption, type AudioClip, type AudioPlanPoint, type AudioPlanTrack, BACKGROUND_Z, BASE_FRAME_STYLE, type Backdrop, type BackgroundMedia, 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, 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 ClickFxStyle, 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_SCHEMA_VERSION, DRAG_FIT_LEVEL, DRAG_MIN_S, DRAG_MIN_TRAVEL_FRAC, type Destination, type Digest, type DigestImageRef, type DigestPlan, type DigestTakeFacts, type DocSegment, type Drag, type DuckOptions, 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, 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, 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, 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 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 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, REST_TILT_ID, RETIRED_ZOOM_STYLES, type RecordingArtifact, type RecordingMeta, type Rect, type RejectedLane, type RejectedSpan, 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, 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, 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 ZoomSpan, type ZoomStyleName, type ZoomStyleParams, type ZoomView, type ZoomWindow, anchorKindOf, anchorSourceDuration, animStep, applyLook, applyTemplate, aspectRatioValue, audioLane, backdropMedia, buildDigest, calloutBox, calloutClip, calloutGroundOf, calloutLook, calloutSource, camBubbleRect, camBubbleRectAt, camLane, camMoveLane, camRectFromPose, camRestPose, camTrackFromDoc, cameraCentring, cameraModel, cardEnter, cardExit, cardFields, cardInset, cardPointToScreen, cardPoseTrack, clampCamFrac, clampCamSize, clampFocus, clampFreezeSeconds, clampSpeedRate, clampTiltDeg, clampZoomLevel, clipEnvelope, clipLength, clipsFrom, computeCardLayout, computeMicRms, computePeaks, copyLayout, copyStyle, cropBox, cssFamilies, cssWeights, cursorFromCsv, cursorFromPlaywrightTrace, cursorFromRecords, cursorFromTrace, cursorIdleFade, deltaE, deriveViewportCrop, destinationById, destinationsForChannel, docCardLayout, docFreezes, docMediaList, docOutputDuration, docRestTime, docStillTime, docToCropSpace, docToFullSpace, docTransitions, docZoomTrack, dragsFromTrack, dropTemplate, duckCurve, effectiveSegments, endCardClips, enterKey, enterOf, entranceSeconds, envelopeAt, envelopeValueAt, exitKey, exitOf, exitSeconds, expandEndCard, expectedFrameSize, exportSizeFor, extractClicks, findStep, focusBounds, focusForViewportCentre, followFocusEvents, frameGeometry, freezeLane, freezeOutputExtents, hexToRgb, hexToRgbTriplet, houseLook, htmlLayerBleed, htmlLayerBleedFor, htmlLayerFaces, htmlLayerKey, htmlLayerLabel, htmlLayerPayload, htmlLayerPictureBox, htmlLayerProblems, htmlLayerSvg, htmlLayerText, htmlLayerUnhostedFamilies, htmlLayerWidth, htmlStarterClip, idleGaps, idleKey, isKeyedOverlay, isLookKind, isMusicBed, isPlayback, isProgramDoc, isRecordingDoc, isRejected, isStageClip, isUnitStep, lastLayerEnd, layerMedia, layoutOf, levelForFocusFraction, liveZoomStyleName, lookFromBrand, lookKindForGround, lowerProgramDoc, lowerStudioDoc, lowerToComposition, mediaAtOutput, mediaDuration, mediaFrame, mediaKey, mediaRef, mediaRefId, mediaSource, micLane, migrateHostedDoc, migrateMotion, migrateZoomStyle, momentsFromDoc, motionTrack, musicBedClip, nextMediaId, normalizeCaptureSpace, objectMotionBase, objectMotionPoseAt, objectsLane, outputDurationOf, outputEnd, outputRangeToSource, overlapFraction, overlayFaceFor, overlayFontFaces, overlayFontString, overlayFxSpec, overlayHit, overlayLines, overlayMotionBase, overlayMotionPoseAt, overlayPinPoseAt, overlayRect, overlaysLane, ownFreezes, pageDisplayUrl, parseCssColour, parsePoseId, 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, resolveExportSize, resolveOverlayBox, resolveOverlayStyle, resolvePins, resolveText3dAsset, resolveZoomStyle, restLeanOf, restSpansThroughTransitions, rgbToHex, sameMedia, sceneChanges, scrollRuns, segmentOutputExtents, outputLen as segmentOutputLen, segmentStarts, setSpeedInRange, slideSide, smoothCursor, spanOutputExtent, speedLane, studioAudioPlan, studioEntry, studioLayerData, tiltLane, tiltTrackFromDoc, traceKindOf, transitionMult, transitionSeconds, unionFitLevel, unionRect, videoLane, voiceKey, wellFormedXml, withBackdrop, withFreezes, withHolds, withoutRejected, wrapProgramLength, zipEntries, zipEntryBytes, zoomCoversRect, zoomLane, zoomSpanForRange, zoomTrackFromDoc, zoomView, zoomViewport, zoomWindow };
5127
+ export { ASPECT_RATIOS, AUDIO_PLAN_STEP, type AnchorKind, type Anim, type AnimKind, type AnimSide, type AnimStep, type AppliedTemplate, type ApplyTemplateOptions, type AspectRatioOption, type AudioClip, type AudioPlanPoint, type AudioPlanTrack, BACKGROUND_Z, BASE_FRAME_STYLE, type Backdrop, type BackgroundMedia, 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, 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 ClickFxStyle, 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_SCHEMA_VERSION, DRAG_FIT_LEVEL, DRAG_MIN_S, DRAG_MIN_TRAVEL_FRAC, type Destination, type Digest, type DigestImageRef, type DigestPlan, type DigestTakeFacts, type DocSegment, type Drag, type DuckOptions, 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, 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, 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 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 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, REST_TILT_ID, RETIRED_ZOOM_STYLES, type RecordingArtifact, type RecordingMeta, type Rect, type RejectedLane, type RejectedSpan, 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, 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, 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 ZoomSpan, type ZoomStyleName, type ZoomStyleParams, type ZoomView, type ZoomWindow, anchorKindOf, anchorSourceDuration, animStep, applyLook, applyTemplate, aspectRatioValue, audioLane, backdropMedia, buildDigest, calloutBox, calloutClip, calloutGroundOf, calloutLook, calloutSource, camBubbleRect, camBubbleRectAt, camLane, camMoveLane, camRectFromPose, camRestPose, camTrackFromDoc, cameraCentring, cameraModel, cardEnter, cardExit, cardFields, cardInset, cardPointToScreen, cardPoseTrack, clampCamFrac, clampCamSize, clampFocus, clampFreezeSeconds, clampSpeedRate, clampTiltDeg, clampZoomLevel, clipEnvelope, clipLength, clipsFrom, computeCardLayout, computeMicRms, computePeaks, copyLayout, copyStyle, cropBox, cssFamilies, cssWeights, cursorFromCsv, cursorFromPlaywrightTrace, cursorFromRecords, cursorFromTrace, cursorIdleFade, deltaE, deriveViewportCrop, destinationById, destinationsForChannel, docCardLayout, docFreezes, docMediaList, docOutputDuration, docRestTime, docStillTime, docToCropSpace, docToFullSpace, docTransitions, docZoomTrack, dragsFromTrack, dropTemplate, duckCurve, effectiveSegments, endCardClips, enterKey, enterOf, entranceAt, entranceEnd, entranceSeconds, envelopeAt, envelopeValueAt, exitKey, exitOf, exitSeconds, expandEndCard, expectedFrameSize, exportSizeFor, extractClicks, findStep, focusBounds, focusForViewportCentre, followFocusEvents, frameGeometry, freezeLane, freezeOutputExtents, hexToRgb, hexToRgbTriplet, houseLook, htmlLayerBleed, htmlLayerBleedFor, htmlLayerFaces, htmlLayerKey, htmlLayerLabel, htmlLayerPayload, htmlLayerPictureBox, htmlLayerProblems, htmlLayerSvg, htmlLayerText, htmlLayerUnhostedFamilies, htmlLayerWidth, htmlStarterClip, idleGaps, idleKey, isKeyedOverlay, isLookKind, isMusicBed, isPlayback, isProgramDoc, isRecordingDoc, isRejected, isStageClip, isUnitStep, lastLayerEnd, layerMedia, layoutOf, levelForFocusFraction, liveZoomStyleName, lookFromBrand, lookKindForGround, lowerProgramDoc, lowerStudioDoc, lowerToComposition, mediaAtOutput, mediaDuration, mediaFrame, mediaKey, mediaRef, mediaRefId, mediaSource, micLane, migrateHostedDoc, migrateMotion, migrateZoomStyle, momentsFromDoc, motionTrack, musicBedClip, nextMediaId, normalizeCaptureSpace, objectMotionBase, objectMotionPoseAt, objectsLane, outputDurationOf, outputEnd, outputRangeToSource, overlapFraction, overlayFaceFor, overlayFontFaces, overlayFontString, overlayFxSpec, overlayHit, overlayLines, overlayMotionBase, overlayMotionPoseAt, overlayPinPoseAt, overlayRect, overlaysLane, ownFreezes, pageDisplayUrl, parseCssColour, parsePoseId, 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, resolveExportSize, resolveOverlayBox, resolveOverlayStyle, resolvePins, resolveText3dAsset, resolveZoomStyle, restLeanOf, restSpansThroughTransitions, rgbToHex, sameMedia, sceneChanges, scrollRuns, segmentOutputExtents, outputLen as segmentOutputLen, segmentStarts, setSpeedInRange, slideSide, smoothCursor, spanOutputExtent, speedLane, studioAudioPlan, studioEntry, studioLayerData, 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
@@ -1420,7 +1420,7 @@ function docStillTime(doc) {
1420
1420
  }
1421
1421
  }
1422
1422
  if (!(footage > 0)) return r3(clampOut(STILL_DEFAULT));
1423
- let hero = entranceSeconds(cardEnter(doc.frame));
1423
+ let hero = entranceEnd(cardEnter(doc.frame));
1424
1424
  for (const clip of doc.overlays ?? []) {
1425
1425
  if (clip.start > OPENING_WINDOW) continue;
1426
1426
  const step = enterOf(clip.anim);
@@ -1488,6 +1488,14 @@ function entranceSeconds(e) {
1488
1488
  if (!e || e.kind === "none") return 0;
1489
1489
  return Math.max(0.2, Math.min(3, e.seconds ?? ENTRANCE_SECONDS));
1490
1490
  }
1491
+ function entranceAt(e) {
1492
+ if (!entranceSeconds(e)) return 0;
1493
+ const at = e?.at;
1494
+ return typeof at === "number" && at > 0 ? Math.min(30, at) : 0;
1495
+ }
1496
+ function entranceEnd(e) {
1497
+ return entranceAt(e) + entranceSeconds(e);
1498
+ }
1491
1499
  function exitSeconds(e) {
1492
1500
  if (!e || e.kind === "none") return 0;
1493
1501
  const house = e.kind === "fade" ? CARD_FADE_SECONDS : END_CARD_RECEDE;
@@ -1551,22 +1559,26 @@ function withHolds(docSegments, rated) {
1551
1559
  function entranceTiltKeyframes(e) {
1552
1560
  const s = entranceSeconds(e);
1553
1561
  if (!s || e?.kind !== "tilt-in") return [];
1562
+ const a = entranceAt(e);
1554
1563
  return [
1555
1564
  { t: 0, value: [...TILT_IN_POSE], ease: "none" },
1556
- { t: s, value: [0, 0], ease: "power3.out" }
1565
+ ...a ? [{ t: a, value: [...TILT_IN_POSE], ease: "none" }] : [],
1566
+ { t: a + s, value: [0, 0], ease: "power3.out" }
1557
1567
  ];
1558
1568
  }
1559
1569
  function entranceZoomKeyframes(e) {
1560
1570
  const s = entranceSeconds(e);
1561
1571
  if (!s) return [];
1572
+ const a = entranceAt(e);
1562
1573
  if (e?.kind === "pull-out")
1563
1574
  return [
1564
1575
  { t: 0, value: [PULL_OUT_LEVEL, 0.5, 0.42], ease: "none" },
1565
- { t: s, value: [1, 0.5, 0.5], ease: "power3.out" }
1576
+ ...a ? [{ t: a, value: [PULL_OUT_LEVEL, 0.5, 0.42], ease: "none" }] : [],
1577
+ { t: a + s, value: [1, 0.5, 0.5], ease: "power3.out" }
1566
1578
  ];
1567
1579
  return [
1568
1580
  { t: 0, value: [1, 0.5, 0.5], ease: "none" },
1569
- { t: s, value: [1, 0.5, 0.5], ease: "none" }
1581
+ { t: a + s, value: [1, 0.5, 0.5], ease: "none" }
1570
1582
  ];
1571
1583
  }
1572
1584
  function prependEntrance(track, head) {
@@ -1582,15 +1594,18 @@ var RECEDE_MID = [0.91, -0.018, 0.8];
1582
1594
  function cardPoseTrack(enter, exit, footageEnd, outputEnd2 = footageEnd) {
1583
1595
  const keyframes = [];
1584
1596
  const s = entranceSeconds(enter);
1597
+ const a = entranceAt(enter);
1585
1598
  if (s) {
1586
1599
  const from = enter?.kind === "rise" ? [0.96, 0.08, 0.7] : enter?.kind === "pull-out" || enter?.kind === "fade" || enter?.kind === "slide" ? enter.kind === "fade" ? [1, 0, 0] : [1, 0, 1] : [0.94, 0.05, 0.7];
1600
+ if (a) from[2] = 0;
1587
1601
  keyframes.push({ t: 0, value: from, ease: "none" });
1588
- keyframes.push({ t: s, value: [1, 0, 1], ease: "power3.out" });
1602
+ if (a) keyframes.push({ t: a, value: [...from], ease: "none" });
1603
+ keyframes.push({ t: a + s, value: [1, 0, 1], ease: "power3.out" });
1589
1604
  }
1590
1605
  const x = exitSeconds(exit);
1591
1606
  let last = [1, 0, 1];
1592
1607
  if (x > 0 && footageEnd > 0) {
1593
- const t0 = round3(Math.max(s, footageEnd - x));
1608
+ const t0 = round3(Math.max(a + s, footageEnd - x));
1594
1609
  const t1 = round3(Math.max(t0 + 0.05, footageEnd));
1595
1610
  last = exitPose(exit);
1596
1611
  keyframes.push({ t: t0, value: [1, 0, 1], ease: "none" });
@@ -1812,6 +1827,7 @@ function liveZoomStyleName(name) {
1812
1827
  if (name in ZOOM_STYLES) return name;
1813
1828
  return RETIRED_ZOOM_STYLES[name]?.style ?? null;
1814
1829
  }
1830
+ var HOLD_DRIFT_MAX = 0.15;
1815
1831
  var PUMP_REST = 1;
1816
1832
  function pumpFreeChainGap(p) {
1817
1833
  return p.rampOut + (p.rampIn - p.rampInOverlap) + PUMP_REST;
@@ -3590,7 +3606,7 @@ function docTransitions(doc) {
3590
3606
  if (open?.kind === "slide" && extents.length) {
3591
3607
  const first = extents[0];
3592
3608
  const m = move(open, "enter", Math.max(0, first.end - first.start) / 2);
3593
- if (m) out.push({ t: 0, d: m.d, in: m });
3609
+ if (m) out.push({ t: round32(entranceAt(open)), d: m.d, in: m });
3594
3610
  }
3595
3611
  for (let i = 0; i + 1 < segments.length; i++) {
3596
3612
  const a = segments[i];
@@ -5868,7 +5884,15 @@ function zoomTrackFromDoc(zoom, segments, style = ZOOM_STYLES[DEFAULT_ZOOM_STYLE
5868
5884
  }
5869
5885
  cur = next2;
5870
5886
  }
5871
- push2(tOut, cur, "none");
5887
+ const drift = Math.max(0, style.holdDrift ?? 0);
5888
+ const landed = keyframes.at(-1)?.t;
5889
+ if (drift > 0 && z.focusMode !== "auto" && !(z.followEvents ?? []).length && landed !== void 0 && tOut > landed) {
5890
+ const grow = Math.min(HOLD_DRIFT_MAX, drift * (tOut - landed));
5891
+ cur = [clampZoomLevel(cur[0] * (1 + grow)), cur[1], cur[2], cur[3]];
5892
+ push2(tOut, cur, "linear");
5893
+ } else {
5894
+ push2(tOut, cur, "none");
5895
+ }
5872
5896
  const next = mapped.at(i + 1);
5873
5897
  if (next && next.tIn - tOut <= style.chainGap) {
5874
5898
  const mNext = transitionMult(next.z.transition);
@@ -6930,37 +6954,71 @@ var ON_FRAME = `(ctx, content, dt) => {
6930
6954
  bgC.fillStyle = '#0b0b0c'
6931
6955
  bgC.fillStyle = (function () {
6932
6956
  var bgcss = frame.background || '#0b0b0c'
6933
- if (typeof bgcss === 'string' && bgcss.indexOf('linear-gradient') === 0) {
6934
- var inner = bgcss.substring(bgcss.indexOf('(') + 1, bgcss.lastIndexOf(')'))
6935
- var parts = inner.split(',').map(function (x) { return x.trim() })
6936
- var ang = 135, cols = []
6937
- for (var i = 0; i < parts.length; i++) {
6938
- if (parts[i].indexOf('deg') >= 0) ang = parseFloat(parts[i])
6939
- else cols.push(parts[i])
6957
+ if (typeof bgcss !== 'string') return '#0b0b0c'
6958
+ var gKind = bgcss.indexOf('linear-gradient') === 0 ? 'linear' : bgcss.indexOf('radial-gradient') === 0 ? 'radial' : ''
6959
+ if (!gKind) return bgcss
6960
+ // Split on TOP-LEVEL commas only: an rgba() or hsl() stop has commas of
6961
+ // its own, and splitting inside one hands canvas half a colour.
6962
+ var gin = bgcss.substring(bgcss.indexOf('(') + 1, bgcss.lastIndexOf(')'))
6963
+ var gps = [], gDepth = 0, gCur = ''
6964
+ for (var gi = 0; gi < gin.length; gi++) {
6965
+ var gch = gin.charAt(gi)
6966
+ if (gch === '(') gDepth++
6967
+ else if (gch === ')') gDepth--
6968
+ if (gch === ',' && gDepth === 0) { gps.push(gCur.trim()); gCur = '' } else gCur += gch
6969
+ }
6970
+ gps.push(gCur.trim())
6971
+ // The geometry (an angle, a side, a shape and centre) leads; every other
6972
+ // part is a STOP, a colour with an optional position ('#2b6f64 40%').
6973
+ var ang = 135, rcx = 0.5, rcy = 0.5, gStops = []
6974
+ for (var gj = 0; gj < gps.length; gj++) {
6975
+ var gp = gps[gj]
6976
+ if (!gp) continue
6977
+ if (gKind === 'linear' && gj === 0 && gp.indexOf('deg') >= 0) { ang = parseFloat(gp); continue }
6978
+ if (gKind === 'linear' && gj === 0 && gp.indexOf('to ') === 0) {
6979
+ var tdx = gp.indexOf('right') >= 0 ? 1 : gp.indexOf('left') >= 0 ? -1 : 0
6980
+ var tdy = gp.indexOf('bottom') >= 0 ? 1 : gp.indexOf('top') >= 0 ? -1 : 0
6981
+ ang = Math.atan2(tdx, -tdy) * 180 / Math.PI
6982
+ continue
6940
6983
  }
6941
- if (cols.length < 2) cols = [cols[0] || '#000', cols[0] || '#000']
6984
+ if (gKind === 'radial' && gj === 0 && (gp.indexOf('circle') === 0 || gp.indexOf('ellipse') === 0 || gp.indexOf('at ') === 0 || gp.indexOf('closest') === 0 || gp.indexOf('farthest') === 0)) {
6985
+ var rat = /at\\s+([\\d.]+)%\\s+([\\d.]+)%/.exec(gp)
6986
+ if (rat) { rcx = parseFloat(rat[1]) / 100; rcy = parseFloat(rat[2]) / 100 }
6987
+ continue
6988
+ }
6989
+ var gSp = gp.lastIndexOf(' ')
6990
+ var gTail = gSp > 0 ? gp.substring(gSp + 1) : ''
6991
+ if (gTail.charAt(gTail.length - 1) === '%' && !isNaN(parseFloat(gTail))) {
6992
+ gStops.push({ c: gp.substring(0, gSp).trim(), p: parseFloat(gTail) / 100 })
6993
+ } else gStops.push({ c: gp, p: null })
6994
+ }
6995
+ if (!gStops.length) return '#0b0b0c'
6996
+ if (gStops.length === 1) gStops.push({ c: gStops[0].c, p: null })
6997
+ // CSS's own fix-up: an unplaced first stop sits at 0 and last at 1, a
6998
+ // position never runs backwards, and the unplaced stops between two
6999
+ // placed ones spread evenly. Canvas throws outside 0..1, so clamp.
7000
+ var gN = gStops.length
7001
+ if (gStops[0].p === null) gStops[0].p = 0
7002
+ if (gStops[gN - 1].p === null) gStops[gN - 1].p = 1
7003
+ var gMax = 0
7004
+ for (var gk = 0; gk < gN; gk++) {
7005
+ if (gStops[gk].p !== null) { gStops[gk].p = Math.min(1, Math.max(gMax, gStops[gk].p)); gMax = gStops[gk].p }
7006
+ }
7007
+ for (var gm = 1; gm < gN; gm++) {
7008
+ if (gStops[gm].p !== null) continue
7009
+ var gEnd = gm
7010
+ while (gStops[gEnd].p === null) gEnd++
7011
+ var gFrom = gStops[gm - 1].p, gTo = gStops[gEnd].p, gRun = gEnd - gm + 1
7012
+ for (var gq = gm; gq < gEnd; gq++) gStops[gq].p = gFrom + (gTo - gFrom) * (gq - gm + 1) / gRun
7013
+ }
7014
+ var g
7015
+ if (gKind === 'linear') {
6942
7016
  var rad = (ang - 90) * Math.PI / 180
6943
7017
  var ux = Math.cos(rad), uy = Math.sin(rad)
6944
- var g = bgC.createLinearGradient(W / 2 - ux * W / 2, H / 2 - uy * H / 2, W / 2 + ux * W / 2, H / 2 + uy * H / 2)
6945
- g.addColorStop(0, cols[0]); g.addColorStop(1, cols[cols.length - 1])
6946
- return g
6947
- }
6948
- // Radial: 'radial-gradient([circle|ellipse] [at X% Y%,] A, B)'. Canvas
6949
- // cannot take the string, so it is built here like the linear one, with
6950
- // CSS's own default extent (farthest corner) so the second colour lands
6951
- // exactly where a browser would put it.
6952
- if (typeof bgcss === 'string' && bgcss.indexOf('radial-gradient') === 0) {
6953
- var rin = bgcss.substring(bgcss.indexOf('(') + 1, bgcss.lastIndexOf(')'))
6954
- var rps = rin.split(',').map(function (x) { return x.trim() })
6955
- var rcx = 0.5, rcy = 0.5, rcols = []
6956
- for (var ri = 0; ri < rps.length; ri++) {
6957
- var rp = rps[ri]
6958
- if (rp.indexOf('circle') === 0 || rp.indexOf('ellipse') === 0 || rp.indexOf('at ') === 0) {
6959
- var rat = /at\\s+([\\d.]+)%\\s+([\\d.]+)%/.exec(rp)
6960
- if (rat) { rcx = parseFloat(rat[1]) / 100; rcy = parseFloat(rat[2]) / 100 }
6961
- } else rcols.push(rp)
6962
- }
6963
- if (rcols.length < 2) rcols = [rcols[0] || '#000', rcols[0] || '#000']
7018
+ g = bgC.createLinearGradient(W / 2 - ux * W / 2, H / 2 - uy * H / 2, W / 2 + ux * W / 2, H / 2 + uy * H / 2)
7019
+ } else {
7020
+ // CSS's default extent (farthest corner), so the last stop lands
7021
+ // exactly where a browser would put it.
6964
7022
  var rpx = rcx * W, rpy = rcy * H
6965
7023
  var rr = Math.max(
6966
7024
  Math.sqrt(rpx * rpx + rpy * rpy),
@@ -6968,11 +7026,15 @@ var ON_FRAME = `(ctx, content, dt) => {
6968
7026
  Math.sqrt(rpx * rpx + (H - rpy) * (H - rpy)),
6969
7027
  Math.sqrt((W - rpx) * (W - rpx) + (H - rpy) * (H - rpy))
6970
7028
  )
6971
- var rg = bgC.createRadialGradient(rpx, rpy, 0, rpx, rpy, rr)
6972
- rg.addColorStop(0, rcols[0]); rg.addColorStop(1, rcols[rcols.length - 1])
6973
- return rg
7029
+ g = bgC.createRadialGradient(rpx, rpy, 0, rpx, rpy, rr)
6974
7030
  }
6975
- return bgcss
7031
+ // A stop canvas still cannot parse (a colour keyword it lacks, a second
7032
+ // position) lands on the known ground: a background must never take the
7033
+ // frame down with it.
7034
+ try {
7035
+ for (var gs = 0; gs < gN; gs++) g.addColorStop(gStops[gs].p, gStops[gs].c)
7036
+ } catch (e) { return '#0b0b0c' }
7037
+ return g
6976
7038
  })()
6977
7039
  bgC.fillRect(0, 0, W, H)
6978
7040
 
@@ -11530,6 +11592,7 @@ export {
11530
11592
  FREEZE_DEFAULT_SECONDS,
11531
11593
  FREEZE_SECONDS_MAX,
11532
11594
  FREEZE_SECONDS_MIN,
11595
+ HOLD_DRIFT_MAX,
11533
11596
  HOUSE_GRADIENT,
11534
11597
  HOUSE_REGISTER,
11535
11598
  HTML_LAYER_FOREIGN_FIELDS,
@@ -11689,6 +11752,8 @@ export {
11689
11752
  endCardClips,
11690
11753
  enterKey,
11691
11754
  enterOf,
11755
+ entranceAt,
11756
+ entranceEnd,
11692
11757
  entranceSeconds,
11693
11758
  envelopeAt,
11694
11759
  envelopeValueAt,