clipwise 0.2.1 → 0.3.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
@@ -492,6 +492,7 @@ declare const OutputConfigSchema: z.ZodObject<{
492
492
  height: z.ZodDefault<z.ZodNumber>;
493
493
  fps: z.ZodDefault<z.ZodNumber>;
494
494
  quality: z.ZodDefault<z.ZodNumber>;
495
+ preset: z.ZodOptional<z.ZodEnum<["social", "balanced", "archive"]>>;
495
496
  outputDir: z.ZodDefault<z.ZodString>;
496
497
  filename: z.ZodDefault<z.ZodString>;
497
498
  }, "strip", z.ZodTypeAny, {
@@ -502,12 +503,14 @@ declare const OutputConfigSchema: z.ZodObject<{
502
503
  quality: number;
503
504
  outputDir: string;
504
505
  filename: string;
506
+ preset?: "social" | "balanced" | "archive" | undefined;
505
507
  }, {
506
508
  format?: "gif" | "mp4" | "webm" | "png-sequence" | undefined;
507
509
  width?: number | undefined;
508
510
  height?: number | undefined;
509
511
  fps?: number | undefined;
510
512
  quality?: number | undefined;
513
+ preset?: "social" | "balanced" | "archive" | undefined;
511
514
  outputDir?: string | undefined;
512
515
  filename?: string | undefined;
513
516
  }>;
@@ -1146,6 +1149,7 @@ declare const ScenarioSchema: z.ZodObject<{
1146
1149
  height: z.ZodDefault<z.ZodNumber>;
1147
1150
  fps: z.ZodDefault<z.ZodNumber>;
1148
1151
  quality: z.ZodDefault<z.ZodNumber>;
1152
+ preset: z.ZodOptional<z.ZodEnum<["social", "balanced", "archive"]>>;
1149
1153
  outputDir: z.ZodDefault<z.ZodString>;
1150
1154
  filename: z.ZodDefault<z.ZodString>;
1151
1155
  }, "strip", z.ZodTypeAny, {
@@ -1156,12 +1160,14 @@ declare const ScenarioSchema: z.ZodObject<{
1156
1160
  quality: number;
1157
1161
  outputDir: string;
1158
1162
  filename: string;
1163
+ preset?: "social" | "balanced" | "archive" | undefined;
1159
1164
  }, {
1160
1165
  format?: "gif" | "mp4" | "webm" | "png-sequence" | undefined;
1161
1166
  width?: number | undefined;
1162
1167
  height?: number | undefined;
1163
1168
  fps?: number | undefined;
1164
1169
  quality?: number | undefined;
1170
+ preset?: "social" | "balanced" | "archive" | undefined;
1165
1171
  outputDir?: string | undefined;
1166
1172
  filename?: string | undefined;
1167
1173
  }>>;
@@ -1543,6 +1549,7 @@ declare const ScenarioSchema: z.ZodObject<{
1543
1549
  quality: number;
1544
1550
  outputDir: string;
1545
1551
  filename: string;
1552
+ preset?: "social" | "balanced" | "archive" | undefined;
1546
1553
  };
1547
1554
  steps: {
1548
1555
  actions: ({
@@ -1749,6 +1756,7 @@ declare const ScenarioSchema: z.ZodObject<{
1749
1756
  height?: number | undefined;
1750
1757
  fps?: number | undefined;
1751
1758
  quality?: number | undefined;
1759
+ preset?: "social" | "balanced" | "archive" | undefined;
1752
1760
  outputDir?: string | undefined;
1753
1761
  filename?: string | undefined;
1754
1762
  } | undefined;
@@ -1775,6 +1783,8 @@ interface CapturedFrame {
1775
1783
  width: number;
1776
1784
  height: number;
1777
1785
  };
1786
+ /** Device pixel ratio used during capture (1 = normal, 2 = Retina/HiDPI). */
1787
+ deviceScaleFactor?: number;
1778
1788
  stepName?: string;
1779
1789
  stepIndex?: number;
1780
1790
  actionType?: string;
@@ -1804,6 +1814,7 @@ declare class ClipwiseRecorder {
1804
1814
  private currentStepIndex;
1805
1815
  private cursorPosition;
1806
1816
  private viewport;
1817
+ private deviceScaleFactor;
1807
1818
  private isCapturing;
1808
1819
  private targetFps;
1809
1820
  private cursorSpeed;
@@ -1868,6 +1879,11 @@ declare class ClipwiseRecorder {
1868
1879
  * Interpolate cursor position at a given timestamp using the cursor timeline.
1869
1880
  */
1870
1881
  private interpolateCursorAt;
1882
+ /**
1883
+ * Binary search: returns the index of the last entry whose timestamp <= target.
1884
+ * Assumes the array is sorted by timestamp in ascending order.
1885
+ */
1886
+ private binarySearchTimeline;
1871
1887
  /**
1872
1888
  * Clean up browser resources. Always called after recording.
1873
1889
  */
@@ -1882,25 +1898,15 @@ interface FrameContext {
1882
1898
  y: number;
1883
1899
  }>;
1884
1900
  }
1901
+
1885
1902
  declare class CanvasRenderer {
1886
1903
  private effects;
1887
1904
  private output;
1888
1905
  private steps;
1889
1906
  constructor(effects: EffectsConfig, output: OutputConfig, steps?: Step[]);
1890
1907
  /**
1891
- * Apply the full effects pipeline to a single captured frame.
1892
- *
1893
- * Pipeline order:
1894
- * 1. Device frame (browser chrome / mobile mockup)
1895
- * 2. Cursor highlight (Screen Studio glow)
1896
- * 3. Cursor trail
1897
- * 4. Cursor rendering
1898
- * 5. Click ripple effect (animated progress)
1899
- * 6. Keystroke HUD
1900
- * 7. Zoom (adaptive, cursor-following)
1901
- * 8. Background (padding, gradient, rounded corners)
1902
- * 9. Watermark overlay
1903
- * 10. Final resize
1908
+ * Apply the full effects pipeline to a single frame.
1909
+ * Delegates to the standalone composeFrame function.
1904
1910
  */
1905
1911
  composeFrame(frame: CapturedFrame, context?: Partial<FrameContext>): Promise<ComposedFrame>;
1906
1912
  /**
@@ -1909,22 +1915,25 @@ declare class CanvasRenderer {
1909
1915
  * Multi-pass approach:
1910
1916
  * Pass 1: Speed ramping (adjust frame set).
1911
1917
  * Pass 2: Calculate per-frame contexts (zoom, click, trail).
1912
- * Pass 3: Render each frame with effects.
1918
+ * Pass 3: Render frames in parallel using worker threads.
1913
1919
  * Pass 4: Apply scene transitions at step boundaries.
1914
1920
  */
1915
1921
  composeAll(frames: CapturedFrame[]): Promise<ComposedFrame[]>;
1916
1922
  /**
1917
- * Calculate per-frame rendering context (zoom, click progress, cursor trail, tilt).
1923
+ * Distribute frame composition across a pool of worker threads.
1924
+ * Workers process frames concurrently; results are collected in order.
1925
+ */
1926
+ private processWithWorkers;
1927
+ /**
1928
+ * Calculate per-frame rendering context (zoom scale, click progress, cursor trail).
1918
1929
  */
1919
1930
  private calculateFrameContexts;
1920
1931
  /**
1921
1932
  * Apply speed ramping: slow down near actions, speed up during idle.
1922
- * Returns a new frame array with frames duplicated or skipped.
1923
1933
  */
1924
1934
  private applySpeedRamp;
1925
1935
  /**
1926
1936
  * Apply crossfade transitions at step boundaries where configured.
1927
- * Modifies the composed array in-place.
1928
1937
  */
1929
1938
  private applyTransitions;
1930
1939
  }
@@ -1935,15 +1944,22 @@ declare class CanvasRenderer {
1935
1944
  */
1936
1945
  declare function encodeGif(frames: ComposedFrame[], config: OutputConfig): Promise<Buffer>;
1937
1946
  /**
1938
- * Encode a sequence of composed frames into an MP4 file using ffmpeg.
1939
- * Writes frames as PNG sequence to a temp directory, then runs ffmpeg.
1947
+ * Encode a sequence of composed frames into an MP4 buffer.
1948
+ *
1949
+ * Uses FFmpeg stdin piping (raw video) to eliminate disk I/O overhead.
1950
+ * Encoder priority: hevc_videotoolbox (macOS HEVC HW) → h264_videotoolbox
1951
+ * (macOS H.264 HW) → libx264 (software fallback).
1952
+ *
1953
+ * Encoding quality is controlled by the output.preset field:
1954
+ * social — screen-recording quality, ~2–4 MB / 30s
1955
+ * balanced — high fidelity, ~4–8 MB / 30s
1956
+ * archive — near-lossless, uncapped bitrate
1940
1957
  *
1941
1958
  * Requires ffmpeg to be installed and available in PATH.
1942
1959
  */
1943
1960
  declare function encodeMp4(frames: ComposedFrame[], config: OutputConfig): Promise<Buffer>;
1944
1961
  /**
1945
1962
  * Save a sequence of composed frames as individual PNG files.
1946
- * Returns an array of file paths for the saved images.
1947
1963
  */
1948
1964
  declare function savePngSequence(frames: ComposedFrame[], config: OutputConfig): Promise<string[]>;
1949
1965
 
@@ -1982,26 +1998,28 @@ declare function lerpZoom(current: number, target: number, factor: number): numb
1982
1998
  type CursorEffect = EffectsConfig["cursor"];
1983
1999
  /**
1984
2000
  * Render a glowing highlight circle around the cursor (Screen Studio style).
2001
+ * @param dpr - Device pixel ratio (default 1). Scales position and size for HiDPI.
1985
2002
  */
1986
2003
  declare function renderCursorHighlight(frameBuffer: Buffer, position: {
1987
2004
  x: number;
1988
2005
  y: number;
1989
- }, config: CursorEffect, frameWidth: number, frameHeight: number): Promise<Buffer>;
2006
+ }, config: CursorEffect, frameWidth: number, frameHeight: number, dpr?: number): Promise<Buffer>;
1990
2007
  /**
1991
2008
  * Render a cursor trail (fading line segments following cursor path).
1992
2009
  * Each segment fades from transparent (oldest) to opaque (newest).
2010
+ * @param dpr - Device pixel ratio (default 1). Scales positions for HiDPI.
1993
2011
  */
1994
2012
  declare function renderCursorTrail(frameBuffer: Buffer, positions: Array<{
1995
2013
  x: number;
1996
2014
  y: number;
1997
- }>, config: CursorEffect, frameWidth: number, frameHeight: number): Promise<Buffer>;
2015
+ }>, config: CursorEffect, frameWidth: number, frameHeight: number, dpr?: number): Promise<Buffer>;
1998
2016
 
1999
2017
  type KeystrokeConfig = EffectsConfig["keystroke"];
2000
2018
  /**
2001
2019
  * Render a keystroke HUD overlay showing recently typed keys.
2002
2020
  * Inspired by KeyCastr / CursorClip.
2003
2021
  */
2004
- declare function renderKeystrokeHud(frameBuffer: Buffer, keystrokes: KeystrokeEvent[], frameTimestamp: number, config: KeystrokeConfig, frameWidth: number, frameHeight: number): Promise<Buffer>;
2022
+ declare function renderKeystrokeHud(frameBuffer: Buffer, keystrokes: KeystrokeEvent[], frameTimestamp: number, config: KeystrokeConfig, frameWidth: number, frameHeight: number, dpr?: number): Promise<Buffer>;
2005
2023
 
2006
2024
  /**
2007
2025
  * Apply a crossfade transition between two frame buffers.