@vosjs/studio-core 0.41.2 → 0.42.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 +155 -2
- package/dist/index.js +207 -15
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -210,6 +210,12 @@ interface SpeedParams {
|
|
|
210
210
|
scrollMin: number;
|
|
211
211
|
/** Rate applied to scroll runs. */
|
|
212
212
|
scrollRate: number;
|
|
213
|
+
/**
|
|
214
|
+
* Rate applied to a scripted `wait` or a hover's dwell in which nothing
|
|
215
|
+
* moved on screen: the flow's own pauses, read from the step timeline
|
|
216
|
+
* with the digest's activity as the witness.
|
|
217
|
+
*/
|
|
218
|
+
stillRate: number;
|
|
213
219
|
}
|
|
214
220
|
/** Conservative defaults: only stretches nobody wants to watch in real time. */
|
|
215
221
|
declare const DEFAULT_SPEED_PARAMS: SpeedParams;
|
|
@@ -227,6 +233,12 @@ declare function planAutoSpeed(track: readonly CursorEvent[], opts: {
|
|
|
227
233
|
params?: Partial<SpeedParams>;
|
|
228
234
|
/** Per-SOURCE-second motion bins (0..1) when a digest measured them. */
|
|
229
235
|
activity?: readonly number[] | null;
|
|
236
|
+
/**
|
|
237
|
+
* The step timeline of a scripted take (`meta.steps`): the flow's own
|
|
238
|
+
* pauses become still spans when the activity witness says nothing
|
|
239
|
+
* moved in them.
|
|
240
|
+
*/
|
|
241
|
+
steps?: readonly StepSpan[] | null;
|
|
230
242
|
}): SpeedSpan[];
|
|
231
243
|
/**
|
|
232
244
|
* Scroll runs as [start, last] seconds — the same grouping the speed planner
|
|
@@ -560,6 +572,14 @@ interface StepSpan {
|
|
|
560
572
|
* (a pin then reads the presses inside the step's window).
|
|
561
573
|
*/
|
|
562
574
|
rect?: Rect;
|
|
575
|
+
/** The page the step left, origin and path only (never a query or a hash). */
|
|
576
|
+
url?: string;
|
|
577
|
+
/**
|
|
578
|
+
* The words of the element the step's `read` named, once the step had
|
|
579
|
+
* settled: trimmed, whitespace collapsed, at most 2 KB. The take's own
|
|
580
|
+
* payload, which a layer quotes instead of replaying the flow.
|
|
581
|
+
*/
|
|
582
|
+
text?: string;
|
|
563
583
|
}
|
|
564
584
|
/** Everything the capture extension hands off to the studio. */
|
|
565
585
|
interface RecordingArtifact {
|
|
@@ -2599,6 +2619,11 @@ interface PlanOptions {
|
|
|
2599
2619
|
typingHold?: number;
|
|
2600
2620
|
/** level floor for typing spans (a wide field still reads punchier). */
|
|
2601
2621
|
typingMinLevel?: number;
|
|
2622
|
+
/**
|
|
2623
|
+
* The step timeline of a scripted take (`meta.steps`): one zoom per step
|
|
2624
|
+
* where its presses share a window, never one per press.
|
|
2625
|
+
*/
|
|
2626
|
+
steps?: readonly StepSpan[] | null;
|
|
2602
2627
|
}
|
|
2603
2628
|
/** One press (or ping) in seconds, with the target element when known. */
|
|
2604
2629
|
interface Click {
|
|
@@ -2636,7 +2661,99 @@ interface PlanTiltOptions {
|
|
|
2636
2661
|
*/
|
|
2637
2662
|
declare function planAutoTilt(zoom: readonly ZoomSpan[], segments: Segment[], options: PlanTiltOptions): TiltSpan[];
|
|
2638
2663
|
|
|
2639
|
-
|
|
2664
|
+
/**
|
|
2665
|
+
* The digest sees consequences: what a click or a typing run DID to the
|
|
2666
|
+
* page. A press is one frame; the page's answer comes after it, a dialog
|
|
2667
|
+
* opening, a 200 landing, a graph re-laying out, a card vanishing. The
|
|
2668
|
+
* region that changed in the seconds after the step is a moment a cut can
|
|
2669
|
+
* hold on, and a zoom can frame.
|
|
2670
|
+
*
|
|
2671
|
+
* Pure: the browser samples luma grids (the cli's digest page) at the
|
|
2672
|
+
* step's end and a few beats after it; this module finds the changed
|
|
2673
|
+
* region and keeps the sample that changed most. Two things keep it
|
|
2674
|
+
* honest on a page that moves on its own. A sample a beat BEFORE the step
|
|
2675
|
+
* gives each cell its own drift, and only what moved past that drift
|
|
2676
|
+
* counts (`ambientDrift`). And a change is judged by the blocks it FILLS,
|
|
2677
|
+
* not by the cells it touches: a silk or a shimmer flickers cells all over
|
|
2678
|
+
* the frame and fills no block, while a dialog, a recoloured pane or a
|
|
2679
|
+
* status line fills its own.
|
|
2680
|
+
*/
|
|
2681
|
+
|
|
2682
|
+
/** A luma grid of the frame at one instant, row-major, `w × h` cells. */
|
|
2683
|
+
interface LumaGrid {
|
|
2684
|
+
w: number;
|
|
2685
|
+
h: number;
|
|
2686
|
+
luma: ArrayLike<number>;
|
|
2687
|
+
}
|
|
2688
|
+
/** What changed between two grids: the largest cluster of blocks that filled, and its box. */
|
|
2689
|
+
interface ChangedRegion {
|
|
2690
|
+
/** The cluster's share of the frame's blocks, 0..1. */
|
|
2691
|
+
fraction: number;
|
|
2692
|
+
/** The cluster's bounding box, normalized frame fractions. */
|
|
2693
|
+
rect: NormRect;
|
|
2694
|
+
}
|
|
2695
|
+
/** The grid the browser samples: coarse enough that a cursor is one cell, a dialog a block. */
|
|
2696
|
+
declare const CHANGE_GRID: {
|
|
2697
|
+
readonly w: 128;
|
|
2698
|
+
readonly h: 72;
|
|
2699
|
+
};
|
|
2700
|
+
/** The floor a change must clear to be named: 2% of the frame's blocks. */
|
|
2701
|
+
declare const CHANGE_FLOOR = 0.02;
|
|
2702
|
+
/** How long after a seed the digest looks for its consequence, source seconds. */
|
|
2703
|
+
declare const CHANGE_OFFSETS: readonly [0.3, 0.8, 1.5, 2.5];
|
|
2704
|
+
/** How long before a seed the ambient sample is taken, source seconds. */
|
|
2705
|
+
declare const CHANGE_LEAD = 0.5;
|
|
2706
|
+
/**
|
|
2707
|
+
* The changed region between two grids, or null when nothing (or fewer
|
|
2708
|
+
* than `minBlocks`) filled. `delta` is the luma step a cell must move by,
|
|
2709
|
+
* the digest's own motion delta. `ambient`, when given, is what each cell
|
|
2710
|
+
* moves by on its own (see `ambientDrift`) and how long after `before`
|
|
2711
|
+
* this grid was taken: a cell counts only when it moved past what its own
|
|
2712
|
+
* drift explains over that time. A block is `block` cells a side (the
|
|
2713
|
+
* grid's sixteenth by default: 16 × 9 blocks over the sampled grid).
|
|
2714
|
+
*/
|
|
2715
|
+
declare function changedRegion(before: LumaGrid, after: LumaGrid, delta: number, minBlocks?: number, ambient?: {
|
|
2716
|
+
rate: ArrayLike<number>;
|
|
2717
|
+
dt: number;
|
|
2718
|
+
} | null, block?: number): ChangedRegion | null;
|
|
2719
|
+
/**
|
|
2720
|
+
* How much each cell moves on its own, per second: a page whose background
|
|
2721
|
+
* animates (a silk, a video, a shimmer) changes everywhere every frame, and
|
|
2722
|
+
* the consequence of a press would drown in it. Two grids taken BEFORE the
|
|
2723
|
+
* seed, `lead` seconds apart, give each cell its drift; `changedRegion`
|
|
2724
|
+
* then counts a cell only when it moved past what that drift explains.
|
|
2725
|
+
*/
|
|
2726
|
+
declare function ambientDrift(earlier: LumaGrid, before: LumaGrid, lead: number): number[] | null;
|
|
2727
|
+
/** One sample after a seed: when it was taken and what had changed by then. */
|
|
2728
|
+
interface ChangeSample {
|
|
2729
|
+
/** Source seconds after the seed. */
|
|
2730
|
+
dt: number;
|
|
2731
|
+
region: ChangedRegion | null;
|
|
2732
|
+
}
|
|
2733
|
+
/** A consequence the digest will name: a moment's seed and the region it changed. */
|
|
2734
|
+
interface ChangeWitness {
|
|
2735
|
+
/** The seed moment's id (a click or a typing run). */
|
|
2736
|
+
seed: string;
|
|
2737
|
+
/** Source second the seed ended at: the frame the change is measured from. */
|
|
2738
|
+
at: number;
|
|
2739
|
+
/** Source second of the sample that had changed most. */
|
|
2740
|
+
peakAt: number;
|
|
2741
|
+
fraction: number;
|
|
2742
|
+
rect: NormRect;
|
|
2743
|
+
}
|
|
2744
|
+
/**
|
|
2745
|
+
* The witness for one seed: the sample that changed most, when it clears
|
|
2746
|
+
* the floor. A consequence that never clears it is no moment, and a seed
|
|
2747
|
+
* that changed everything (a navigation) is the scene detector's.
|
|
2748
|
+
*/
|
|
2749
|
+
declare function pickChange(seed: {
|
|
2750
|
+
id: string;
|
|
2751
|
+
at: number;
|
|
2752
|
+
}, samples: readonly ChangeSample[], floor?: number): ChangeWitness | null;
|
|
2753
|
+
|
|
2754
|
+
type MomentKind = 'head' | 'tail' | 'click' | 'typing'
|
|
2755
|
+
/** What a click or a typing run DID: the region of the page that answered it. */
|
|
2756
|
+
| 'changed' | 'scroll' | 'dwell' | 'idle' | 'scene';
|
|
2640
2757
|
/** A rect in normalized [0..1] frame fractions (the zoom cx/cy convention). */
|
|
2641
2758
|
interface NormRect {
|
|
2642
2759
|
x: number;
|
|
@@ -2686,6 +2803,8 @@ interface Moment {
|
|
|
2686
2803
|
};
|
|
2687
2804
|
/** Transcript text over the window, when a transcript was merged. */
|
|
2688
2805
|
said: string | null;
|
|
2806
|
+
/** A `changed` moment: the click or typing moment it answers. */
|
|
2807
|
+
seed?: string;
|
|
2689
2808
|
}
|
|
2690
2809
|
interface DigestPlan {
|
|
2691
2810
|
zoom: ZoomSpan[];
|
|
@@ -2706,6 +2825,11 @@ interface MomentsOptions {
|
|
|
2706
2825
|
transcript?: readonly TranscriptSegment[] | null;
|
|
2707
2826
|
/** Idle threshold (seconds); defaults to the speed planner's. */
|
|
2708
2827
|
idleMin?: number;
|
|
2828
|
+
/**
|
|
2829
|
+
* What the clicks and typing runs did to the page, measured by the
|
|
2830
|
+
* digest's decode pass (see changes.ts): each becomes a `changed` moment.
|
|
2831
|
+
*/
|
|
2832
|
+
changes?: readonly ChangeWitness[];
|
|
2709
2833
|
}
|
|
2710
2834
|
/**
|
|
2711
2835
|
* The three planners, run fresh under the doc's own style — the proposals.
|
|
@@ -3292,6 +3416,33 @@ interface DigestTakeFacts {
|
|
|
3292
3416
|
/** Masks the script asked for, with how many elements each reached. */
|
|
3293
3417
|
masks: NonNullable<RecordingMeta['masks']>;
|
|
3294
3418
|
}
|
|
3419
|
+
/**
|
|
3420
|
+
* One script step as the digest tells it: when it ran in the footage and
|
|
3421
|
+
* in the cut, the page it left and the words its `read` kept, so an agent
|
|
3422
|
+
* places a layer by the table and quotes the take by the text.
|
|
3423
|
+
*/
|
|
3424
|
+
interface DigestStep {
|
|
3425
|
+
step: number;
|
|
3426
|
+
id: string | null;
|
|
3427
|
+
do: string;
|
|
3428
|
+
selector: string | null;
|
|
3429
|
+
/** Footage seconds the step occupied. */
|
|
3430
|
+
source: {
|
|
3431
|
+
in: number;
|
|
3432
|
+
out: number;
|
|
3433
|
+
};
|
|
3434
|
+
/** The same window in the cut, null when trimmed away. */
|
|
3435
|
+
output: {
|
|
3436
|
+
in: number;
|
|
3437
|
+
out: number;
|
|
3438
|
+
} | null;
|
|
3439
|
+
skipped: boolean;
|
|
3440
|
+
navigated: boolean;
|
|
3441
|
+
/** The page after the step, origin and path; null on a human recording. */
|
|
3442
|
+
url: string | null;
|
|
3443
|
+
/** The words the step's `read` kept, or null. */
|
|
3444
|
+
text: string | null;
|
|
3445
|
+
}
|
|
3295
3446
|
interface Digest {
|
|
3296
3447
|
digestVersion: number;
|
|
3297
3448
|
take: DigestTakeFacts;
|
|
@@ -3306,6 +3457,8 @@ interface Digest {
|
|
|
3306
3457
|
crop: string | null;
|
|
3307
3458
|
box: PxRect | null;
|
|
3308
3459
|
})[];
|
|
3460
|
+
/** The script's steps (a CLI take; empty for a human recording). */
|
|
3461
|
+
steps: DigestStep[];
|
|
3309
3462
|
activity: number[] | null;
|
|
3310
3463
|
plan: DigestPlan;
|
|
3311
3464
|
doc: {
|
|
@@ -5228,4 +5381,4 @@ declare function rejectSpan(rejected: RejectedSpan[] | undefined, lane: Rejected
|
|
|
5228
5381
|
anchor?: StepAnchor;
|
|
5229
5382
|
}, note?: string): RejectedSpan;
|
|
5230
5383
|
|
|
5231
|
-
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, 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, 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, anchorKindOf, anchorSourceDuration, animStep, applyLook, applyTemplate, aspectRatioValue, audioLane, backdropMedia, boldWeightFor, 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, isLoweredRecording, isMusicBed, isPlayback, isProgramDoc, isRecordingDoc, isRejected, isStageClip, isUnitStep, lastLayerEnd, layerMedia, layoutOf, levelForFocusFraction, liveZoomStyleName, lookFromBrand, lookKindForGround, lowerProgramDoc, lowerStudioDoc, lowerToComposition, marksEmphasis, mediaAtOutput, mediaDuration, mediaFrame, mediaKey, mediaRef, mediaRefId, mediaSource, micLane, migrateHostedDoc, migrateMotion, migrateText, migrateTextClip, migrateZoomStyle, 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, 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, snapRunWeight, spanOutputExtent, speedLane, 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 };
|
|
5384
|
+
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, 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 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, 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, 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, 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, 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, animStep, applyLook, applyTemplate, aspectRatioValue, audioLane, backdropMedia, boldWeightFor, buildDigest, calloutBox, calloutClip, calloutGroundOf, calloutLook, calloutSource, camBubbleRect, camBubbleRectAt, camLane, camMoveLane, camRectFromPose, camRestPose, camTrackFromDoc, cameraCentring, cameraModel, cardEnter, cardExit, cardFields, cardInset, cardPointToScreen, cardPoseTrack, changedRegion, 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, isLoweredRecording, isMusicBed, isPlayback, isProgramDoc, isRecordingDoc, isRejected, isStageClip, isUnitStep, lastLayerEnd, layerMedia, layoutOf, levelForFocusFraction, liveZoomStyleName, lookFromBrand, lookKindForGround, lowerProgramDoc, lowerStudioDoc, lowerToComposition, marksEmphasis, mediaAtOutput, mediaDuration, mediaFrame, mediaKey, mediaRef, mediaRefId, mediaSource, micLane, migrateHostedDoc, migrateMotion, migrateText, migrateTextClip, migrateZoomStyle, 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, resolveExportSize, resolveOverlayBox, resolveOverlayStyle, resolvePins, resolveText3dAsset, resolveZoomStyle, restLeanOf, restSpansThroughTransitions, rgbToHex, sameMedia, sceneChanges, scrollRuns, segmentOutputExtents, outputLen as segmentOutputLen, segmentStarts, setSpeedInRange, slideSide, smoothCursor, snapRunWeight, spanOutputExtent, speedLane, 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
|
@@ -3403,6 +3403,13 @@ var TYPING_CLICK_ABSORB = 1.5;
|
|
|
3403
3403
|
var TYPING_REFOCUS_FRAC = 0.08;
|
|
3404
3404
|
function groupTrack(track, opts) {
|
|
3405
3405
|
const { width, height, clusterGap, typingGap, typingZoom, targetFill } = opts;
|
|
3406
|
+
const stepOf = (t) => opts.steps?.find(
|
|
3407
|
+
(st) => st.do !== "wait" && !st.skipped && st.tStart <= t && t <= st.tEnd
|
|
3408
|
+
) ?? null;
|
|
3409
|
+
const sameStep = (a, b) => {
|
|
3410
|
+
const sa = stepOf(a.t);
|
|
3411
|
+
return sa !== null && sa === stepOf(b.t);
|
|
3412
|
+
};
|
|
3406
3413
|
const minLevel = opts.minLevel ?? resolveZoomStyle().minLevel;
|
|
3407
3414
|
const clicks = dedupePresses(
|
|
3408
3415
|
track.filter((e) => e.type === "down")
|
|
@@ -3436,7 +3443,7 @@ function groupTrack(track, opts) {
|
|
|
3436
3443
|
for (const c of list) {
|
|
3437
3444
|
const last = clusters.at(-1);
|
|
3438
3445
|
const prev = last?.at(-1);
|
|
3439
|
-
const joins = last && prev && c.t - prev.t <= clusterGap && (!spatial || unionFitLevel(unionRect([...last, c]), width, height) >= minLevel);
|
|
3446
|
+
const joins = last && prev && (c.t - prev.t <= clusterGap || sameStep(prev, c)) && (!spatial || unionFitLevel(unionRect([...last, c]), width, height) >= minLevel);
|
|
3440
3447
|
if (joins) last.push(c);
|
|
3441
3448
|
else clusters.push([c]);
|
|
3442
3449
|
}
|
|
@@ -3515,7 +3522,8 @@ function planAutoZoom(track, options) {
|
|
|
3515
3522
|
typingGap,
|
|
3516
3523
|
typingZoom,
|
|
3517
3524
|
targetFill,
|
|
3518
|
-
minLevel
|
|
3525
|
+
minLevel,
|
|
3526
|
+
steps: options.steps
|
|
3519
3527
|
});
|
|
3520
3528
|
const { sessions } = grouped;
|
|
3521
3529
|
const drags = dragsFromTrack(track, width, height);
|
|
@@ -3630,10 +3638,11 @@ function planAutoZoom(track, options) {
|
|
|
3630
3638
|
const spans = within([...zSpans, ...kSpans, ...dragSpans]).sort(
|
|
3631
3639
|
(a, b) => a.in - b.in
|
|
3632
3640
|
);
|
|
3641
|
+
const firstStep = options.steps?.find((st) => !st.skipped)?.tStart;
|
|
3633
3642
|
const dwells = dwellSpans(track, width, height, maxLevel, [
|
|
3634
3643
|
...spans,
|
|
3635
3644
|
...dragReserved
|
|
3636
|
-
]);
|
|
3645
|
+
]).filter((d) => firstStep === void 0 || d.out > firstStep);
|
|
3637
3646
|
return within([...spans, ...dwells]).sort((a, b) => a.in - b.in);
|
|
3638
3647
|
}
|
|
3639
3648
|
function typingSessions(track, width, height, typingGap) {
|
|
@@ -9238,13 +9247,15 @@ var DEFAULT_SPEED_PARAMS = {
|
|
|
9238
9247
|
typingMin: 3,
|
|
9239
9248
|
typingRate: 3,
|
|
9240
9249
|
scrollMin: 2.5,
|
|
9241
|
-
scrollRate: 2
|
|
9250
|
+
scrollRate: 2,
|
|
9251
|
+
stillRate: 2
|
|
9242
9252
|
};
|
|
9243
9253
|
var TYPING_GAP = 1.5;
|
|
9244
9254
|
var SCROLL_GAP = 0.8;
|
|
9245
9255
|
var IDLE_PAD = 0.6;
|
|
9246
9256
|
var MIN_SPAN = 1;
|
|
9247
9257
|
var PLAYBACK_ACTIVITY = 0.1;
|
|
9258
|
+
var STILL_ACTIVITY = 0.02;
|
|
9248
9259
|
function planAutoSpeed(track, opts) {
|
|
9249
9260
|
const p = { ...DEFAULT_SPEED_PARAMS, ...opts.params };
|
|
9250
9261
|
const durS = opts.durationMs / 1e3;
|
|
@@ -9263,6 +9274,9 @@ function planAutoSpeed(track, opts) {
|
|
|
9263
9274
|
p.scrollMin,
|
|
9264
9275
|
(start, last) => cands.push({ in: start, out: last, rate: p.scrollRate })
|
|
9265
9276
|
);
|
|
9277
|
+
for (const [a, b] of stillSteps(opts.steps, opts.activity)) {
|
|
9278
|
+
if (b - a >= MIN_SPAN) cands.push({ in: a, out: b, rate: p.stillRate });
|
|
9279
|
+
}
|
|
9266
9280
|
for (const [a, b] of idleGaps(evs, durS, p.idleMin)) {
|
|
9267
9281
|
if (isPlayback(opts.activity, a, b)) continue;
|
|
9268
9282
|
const start = a + IDLE_PAD;
|
|
@@ -9316,6 +9330,29 @@ function idleGaps(track, durationS, idleMin = DEFAULT_SPEED_PARAMS.idleMin) {
|
|
|
9316
9330
|
if (durationS - prev >= idleMin) gaps.push([prev, durationS]);
|
|
9317
9331
|
return gaps;
|
|
9318
9332
|
}
|
|
9333
|
+
function stillSteps(steps, activity) {
|
|
9334
|
+
if (!steps?.length || !activity?.length) return [];
|
|
9335
|
+
const live = steps.filter((st) => !st.skipped);
|
|
9336
|
+
const doing = live.map((st) => st.do !== "wait");
|
|
9337
|
+
const first = doing.indexOf(true);
|
|
9338
|
+
const last = doing.lastIndexOf(true);
|
|
9339
|
+
const out = [];
|
|
9340
|
+
for (const [i, st] of live.entries()) {
|
|
9341
|
+
if (st.do !== "wait" && st.do !== "hover") continue;
|
|
9342
|
+
if (st.do === "wait" && (first < 0 || i < first || i > last)) continue;
|
|
9343
|
+
if (meanActivity(activity, st.tStart, st.tEnd) >= STILL_ACTIVITY) continue;
|
|
9344
|
+
out.push([st.tStart, st.tEnd]);
|
|
9345
|
+
}
|
|
9346
|
+
return out;
|
|
9347
|
+
}
|
|
9348
|
+
function meanActivity(activity, a, b) {
|
|
9349
|
+
const lo = Math.max(0, Math.floor(a));
|
|
9350
|
+
const hi = Math.min(activity.length, Math.ceil(b));
|
|
9351
|
+
if (hi <= lo) return 0;
|
|
9352
|
+
let sum = 0;
|
|
9353
|
+
for (let i = lo; i < hi; i++) sum += activity[i];
|
|
9354
|
+
return sum / (hi - lo);
|
|
9355
|
+
}
|
|
9319
9356
|
function isPlayback(activity, a, b) {
|
|
9320
9357
|
if (!activity?.length) return false;
|
|
9321
9358
|
const lo = Math.max(0, Math.floor(a));
|
|
@@ -9354,12 +9391,14 @@ function planForDigest(doc, activity) {
|
|
|
9354
9391
|
width: meta.width,
|
|
9355
9392
|
height: meta.height,
|
|
9356
9393
|
style: doc.zoomStyle,
|
|
9357
|
-
params: doc.zoomParams
|
|
9394
|
+
params: doc.zoomParams,
|
|
9395
|
+
steps: meta.steps
|
|
9358
9396
|
});
|
|
9359
9397
|
const speed = planAutoSpeed(cursor, {
|
|
9360
9398
|
durationMs: meta.durationMs,
|
|
9361
9399
|
params: doc.speedParams,
|
|
9362
|
-
activity
|
|
9400
|
+
activity,
|
|
9401
|
+
steps: meta.steps
|
|
9363
9402
|
});
|
|
9364
9403
|
const style = resolveZoomStyle(doc.zoomStyle, doc.zoomParams);
|
|
9365
9404
|
const intensity = doc.tiltStyle ?? style.tilt.intensity;
|
|
@@ -9399,7 +9438,8 @@ function momentsFromDoc(doc, plan, opts = {}) {
|
|
|
9399
9438
|
typingGap: style.typingGap,
|
|
9400
9439
|
typingZoom: style.typingZoom,
|
|
9401
9440
|
targetFill: style.targetFill,
|
|
9402
|
-
minLevel: style.minLevel
|
|
9441
|
+
minLevel: style.minLevel,
|
|
9442
|
+
steps: meta.steps
|
|
9403
9443
|
});
|
|
9404
9444
|
const pressed = (c, surface) => {
|
|
9405
9445
|
const f = clusterFocus(c, width, height);
|
|
@@ -9495,15 +9535,30 @@ function momentsFromDoc(doc, plan, opts = {}) {
|
|
|
9495
9535
|
rect: null
|
|
9496
9536
|
});
|
|
9497
9537
|
}
|
|
9538
|
+
for (const c of opts.changes ?? []) {
|
|
9539
|
+
if (!(c.at >= 0 && c.at < dur)) continue;
|
|
9540
|
+
const peak = Math.min(dur, Math.max(c.at, c.peakAt));
|
|
9541
|
+
drafts.push({
|
|
9542
|
+
kind: "changed",
|
|
9543
|
+
in: c.at,
|
|
9544
|
+
out: peak,
|
|
9545
|
+
at: peak,
|
|
9546
|
+
focus: { cx: c.rect.x + c.rect.w / 2, cy: c.rect.y + c.rect.h / 2 },
|
|
9547
|
+
rect: c.rect,
|
|
9548
|
+
seedAt: c.at,
|
|
9549
|
+
fraction: c.fraction
|
|
9550
|
+
});
|
|
9551
|
+
}
|
|
9498
9552
|
const order = {
|
|
9499
9553
|
head: 0,
|
|
9500
9554
|
click: 1,
|
|
9501
9555
|
typing: 2,
|
|
9502
|
-
|
|
9503
|
-
|
|
9504
|
-
|
|
9505
|
-
|
|
9506
|
-
|
|
9556
|
+
changed: 3,
|
|
9557
|
+
scroll: 4,
|
|
9558
|
+
dwell: 5,
|
|
9559
|
+
scene: 6,
|
|
9560
|
+
idle: 7,
|
|
9561
|
+
tail: 8
|
|
9507
9562
|
};
|
|
9508
9563
|
drafts.sort((a, b) => a.in - b.in || order[a.kind] - order[b.kind]);
|
|
9509
9564
|
const rated = ratedSegments(doc);
|
|
@@ -9512,8 +9567,17 @@ function momentsFromDoc(doc, plan, opts = {}) {
|
|
|
9512
9567
|
return spanOutputExtent(rated, lo, Math.max(b, lo + 1e-3));
|
|
9513
9568
|
};
|
|
9514
9569
|
const covers = (s, d) => d.in === d.out ? s.in <= d.in && d.in < s.out : s.in < d.out && s.out > d.in;
|
|
9570
|
+
const ids = drafts.map((_, i) => `m${String(i + 1).padStart(2, "0")}`);
|
|
9571
|
+
const seedOf = (d) => {
|
|
9572
|
+
if (d.kind !== "changed" || d.seedAt === void 0) return void 0;
|
|
9573
|
+
const j = drafts.findIndex(
|
|
9574
|
+
(x) => x.kind === "click" && x.at === d.seedAt || x.kind === "typing" && x.out === d.seedAt
|
|
9575
|
+
);
|
|
9576
|
+
return j >= 0 ? ids[j] : void 0;
|
|
9577
|
+
};
|
|
9515
9578
|
return drafts.map((d, i) => {
|
|
9516
9579
|
const output = outputOf(d.in, d.out);
|
|
9580
|
+
const seed = seedOf(d);
|
|
9517
9581
|
const outAt = d.at === null ? null : outputOf(d.at, d.at);
|
|
9518
9582
|
const proposed = {};
|
|
9519
9583
|
const z = plan.zoom.find((s) => covers(s, d));
|
|
@@ -9523,7 +9587,7 @@ function momentsFromDoc(doc, plan, opts = {}) {
|
|
|
9523
9587
|
const tl = plan.tilt.find((s) => covers(s, d));
|
|
9524
9588
|
if (tl) proposed.tilt = tl.id;
|
|
9525
9589
|
return {
|
|
9526
|
-
id:
|
|
9590
|
+
id: ids[i],
|
|
9527
9591
|
kind: d.kind,
|
|
9528
9592
|
source: { in: round10(d.in), out: round10(d.out) },
|
|
9529
9593
|
output: output ? { in: round10(output.start), out: round10(output.end) } : null,
|
|
@@ -9539,9 +9603,10 @@ function momentsFromDoc(doc, plan, opts = {}) {
|
|
|
9539
9603
|
...d.clicks !== void 0 ? { clicks: d.clicks } : {},
|
|
9540
9604
|
...d.surface ? { surface: true } : {},
|
|
9541
9605
|
...d.pings !== void 0 ? { pings: d.pings } : {},
|
|
9542
|
-
activity: activityOf(opts.bins, d),
|
|
9606
|
+
activity: d.kind === "changed" && d.fraction !== void 0 ? round10(d.fraction) : activityOf(opts.bins, d),
|
|
9543
9607
|
proposed,
|
|
9544
|
-
said: saidOver(opts.transcript, d)
|
|
9608
|
+
said: saidOver(opts.transcript, d),
|
|
9609
|
+
...seed ? { seed } : {}
|
|
9545
9610
|
};
|
|
9546
9611
|
});
|
|
9547
9612
|
}
|
|
@@ -9568,6 +9633,105 @@ function round10(v) {
|
|
|
9568
9633
|
return Math.round(v * 1e3) / 1e3;
|
|
9569
9634
|
}
|
|
9570
9635
|
|
|
9636
|
+
// src/digest/changes.ts
|
|
9637
|
+
var CHANGE_GRID = { w: 128, h: 72 };
|
|
9638
|
+
var BLOCK_FILL = 0.5;
|
|
9639
|
+
var CHANGE_FLOOR = 0.02;
|
|
9640
|
+
var CHANGE_OFFSETS = [0.3, 0.8, 1.5, 2.5];
|
|
9641
|
+
var CHANGE_LEAD = 0.5;
|
|
9642
|
+
function changedRegion(before, after, delta, minBlocks = 1, ambient = null, block = Math.max(1, Math.round(before.w / 16))) {
|
|
9643
|
+
const { w, h } = before;
|
|
9644
|
+
if (after.w !== w || after.h !== h || w <= 0 || h <= 0) return null;
|
|
9645
|
+
const cols = Math.ceil(w / block);
|
|
9646
|
+
const rows = Math.ceil(h / block);
|
|
9647
|
+
const moved = new Uint16Array(cols * rows);
|
|
9648
|
+
const cells = new Uint16Array(cols * rows);
|
|
9649
|
+
for (let y = 0; y < h; y++) {
|
|
9650
|
+
const by = Math.floor(y / block);
|
|
9651
|
+
for (let x = 0; x < w; x++) {
|
|
9652
|
+
const i = y * w + x;
|
|
9653
|
+
const b = by * cols + Math.floor(x / block);
|
|
9654
|
+
cells[b]++;
|
|
9655
|
+
const drift = ambient ? ambient.rate[i] * ambient.dt : 0;
|
|
9656
|
+
if (Math.abs(after.luma[i] - before.luma[i]) - drift > delta) moved[b]++;
|
|
9657
|
+
}
|
|
9658
|
+
}
|
|
9659
|
+
const filled = new Uint8Array(cols * rows);
|
|
9660
|
+
for (let b = 0; b < filled.length; b++)
|
|
9661
|
+
if (moved[b] >= cells[b] * BLOCK_FILL) filled[b] = 1;
|
|
9662
|
+
const seen = new Uint8Array(cols * rows);
|
|
9663
|
+
let best = null;
|
|
9664
|
+
for (let start = 0; start < filled.length; start++) {
|
|
9665
|
+
if (!filled[start] || seen[start]) continue;
|
|
9666
|
+
const stack = [start];
|
|
9667
|
+
seen[start] = 1;
|
|
9668
|
+
let size = 0;
|
|
9669
|
+
let minX = cols;
|
|
9670
|
+
let minY = rows;
|
|
9671
|
+
let maxX = -1;
|
|
9672
|
+
let maxY = -1;
|
|
9673
|
+
while (stack.length) {
|
|
9674
|
+
const b = stack.pop();
|
|
9675
|
+
size++;
|
|
9676
|
+
const bx = b % cols;
|
|
9677
|
+
const by = Math.floor(b / cols);
|
|
9678
|
+
if (bx < minX) minX = bx;
|
|
9679
|
+
if (bx > maxX) maxX = bx;
|
|
9680
|
+
if (by < minY) minY = by;
|
|
9681
|
+
if (by > maxY) maxY = by;
|
|
9682
|
+
for (const [dx, dy] of [
|
|
9683
|
+
[1, 0],
|
|
9684
|
+
[-1, 0],
|
|
9685
|
+
[0, 1],
|
|
9686
|
+
[0, -1]
|
|
9687
|
+
]) {
|
|
9688
|
+
const nx = bx + dx;
|
|
9689
|
+
const ny = by + dy;
|
|
9690
|
+
if (nx < 0 || ny < 0 || nx >= cols || ny >= rows) continue;
|
|
9691
|
+
const n = ny * cols + nx;
|
|
9692
|
+
if (filled[n] && !seen[n]) {
|
|
9693
|
+
seen[n] = 1;
|
|
9694
|
+
stack.push(n);
|
|
9695
|
+
}
|
|
9696
|
+
}
|
|
9697
|
+
}
|
|
9698
|
+
if (!best || size > best.size) best = { size, minX, minY, maxX, maxY };
|
|
9699
|
+
}
|
|
9700
|
+
if (!best || best.size < minBlocks) return null;
|
|
9701
|
+
return {
|
|
9702
|
+
fraction: best.size / (cols * rows),
|
|
9703
|
+
rect: {
|
|
9704
|
+
x: best.minX * block / w,
|
|
9705
|
+
y: best.minY * block / h,
|
|
9706
|
+
w: Math.min(w, (best.maxX + 1) * block) / w - best.minX * block / w,
|
|
9707
|
+
h: Math.min(h, (best.maxY + 1) * block) / h - best.minY * block / h
|
|
9708
|
+
}
|
|
9709
|
+
};
|
|
9710
|
+
}
|
|
9711
|
+
function ambientDrift(earlier, before, lead) {
|
|
9712
|
+
const { w, h } = before;
|
|
9713
|
+
if (earlier.w !== w || earlier.h !== h || !(lead > 0)) return null;
|
|
9714
|
+
const rate = new Array(w * h);
|
|
9715
|
+
for (let i = 0; i < rate.length; i++)
|
|
9716
|
+
rate[i] = Math.abs(before.luma[i] - earlier.luma[i]) / lead;
|
|
9717
|
+
return rate;
|
|
9718
|
+
}
|
|
9719
|
+
function pickChange(seed, samples, floor = CHANGE_FLOOR) {
|
|
9720
|
+
let best = null;
|
|
9721
|
+
for (const s of samples) {
|
|
9722
|
+
if (!s.region || s.region.fraction < floor) continue;
|
|
9723
|
+
if (!best || s.region.fraction > (best.region?.fraction ?? 0)) best = s;
|
|
9724
|
+
}
|
|
9725
|
+
if (!best?.region) return null;
|
|
9726
|
+
return {
|
|
9727
|
+
seed: seed.id,
|
|
9728
|
+
at: seed.at,
|
|
9729
|
+
peakAt: seed.at + best.dt,
|
|
9730
|
+
fraction: best.region.fraction,
|
|
9731
|
+
rect: best.region.rect
|
|
9732
|
+
};
|
|
9733
|
+
}
|
|
9734
|
+
|
|
9571
9735
|
// src/digest/scenes.ts
|
|
9572
9736
|
var SCENE_MOTION = 0.25;
|
|
9573
9737
|
var SCENE_QUIET = 0.1;
|
|
@@ -10099,6 +10263,7 @@ function buildDigest(input) {
|
|
|
10099
10263
|
activity: "fraction of pixels that changed, per SOURCE second"
|
|
10100
10264
|
},
|
|
10101
10265
|
moments: withFiles,
|
|
10266
|
+
steps: digestSteps(doc),
|
|
10102
10267
|
activity: input.bins,
|
|
10103
10268
|
plan: input.plan,
|
|
10104
10269
|
doc: {
|
|
@@ -10122,6 +10287,26 @@ function buildDigest(input) {
|
|
|
10122
10287
|
}
|
|
10123
10288
|
};
|
|
10124
10289
|
}
|
|
10290
|
+
function digestSteps(doc) {
|
|
10291
|
+
const steps = doc.source.meta.steps ?? [];
|
|
10292
|
+
if (!steps.length) return [];
|
|
10293
|
+
const rated = ratedSegments(doc);
|
|
10294
|
+
return steps.map((s) => {
|
|
10295
|
+
const out = spanOutputExtent(rated, s.tStart, s.tEnd);
|
|
10296
|
+
return {
|
|
10297
|
+
step: s.step,
|
|
10298
|
+
id: s.id ?? null,
|
|
10299
|
+
do: s.do,
|
|
10300
|
+
selector: s.selector ?? null,
|
|
10301
|
+
source: { in: round11(s.tStart), out: round11(s.tEnd) },
|
|
10302
|
+
output: out ? { in: round11(out.start), out: round11(out.end) } : null,
|
|
10303
|
+
skipped: s.skipped === true,
|
|
10304
|
+
navigated: s.navigated === true,
|
|
10305
|
+
url: s.url ?? null,
|
|
10306
|
+
text: s.text ?? null
|
|
10307
|
+
};
|
|
10308
|
+
});
|
|
10309
|
+
}
|
|
10125
10310
|
function outputDurationOf(doc) {
|
|
10126
10311
|
return docOutputDuration(doc);
|
|
10127
10312
|
}
|
|
@@ -11956,6 +12141,10 @@ export {
|
|
|
11956
12141
|
CARD_FADE_SECONDS,
|
|
11957
12142
|
CARD_FOV,
|
|
11958
12143
|
CARD_Z,
|
|
12144
|
+
CHANGE_FLOOR,
|
|
12145
|
+
CHANGE_GRID,
|
|
12146
|
+
CHANGE_LEAD,
|
|
12147
|
+
CHANGE_OFFSETS,
|
|
11959
12148
|
CHANNEL_SPECS_HASH,
|
|
11960
12149
|
CHANNEL_SPECS_VERIFIED,
|
|
11961
12150
|
CLICK_FX_INTENSITY,
|
|
@@ -12105,6 +12294,7 @@ export {
|
|
|
12105
12294
|
ZOOM_SPAN_MIN,
|
|
12106
12295
|
ZOOM_STYLES,
|
|
12107
12296
|
ZOOM_STYLE_OPTIONS,
|
|
12297
|
+
ambientDrift,
|
|
12108
12298
|
anchorKindOf,
|
|
12109
12299
|
anchorSourceDuration,
|
|
12110
12300
|
animStep,
|
|
@@ -12137,6 +12327,7 @@ export {
|
|
|
12137
12327
|
cardPoseTrack,
|
|
12138
12328
|
caretAt,
|
|
12139
12329
|
caretStops,
|
|
12330
|
+
changedRegion,
|
|
12140
12331
|
clampCamFrac,
|
|
12141
12332
|
clampCamSize,
|
|
12142
12333
|
clampFocus,
|
|
@@ -12289,6 +12480,7 @@ export {
|
|
|
12289
12480
|
pageDisplayUrl,
|
|
12290
12481
|
parseCssColour,
|
|
12291
12482
|
parsePoseId,
|
|
12483
|
+
pickChange,
|
|
12292
12484
|
pickStyle,
|
|
12293
12485
|
pinBox,
|
|
12294
12486
|
pinCandidates,
|