@lumy-pack/scene-sieve 0.1.0 → 0.2.1

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.
Files changed (62) hide show
  1. package/README.md +128 -42
  2. package/dist/{commands → cli/commands}/Sieve.d.ts +5 -0
  3. package/dist/{errors.d.ts → cli/errors/classify-error.d.ts} +5 -0
  4. package/dist/cli/index.d.ts +3 -0
  5. package/dist/{utils → cli/options}/parse-options.d.ts +11 -2
  6. package/dist/cli.mjs +1453 -505
  7. package/dist/constants/package-version.d.ts +2 -0
  8. package/dist/constants/pipeline-defaults.d.ts +33 -0
  9. package/dist/core/{analyzer.d.ts → analyzer/analyzer.d.ts} +11 -6
  10. package/dist/core/{dbscan.d.ts → analyzer/clustering/dbscan.d.ts} +1 -1
  11. package/dist/core/analyzer/constants/vision-tuning.d.ts +12 -0
  12. package/dist/core/analyzer/features/feature-diff.d.ts +14 -0
  13. package/dist/core/analyzer/features/frame-features.d.ts +32 -0
  14. package/dist/core/analyzer/index.d.ts +3 -0
  15. package/dist/core/constants/workspace-layout.d.ts +9 -0
  16. package/dist/core/{extractor.d.ts → extractor/extractor.d.ts} +6 -4
  17. package/dist/core/extractor/index.d.ts +1 -0
  18. package/dist/core/index.d.ts +9 -9
  19. package/dist/core/input-resolver/index.d.ts +1 -0
  20. package/dist/core/{input-resolver.d.ts → input-resolver/input-resolver.d.ts} +11 -1
  21. package/dist/core/input-resolver/validation/validate-options.d.ts +8 -0
  22. package/dist/core/orchestrator/index.d.ts +3 -0
  23. package/dist/core/orchestrator/orchestrator.d.ts +8 -0
  24. package/dist/core/{run-in-worker.d.ts → orchestrator/worker/run-in-worker.d.ts} +5 -1
  25. package/dist/core/pruner/index.d.ts +1 -0
  26. package/dist/core/{pruner.d.ts → pruner/pruner.d.ts} +2 -2
  27. package/dist/{utils/math.d.ts → core/pruner/scoring/normalize-scores.d.ts} +4 -0
  28. package/dist/core/segmenter/index.d.ts +1 -0
  29. package/dist/core/{segmenter.d.ts → segmenter/segmenter.d.ts} +11 -11
  30. package/dist/core/utils/metadata/build-edge-metadata.d.ts +11 -0
  31. package/dist/core/utils/metadata/build-frame-metadata.d.ts +20 -0
  32. package/dist/core/utils/metadata/build-sieve-metadata.d.ts +14 -0
  33. package/dist/core/utils/metadata/build-tool-metadata.d.ts +8 -0
  34. package/dist/core/utils/metadata/build-video-metadata.d.ts +14 -0
  35. package/dist/core/utils/metadata/change/build-frame-change.d.ts +20 -0
  36. package/dist/core/utils/metadata/change/select-regions.d.ts +8 -0
  37. package/dist/core/utils/metadata/change/union-area/y-coverage-tree.d.ts +26 -0
  38. package/dist/core/utils/metadata/change/union-area.d.ts +7 -0
  39. package/dist/core/utils/metadata/scale-bounding-box.d.ts +11 -0
  40. package/dist/core/utils/output/finalize-selection.d.ts +15 -0
  41. package/dist/core/utils/sheet/build-tile-label-svg.d.ts +8 -0
  42. package/dist/core/utils/sheet/format-tile-label.d.ts +7 -0
  43. package/dist/core/utils/sheet/render-contact-sheet.d.ts +19 -0
  44. package/dist/core/utils/sheet/sample-tile-frames.d.ts +10 -0
  45. package/dist/core/workspace/index.d.ts +1 -0
  46. package/dist/core/{workspace.d.ts → workspace/workspace.d.ts} +11 -2
  47. package/dist/index.cjs +1531 -559
  48. package/dist/index.d.ts +2 -2
  49. package/dist/index.mjs +1533 -558
  50. package/dist/pipeline-worker.mjs +1213 -404
  51. package/dist/types/index.d.ts +173 -0
  52. package/package.json +14 -11
  53. package/dist/constants.d.ts +0 -32
  54. package/dist/core/orchestrator.d.ts +0 -2
  55. /package/dist/{utils → cli/commands}/command-registry.d.ts +0 -0
  56. /package/dist/{components → cli/components}/PhaseStep.d.ts +0 -0
  57. /package/dist/{components → cli/components}/ProgressBar.d.ts +0 -0
  58. /package/dist/core/{pipeline-worker.d.ts → orchestrator/worker/pipeline-worker.d.ts} +0 -0
  59. /package/dist/{utils → core/pruner/heap}/min-heap.d.ts +0 -0
  60. /package/dist/{utils → core/segmenter/scheduling}/concurrency.d.ts +0 -0
  61. /package/dist/{utils → core/utils/filesystem}/paths.d.ts +0 -0
  62. /package/dist/{utils → logging}/logger.d.ts +0 -0
@@ -0,0 +1,2 @@
1
+ /** Runtime manifest version shared by CLI responses and metadata documents. */
2
+ export declare const PACKAGE_VERSION: string;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Default values for scene-sieve pipeline options (frame count, threshold, extraction, segmentation).
3
+ */
4
+ export declare const DEFAULT_COUNT = 20;
5
+ export declare const DEFAULT_THRESHOLD = 0.5;
6
+ export declare const DEFAULT_FPS = 5;
7
+ export declare const DEFAULT_SCALE = 720;
8
+ export declare const DEFAULT_QUALITY = 80;
9
+ export declare const DEFAULT_MAX_FRAMES = 300;
10
+ export declare const DEFAULT_MAX_SEGMENT_DURATION = 300;
11
+ export declare const DEFAULT_SEGMENT_CONCURRENCY = 2;
12
+ export declare const IOU_THRESHOLD = 0.9;
13
+ export declare const ANIMATION_FRAME_THRESHOLD = 5;
14
+ /** Default maximum contact sheet columns. */
15
+ export declare const DEFAULT_SHEET_COLUMNS = 4;
16
+ /** Default contact sheet tile width in pixels. */
17
+ export declare const DEFAULT_SHEET_TILE_WIDTH = 320;
18
+ /** Default maximum contact sheet tiles. */
19
+ export declare const DEFAULT_SHEET_MAX_TILES = 40;
20
+ /** Enable timestamp labels on contact sheet tiles by default. */
21
+ export declare const DEFAULT_SHEET_LABEL = true;
22
+ /** White contact sheet margin and gap in pixels. */
23
+ export declare const SHEET_TILE_GAP = 4;
24
+ /** Tile-height fraction used for label font size. */
25
+ export declare const SHEET_LABEL_HEIGHT_RATIO = 0.07;
26
+ /** Maximum distinct regions retained per selected-frame span. */
27
+ export declare const CHANGE_REGION_LIMIT = 5;
28
+ /** Metadata schema discriminator. */
29
+ export declare const METADATA_VERSION = 2;
30
+ /** Fixed contact sheet output name. */
31
+ export declare const SHEET_FILE_NAME = "sheet.jpg";
32
+ /** Fixed metadata document output name. */
33
+ export declare const METADATA_FILE_NAME = ".metadata.json";
@@ -1,5 +1,5 @@
1
- import type { AnalysisResult, AnimationMetadata, BoundingBox, ProcessContext } from '../types/index.js';
2
- import type { Point2D } from './dbscan.js';
1
+ import type { AnalysisResult, AnimationMetadata, BoundingBox, ProcessContext } from '../../types/index.js';
2
+ import type { Point2D } from './clustering/dbscan.js';
3
3
  type CvLib = typeof import('@techstark/opencv-js');
4
4
  export declare function preprocessFrame(framePath: string, scale: number): Promise<{
5
5
  data: Uint8Array;
@@ -19,10 +19,6 @@ export declare class IoUTracker {
19
19
  flushAndGetAnimations(): AnimationMetadata[];
20
20
  getAnimationWeight(boxIndex: number, boxes: BoundingBox[]): number;
21
21
  }
22
- export interface AKAZEResult {
23
- sNew: Point2D[];
24
- sLoss: Point2D[];
25
- }
26
22
  /**
27
23
  * Pixel-level difference fallback for AKAZE blind spots.
28
24
  *
@@ -37,6 +33,12 @@ export interface AKAZEResult {
37
33
  * 3. threshold → binary mask of significant changes
38
34
  * 4. findContours → bounding rects of changed regions
39
35
  * 5. Grid sampling within each bounding rect → Point2D[]
36
+ *
37
+ * @param cvLib - Initialized OpenCV runtime shared by the analyzer.
38
+ * @param frame1 - Previous grayscale frame, with the same dimensions as frame2.
39
+ * @param frame2 - Next grayscale frame, with the same dimensions as frame1.
40
+ * @returns Grid-sampled points from changed regions.
41
+ * @throws Propagates allocation or OpenCV errors after releasing acquired handles.
40
42
  */
41
43
  export declare function computePixelDiff(cvLib: CvLib, frame1: {
42
44
  data: Uint8Array;
@@ -57,6 +59,9 @@ export declare function computeInformationGain(clusters: BoundingBox[], clusterP
57
59
  * 2. DBSCAN Spatial Clustering
58
60
  * 3. Spatio-temporal IoU Tracking
59
61
  * 4. G(t) Information Gain Scoring
62
+ * @param ctx - Frames, analysis options, and the progress callback for this run.
63
+ * @returns Adjacent scores and tracked animations in analysis coordinates.
64
+ * @throws Propagates runtime errors and rejects total failure of two or more pairs after cleanup.
60
65
  */
61
66
  export declare function analyzeFrames(ctx: ProcessContext): Promise<AnalysisResult>;
62
67
  export {};
@@ -1,4 +1,4 @@
1
- import type { DBSCANResult } from '../types/index.js';
1
+ import type { DBSCANResult } from '../../../types/index.js';
2
2
  export interface Point2D {
3
3
  x: number;
4
4
  y: number;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Tuning constants for the OpenCV-based vision analysis pipeline (DBSCAN, feature matching, pixel-diff fallback).
3
+ */
4
+ export declare const OPENCV_BATCH_SIZE = 10;
5
+ export declare const DBSCAN_ALPHA = 0.03;
6
+ export declare const DBSCAN_MIN_PTS = 4;
7
+ export declare const DECAY_LAMBDA = 0.95;
8
+ export declare const MATCH_DISTANCE_THRESHOLD = 0.25;
9
+ export declare const PIXELDIFF_GAUSSIAN_KERNEL = 3;
10
+ export declare const PIXELDIFF_BINARY_THRESHOLD = 30;
11
+ export declare const PIXELDIFF_CONTOUR_MIN_AREA = 100;
12
+ export declare const PIXELDIFF_SAMPLE_SPACING = 8;
@@ -0,0 +1,14 @@
1
+ import type { Point2D } from '../clustering/dbscan.js';
2
+ import type { FrameFeatures } from './frame-features.js';
3
+ /** Initialized OpenCV runtime supplied by the analyzer. */
4
+ type CvLib = typeof import('@techstark/opencv-js');
5
+ /**
6
+ * Match prev to next with Hamming k=2, crossCheck=false and strict ratio 0.25.
7
+ * @param cvLib - Initialized OpenCV runtime.
8
+ * @param prev - Previous frame's live features, owned by the caller.
9
+ * @param next - Next frame's live features, owned by the caller.
10
+ * @returns Unmatched next-frame coordinates without changing input ownership.
11
+ * @throws Propagates matching errors after releasing temporary native handles.
12
+ */
13
+ export declare function computeNewPoints(cvLib: CvLib, prev: FrameFeatures, next: FrameFeatures): Point2D[];
14
+ export {};
@@ -0,0 +1,32 @@
1
+ import type { AKAZE, KeyPointVector, Mat } from '@techstark/opencv-js';
2
+ /** Initialized OpenCV runtime supplied by the analyzer. */
3
+ type CvLib = typeof import('@techstark/opencv-js');
4
+ /** Grayscale bytes whose length matches width times height. */
5
+ type PreprocessedFrame = {
6
+ data: Uint8Array;
7
+ width: number;
8
+ height: number;
9
+ };
10
+ /** Caller-owned AKAZE features for one frame; delete releases both handles once. */
11
+ export interface FrameFeatures {
12
+ /** Width of the analyzed grayscale image. */
13
+ readonly width: number;
14
+ /** Height of the analyzed grayscale image. */
15
+ readonly height: number;
16
+ /** Keypoints in descriptor row order. */
17
+ readonly keypoints: KeyPointVector;
18
+ /** Descriptor rows equal keypoints.size(). */
19
+ readonly descriptors: Mat;
20
+ /** Release both native handles; repeated calls have no effect. */
21
+ delete(): void;
22
+ }
23
+ /**
24
+ * Detect one frame's features without retaining its image or mask.
25
+ * @param cvLib - Initialized OpenCV runtime.
26
+ * @param akaze - Detector owned and released by the caller.
27
+ * @param frame - Grayscale bytes with matching width and height.
28
+ * @returns Feature handles that the caller must delete.
29
+ * @throws Propagates native errors after releasing partial allocations.
30
+ */
31
+ export declare function computeFrameFeatures(cvLib: CvLib, akaze: AKAZE, frame: PreprocessedFrame): FrameFeatures;
32
+ export {};
@@ -0,0 +1,3 @@
1
+ export { analyzeFrames, computeIoU, computeInformationGain } from './analyzer.js';
2
+ export { dbscan } from './clustering/dbscan.js';
3
+ export type { Point2D } from './clustering/dbscan.js';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Temp workspace naming and frame file layout for pipeline runs.
3
+ */
4
+ export declare const APP_NAME = "scene-sieve";
5
+ export declare const WORKSPACE_PREFIX = "scene-sieve-";
6
+ export declare const TEMP_BASE_DIR: string;
7
+ export declare const FRAME_OUTPUT_EXTENSION = ".jpg";
8
+ export declare const FRAME_FILENAME_PATTERN = "frame_%06d.jpg";
9
+ export declare function getTempWorkspaceDir(sessionId: string): string;
@@ -1,4 +1,4 @@
1
- import type { FrameNode, ProcessContext } from '../types/index.js';
1
+ import type { FrameNode, ProcessContext } from '../../types/index.js';
2
2
  export interface FFprobeMetadata {
3
3
  format?: {
4
4
  format_name?: string;
@@ -10,8 +10,9 @@ export interface FFprobeMetadata {
10
10
  }
11
11
  /**
12
12
  * Extract frames from video/GIF using FFmpeg.
13
- * Always uses FPS-based extraction. For long videos, FPS is automatically
14
- * reduced to stay within maxFrames budget.
13
+ * @param ctx Pipeline context; records effectiveFps and sourceDurationSec for video input.
14
+ * @returns Extracted candidates, or the unchanged input array in frames mode.
15
+ * @throws When the input is missing, metadata has no video stream, or FFmpeg fails.
15
16
  */
16
17
  export declare function extractFrames(ctx: ProcessContext): Promise<FrameNode[]>;
17
18
  export declare function getVideoMetadata(inputPath: string): Promise<FFprobeMetadata>;
@@ -25,6 +26,7 @@ export declare function getVideoMetadata(inputPath: string): Promise<FFprobeMeta
25
26
  * @param scale - Height scale for vision analysis
26
27
  * @param startTime - Start time in seconds
27
28
  * @param duration - Duration in seconds to extract
29
+ * @param frameLimit - Positive output limit; defaults to the range's grid capacity
28
30
  * @returns Array of FrameNode with segment-local timestamps (starting from 0)
29
31
  */
30
- export declare function extractFramesForRange(inputPath: string, outputDir: string, fps: number, scale: number, startTime: number, duration: number): Promise<FrameNode[]>;
32
+ export declare function extractFramesForRange(inputPath: string, outputDir: string, fps: number, scale: number, startTime: number, duration: number, frameLimit?: number): Promise<FrameNode[]>;
@@ -0,0 +1 @@
1
+ export { extractFrames, extractFramesForRange, getVideoMetadata } from './extractor.js';
@@ -1,9 +1,9 @@
1
- export { runPipeline } from './orchestrator.js';
2
- export { analyzeFrames, computeIoU, computeInformationGain, } from './analyzer.js';
3
- export { extractFrames } from './extractor.js';
4
- export { pruneTo, pruneByThreshold, pruneByThresholdWithCap, suppressConsecutiveRuns, } from './pruner.js';
5
- export { dbscan } from './dbscan.js';
6
- export type { Point2D } from './dbscan.js';
7
- export { resolveInput, resolveOptions } from './input-resolver.js';
8
- export { shouldSegment, computeSegmentPlan, processSegment, mergeSegmentFrames, runSegmentedPipeline, } from './segmenter.js';
9
- export { createWorkspace, createSegmentWorkspace, cleanupWorkspace, finalizeOutput, readFramesAsBuffers, writeInputBuffer, writeInputFrames, } from './workspace.js';
1
+ export { runPipeline, runPipelineInWorker } from './orchestrator/index.js';
2
+ export type { AnimationMetadata, VideoMetadata, FrameMetadata, FrameChange, ToolMetadata, ToolParams, SheetMetadata, SheetOptions, SieveMetadata, EdgeMetadata, EdgeChange, } from '../types/index.js';
3
+ export { analyzeFrames, computeIoU, computeInformationGain, dbscan, } from './analyzer/index.js';
4
+ export type { Point2D } from './analyzer/index.js';
5
+ export { extractFrames } from './extractor/index.js';
6
+ export { pruneTo, pruneByThreshold, pruneByThresholdWithCap, suppressConsecutiveRuns, } from './pruner/index.js';
7
+ export { resolveInput, resolveOptions } from './input-resolver/index.js';
8
+ export { shouldSegment, computeSegmentPlan, processSegment, mergeSegmentFrames, runSegmentedPipeline, } from './segmenter/index.js';
9
+ export { createWorkspace, createSegmentWorkspace, cleanupWorkspace, cleanupStaleWorkspaces, finalizeOutput, readFramesAsBuffers, writeInputBuffer, writeInputFrames, } from './workspace/index.js';
@@ -0,0 +1 @@
1
+ export { resolveInput, resolveOptions } from './input-resolver.js';
@@ -1,4 +1,10 @@
1
- import type { FrameNode, ResolvedOptions, SieveOptions } from '../types/index.js';
1
+ import type { FrameNode, ResolvedOptions, SieveOptions } from '../../types/index.js';
2
+ /**
3
+ * Validate supplied options and resolve defaults and paths for the pipeline.
4
+ * @param options - Mode-specific input and optional numeric settings.
5
+ * @returns Complete pipeline settings with absolute file input paths.
6
+ * @throws An input error if a supplied numeric setting is invalid.
7
+ */
2
8
  export declare function resolveOptions(options: SieveOptions): ResolvedOptions;
3
9
  /**
4
10
  * Resolve the input source to a list of FrameNode[].
@@ -6,6 +12,10 @@ export declare function resolveOptions(options: SieveOptions): ResolvedOptions;
6
12
  * - 'file' mode: validate file exists and delegate to extractor (caller's responsibility)
7
13
  * - 'buffer' mode: write buffer as temp video file, return path via FrameNode trick (empty list)
8
14
  * - 'frames' mode: write frame buffers as JPGs, return FrameNode[]
15
+ * @param options - Input source; encoded frames must have matching dimensions.
16
+ * @param workspacePath - Workspace receiving temporary input files.
17
+ * @returns Frame nodes or a resolved video path for extraction.
18
+ * @throws Propagates metadata or write errors and rejects mismatched frame sizes.
9
19
  */
10
20
  export declare function resolveInput(options: SieveOptions, workspacePath: string): Promise<{
11
21
  frames: FrameNode[];
@@ -0,0 +1,8 @@
1
+ import type { SieveOptions } from '../../../types/index.js';
2
+ /**
3
+ * Reject invalid numeric options before defaults or pipeline effects are applied.
4
+ * @param options - Supplied options; omitted numeric fields use pipeline defaults.
5
+ * @returns Nothing when all supplied numeric fields satisfy their contracts.
6
+ * @throws An input error naming the invalid option and its received value.
7
+ */
8
+ export declare function validateOptions(options: SieveOptions): void;
@@ -0,0 +1,3 @@
1
+ export { runPipeline } from './orchestrator.js';
2
+ export { runPipelineInWorker } from './worker/run-in-worker.js';
3
+ export type { SieveWorkerOptions } from './worker/run-in-worker.js';
@@ -0,0 +1,8 @@
1
+ import type { SieveOptions, SieveResult } from '../../types/index.js';
2
+ /**
3
+ * Run the five pipeline stages, delegating segmented inputs to the segmenter.
4
+ * @param options - Mode-specific input and optional pipeline settings.
5
+ * @returns Selected outputs with v2 frame metadata and zero-based API animations.
6
+ * @throws Propagates stage failures after cleaning the workspace unless debug is enabled.
7
+ */
8
+ export declare function runPipeline(options: SieveOptions): Promise<SieveResult>;
@@ -1,9 +1,13 @@
1
- import type { ProgressPhase, SieveInput, SieveOptionsBase, SieveResult } from '../types/index.js';
1
+ import type { ProgressPhase, SieveInput, SieveOptionsBase, SieveResult } from '../../../types/index.js';
2
2
  export type SieveWorkerOptions = Omit<SieveOptionsBase, 'onProgress'> & SieveInput;
3
3
  /**
4
4
  * Run the pipeline, choosing the best execution strategy:
5
5
  *
6
6
  * - Production (bundled .mjs): Worker thread — spinner never freezes
7
7
  * - Dev mode (tsx .ts): Main thread — simpler, spinner may stutter during CPU work
8
+ * @param options - Serializable input and pipeline settings for this run.
9
+ * @param onProgress - Receives worker progress updates.
10
+ * @returns The pipeline result; settlement is unchanged by later exit events.
11
+ * @throws Rejects worker errors or any worker exit before a result is received.
8
12
  */
9
13
  export declare function runPipelineInWorker(options: SieveWorkerOptions, onProgress: (phase: ProgressPhase, percent: number) => void): Promise<SieveResult>;
@@ -0,0 +1 @@
1
+ export { pruneTo, pruneByThreshold, pruneByThresholdWithCap, suppressConsecutiveRuns, } from './pruner.js';
@@ -1,4 +1,4 @@
1
- import type { FrameNode, ScoreEdge } from '../types/index.js';
1
+ import type { FrameNode, ScoreEdge } from '../../types/index.js';
2
2
  /**
3
3
  * Edge-aware greedy merge with re-linking — O(N log N).
4
4
  *
@@ -35,7 +35,7 @@ export declare function pruneTo(graph: ScoreEdge[], frames: FrameNode[], targetC
35
35
  */
36
36
  export declare function suppressConsecutiveRuns(graph: ScoreEdge[], passingIndices: number[], normalizedScores: number[]): Set<number>;
37
37
  /**
38
- * Threshold-based pruning with NMS -- O(N).
38
+ * Threshold-based pruning with NMS -- including normalization, O(N log N).
39
39
  *
40
40
  * 1. Scores are normalized to [0, 1] via percentile normalization.
41
41
  * 2. Edges with normalized score >= threshold are collected.
@@ -1,3 +1,7 @@
1
+ export declare const NORMALIZATION_LOGISTIC_K = 3;
2
+ export declare const NORMALIZATION_ALPHA = 0.4;
3
+ export declare const NORMALIZATION_MAD_COEFFICIENT = 1.4826;
4
+ export declare const NORMALIZATION_MIN_SAMPLE_SIZE = 10;
1
5
  /**
2
6
  * Interface for objects that have a numeric score.
3
7
  */
@@ -0,0 +1 @@
1
+ export { shouldSegment, computeSegmentPlan, processSegment, mergeSegmentFrames, runSegmentedPipeline, } from './segmenter.js';
@@ -1,4 +1,4 @@
1
- import type { AnimationMetadata, FrameNode, ResolvedOptions, ScoreEdge, SegmentPlan, SegmentResult, SieveOptions, SieveResult } from '../types/index.js';
1
+ import type { AnimationMetadata, FrameNode, ResolvedOptions, ScoreEdge, SegmentPlan, SegmentResult, SieveOptions, SieveResult } from '../../types/index.js';
2
2
  /**
3
3
  * Determine whether segmentation should be used.
4
4
  * Returns false for frames mode and GIF files.
@@ -6,25 +6,25 @@ import type { AnimationMetadata, FrameNode, ResolvedOptions, ScoreEdge, SegmentP
6
6
  */
7
7
  export declare function shouldSegment(resolvedOptions: ResolvedOptions, originalOptions: SieveOptions): boolean;
8
8
  /**
9
- * Compute segment boundaries with overlap, frame allocation, and effectiveFps.
10
- * Pure function — no I/O.
11
- *
12
- * - effectiveFps is uniform across all segments
13
- * - Overlap: 1 frame at each internal boundary
14
- * - allocatedFrames total <= maxFrames (last segment adjusted if needed)
9
+ * Partition the global extraction grid into nonempty logical segments.
10
+ * @param totalDuration Positive source duration in seconds.
11
+ * @param maxSegmentDuration Positive logical segment width in seconds.
12
+ * @param maxFrames Candidate budget, defensively raised to at least two.
13
+ * @param fps Positive requested sampling frequency.
14
+ * @returns Contiguous plan indices with grid-aligned seeks and overlap-inclusive limits.
15
15
  */
16
16
  export declare function computeSegmentPlan(totalDuration: number, maxSegmentDuration: number, maxFrames: number, fps: number): SegmentPlan[];
17
17
  /**
18
18
  * Merge multiple segment results into a single unified frame/edge/animation set.
19
- * - Timestamps adjusted using extractStartTime (Section 18 note 1)
20
- * - Overlap frames deduplicated by threshold 1/(effectiveFps*2) (Section 18 note 5)
21
- * - Global IDs reassigned after dedup
22
- * - Duplicate edges keep higher score
19
+ * @param segmentResults Local frames, edges and tracker entries with distinct segment indices.
20
+ * @returns Global timestamp-ordered frames, aliased edges and animations without self loops.
21
+ * Duplicate edges keep the higher score; duplicate animations keep the first tracker entry.
23
22
  */
24
23
  export declare function mergeSegmentFrames(segmentResults: SegmentResult[]): {
25
24
  frames: FrameNode[];
26
25
  edges: ScoreEdge[];
27
26
  animations: AnimationMetadata[];
27
+ analysisResolution: SegmentResult['analysisResolution'];
28
28
  };
29
29
  /**
30
30
  * Extract frames for a single segment and analyze them.
@@ -0,0 +1,11 @@
1
+ import type { EdgeMetadata, ScoreEdge } from '../../../types/index.js';
2
+ /**
3
+ * Serialize raw candidate edges in graph order.
4
+ * @param graph - Adjacent-pair edges, optionally carrying tracker partitions.
5
+ * @param analysisResolution - Analysis dimensions used for both area fractions.
6
+ * @returns One-based IDs with six-decimal scores and four-decimal clamped ratios.
7
+ */
8
+ export declare function buildEdgeMetadata(graph: ScoreEdge[], analysisResolution: {
9
+ width: number;
10
+ height: number;
11
+ }): EdgeMetadata[];
@@ -0,0 +1,20 @@
1
+ import type { FrameMetadata, FrameNode, ScoreEdge } from '../../../types/index.js';
2
+ /**
3
+ * Describe selected frames using candidate adjacency rather than synthetic pruning edges.
4
+ * @param input - Chronological candidates and selections, raw graph and output dimensions.
5
+ * @returns One-based frame summaries with rounded timestamps and nonnegative holds.
6
+ */
7
+ export declare function buildFrameMetadata(input: {
8
+ frames: FrameNode[];
9
+ graph: ScoreEdge[];
10
+ selected: FrameNode[];
11
+ originalDurationMs: number;
12
+ analysisResolution: {
13
+ width: number;
14
+ height: number;
15
+ };
16
+ outputResolution: {
17
+ width: number;
18
+ height: number;
19
+ };
20
+ }): FrameMetadata[];
@@ -0,0 +1,14 @@
1
+ import type { AnimationMetadata, FrameNode, ProcessContext, SheetMetadata, SieveMetadata, VideoMetadata } from '../../../types/index.js';
2
+ /**
3
+ * Assemble the complete v2 document without I/O or mutation.
4
+ * @param input - Pipeline state, selections, output-space video and zero-based animations.
5
+ * @returns Contract-ordered metadata, omitting unrequested optional keys entirely.
6
+ */
7
+ export declare function buildSieveMetadata(input: {
8
+ ctx: ProcessContext;
9
+ selected: FrameNode[];
10
+ video: VideoMetadata;
11
+ animations: AnimationMetadata[];
12
+ version: string;
13
+ sheet?: SheetMetadata;
14
+ }): SieveMetadata;
@@ -0,0 +1,8 @@
1
+ import type { ResolvedOptions, ToolMetadata } from '../../../types/index.js';
2
+ /**
3
+ * Record the tool and the nine selection and encoding settings in contract order.
4
+ * @param options - Validated pipeline settings; operational options are excluded.
5
+ * @param version - Runtime package version supplied by the I/O boundary.
6
+ * @returns Deterministic tool provenance without paths or execution details.
7
+ */
8
+ export declare function buildToolMetadata(options: ResolvedOptions, version: string): ToolMetadata;
@@ -0,0 +1,14 @@
1
+ import type { AnimationMetadata, FrameNode, ProcessContext, VideoMetadata } from '../../../types/index.js';
2
+ /**
3
+ * Read output dimensions and build consistent video and animation metadata.
4
+ * JPEG finalization does not resize, so the source dimensions match the output.
5
+ * @param ctx Pipeline state with source duration, effective FPS and analysis-space animations.
6
+ * @param selected Selected frames in output order; the first candidate is the fallback.
7
+ * @param analysisResolution Analysis dimensions; absent or zero dimensions imply no scaling.
8
+ * @returns Video metadata and new output-space animations, retaining zero-based frame IDs.
9
+ * @throws If sharp cannot read the selected or fallback image. Empty input performs no image I/O.
10
+ */
11
+ export declare function buildVideoMetadata(ctx: ProcessContext, selected: FrameNode[], analysisResolution: ProcessContext['analysisResolution']): Promise<{
12
+ video: VideoMetadata;
13
+ animations: AnimationMetadata[];
14
+ }>;
@@ -0,0 +1,20 @@
1
+ import type { FrameChange, ScoreEdge } from '../../../../types/index.js';
2
+ /**
3
+ * Aggregate adjacent-pair evidence across one selected-frame span.
4
+ * @param input - Ordered raw edges, one-based previous ID, skipped count and dimensions.
5
+ * @returns Rounded raw scores, analysis-space union ratio and output-space regions.
6
+ */
7
+ export declare function buildFrameChange(input: {
8
+ spanEdges: ScoreEdge[];
9
+ fromFrameId: number;
10
+ skippedCandidates: number;
11
+ analysisResolution: {
12
+ width: number;
13
+ height: number;
14
+ };
15
+ outputResolution: {
16
+ width: number;
17
+ height: number;
18
+ };
19
+ regionLimit: number;
20
+ }): FrameChange;
@@ -0,0 +1,8 @@
1
+ import type { BoundingBox } from '../../../../types/index.js';
2
+ /**
3
+ * Select distinct positive-area boxes with deterministic area and coordinate ties.
4
+ * @param boxes - Already scaled output rectangles; the input is not mutated.
5
+ * @param limit - Nonnegative maximum number of regions.
6
+ * @returns Largest boxes ordered by area descending, then y, x and width ascending.
7
+ */
8
+ export declare function selectRegions(boxes: BoundingBox[], limit: number): BoundingBox[];
@@ -0,0 +1,26 @@
1
+ /** Internal sweep helper retaining cover counts and lengths between sorted y bounds. */
2
+ export declare class YCoverageTree {
3
+ private readonly bounds;
4
+ /** Number of whole-node covering intervals, independent of descendants. */
5
+ private readonly counts;
6
+ /** Covered geometric length for each node, including partially covered children. */
7
+ private readonly lengths;
8
+ /**
9
+ * Allocate linear storage for the elementary intervals between coordinates.
10
+ * @param bounds - At least two sorted unique finite y endpoints.
11
+ */
12
+ constructor(bounds: number[]);
13
+ /** Total active covered y length, in the input coordinate system. */
14
+ get coveredLength(): number;
15
+ /**
16
+ * Adjust a nonempty half-open interval and refresh its ancestors' lengths.
17
+ * @param start - Inclusive endpoint index; 0 <= start < end.
18
+ * @param end - Exclusive endpoint index; end < bounds.length.
19
+ * @param delta - One on entry, minus one for the matching departure.
20
+ * @param node - Internal tree slot; callers use the root default.
21
+ * @param left - Inclusive endpoint index of this node.
22
+ * @param right - Exclusive endpoint index of this node.
23
+ * @returns Nothing; mutates this tree's coverage in O(log n).
24
+ */
25
+ update(start: number, end: number, delta: number, node?: number, left?: number, right?: number): void;
26
+ }
@@ -0,0 +1,7 @@
1
+ import type { BoundingBox } from '../../../../types/index.js';
2
+ /**
3
+ * Measure rectangle union with an x sweep in O(n log n) time and O(n) space.
4
+ * @param boxes - Finite rectangles; nonpositive dimensions are ignored.
5
+ * @returns Covered area in the input coordinate system, or zero for empty input.
6
+ */
7
+ export declare function unionArea(boxes: BoundingBox[]): number;
@@ -0,0 +1,11 @@
1
+ import type { BoundingBox } from '../../../types/index.js';
2
+ /**
3
+ * Convert an analysis box to clamped integer output pixels.
4
+ * @param box - Analysis-space rectangle; the input remains unchanged.
5
+ * @param sx - Horizontal output-to-analysis scale.
6
+ * @param sy - Vertical output-to-analysis scale.
7
+ * @param width - Nonnegative output image width.
8
+ * @param height - Nonnegative output image height.
9
+ * @returns A rectangle contained within the output dimensions.
10
+ */
11
+ export declare function scaleBoundingBox(box: BoundingBox, sx: number, sy: number, width: number, height: number): BoundingBox;
@@ -0,0 +1,15 @@
1
+ import type { AnimationMetadata, FrameNode, ProcessContext, SieveMetadata } from '../../../types/index.js';
2
+ /**
3
+ * Read output dimensions once, render optional sheets and finalize the shared v2 document.
4
+ * @param ctx - Pipeline state owned by the orchestrator; this function does not mutate it.
5
+ * @param selected - Selected frames in temporal order.
6
+ * @returns Mode-specific output, the document and zero-based API animations.
7
+ * @throws Propagates image, rendering and output I/O errors to the orchestrator.
8
+ */
9
+ export declare function finalizeSelection(ctx: ProcessContext, selected: FrameNode[]): Promise<{
10
+ outputFiles: string[];
11
+ outputBuffers?: Buffer[];
12
+ document: SieveMetadata;
13
+ animations: AnimationMetadata[];
14
+ sheetBuffer?: Buffer;
15
+ }>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Build a tile-sized SVG overlay with a translucent badge and an explicit text baseline.
3
+ * @param text - A formatTileLabel result containing only digits, #, spaces, colons and periods.
4
+ * @param tileWidth - Positive tile canvas width in pixels.
5
+ * @param tileHeight - Positive tile canvas height in pixels.
6
+ * @returns Encoded SVG bytes for a top-left sharp composite overlay.
7
+ */
8
+ export declare function buildTileLabelSvg(text: string, tileWidth: number, tileHeight: number): Buffer;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Format a contact sheet label without rounding into the next tenth of a second.
3
+ * @param frameId - One-based candidate frame ID.
4
+ * @param timestampMs - Nonnegative candidate time in milliseconds.
5
+ * @returns A label in the form "#<id> mm:ss.s", allowing minutes beyond two digits.
6
+ */
7
+ export declare function formatTileLabel(frameId: number, timestampMs: number): string;
@@ -0,0 +1,19 @@
1
+ import type { FrameNode, SheetMetadata, SheetOptions } from '../../../types/index.js';
2
+ /**
3
+ * Read selected frame images and render a row-major contact sheet.
4
+ * @param input - Nonempty ordered selections, positive dimensions and validated sheet settings.
5
+ * @returns JPEG bytes and the effective tile layout with one-based frame IDs.
6
+ * @throws Propagates sharp image reading, compositing or encoding errors.
7
+ */
8
+ export declare function renderContactSheet(input: {
9
+ selected: FrameNode[];
10
+ resolution: {
11
+ width: number;
12
+ height: number;
13
+ };
14
+ options: Required<SheetOptions>;
15
+ quality: number;
16
+ }): Promise<{
17
+ buffer: Buffer;
18
+ metadata: SheetMetadata;
19
+ }>;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Sample a sequence uniformly while always retaining both endpoints.
3
+ * @param items - Items in temporal order.
4
+ * @param maxTiles - Validated integer limit of at least two.
5
+ * @returns The original sequence when within the limit, otherwise evenly sampled items.
6
+ */
7
+ export declare function sampleTileFrames<T>(items: T[], maxTiles: number): {
8
+ items: T[];
9
+ sampled: boolean;
10
+ };
@@ -0,0 +1 @@
1
+ export { createWorkspace, createSegmentWorkspace, cleanupWorkspace, cleanupStaleWorkspaces, finalizeOutput, readFramesAsBuffers, writeInputBuffer, writeInputFrames, } from './workspace.js';
@@ -1,6 +1,15 @@
1
- import type { FrameNode, ProcessContext } from '../types/index.js';
1
+ import type { FrameNode, ProcessContext, SieveMetadata } from '../../types/index.js';
2
2
  export declare function createWorkspace(sessionId: string): Promise<string>;
3
- export declare function finalizeOutput(ctx: ProcessContext, selectedFrames: FrameNode[]): Promise<string[]>;
3
+ /**
4
+ * Write selected JPEGs and the supplied document before replacing the output directory.
5
+ * @param ctx - Workspace, quality and destination settings.
6
+ * @param selectedFrames - Frames paired by position with document.frames.
7
+ * @param document - Complete metadata, including the output file names.
8
+ * @param sheetBuffer - Optional JPEG contact sheet bytes to persist unchanged.
9
+ * @returns Selected JPEG paths, optional sheet path and finally the metadata path.
10
+ * @throws Rejects mismatched frame counts and propagates image or filesystem errors.
11
+ */
12
+ export declare function finalizeOutput(ctx: ProcessContext, selectedFrames: FrameNode[], document: SieveMetadata, sheetBuffer?: Buffer): Promise<string[]>;
4
13
  export declare function createSegmentWorkspace(parentWorkspacePath: string, segmentIndex: number): Promise<string>;
5
14
  export declare function cleanupWorkspace(workspacePath: string): Promise<void>;
6
15
  /**