@lumy-pack/scene-sieve 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -0
- package/dist/cli.mjs +708 -86
- package/dist/index.cjs +382 -4
- package/dist/index.mjs +382 -4
- package/dist/pipeline-worker.mjs +382 -4
- package/package.json +3 -2
- package/dist/cli.d.ts +0 -1
- package/dist/commands/Sieve.d.ts +0 -15
- package/dist/components/PhaseStep.d.ts +0 -14
- package/dist/components/ProgressBar.d.ts +0 -7
- package/dist/constants.d.ts +0 -30
- package/dist/core/analyzer.d.ts +0 -62
- package/dist/core/dbscan.d.ts +0 -10
- package/dist/core/extractor.d.ts +0 -7
- package/dist/core/index.d.ts +0 -8
- package/dist/core/input-resolver.d.ts +0 -13
- package/dist/core/orchestrator.d.ts +0 -2
- package/dist/core/pipeline-worker.d.ts +0 -1
- package/dist/core/pruner.d.ts +0 -61
- package/dist/core/run-in-worker.d.ts +0 -9
- package/dist/core/workspace.d.ts +0 -24
- package/dist/index.d.ts +0 -2
- package/dist/types/index.d.ts +0 -107
- package/dist/utils/logger.d.ts +0 -8
- package/dist/utils/math.d.ts +0 -27
- package/dist/utils/min-heap.d.ts +0 -16
- package/dist/utils/paths.d.ts +0 -18
package/dist/core/pruner.d.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import type { FrameNode, ScoreEdge } from '../types/index.js';
|
|
2
|
-
/**
|
|
3
|
-
* Edge-aware greedy merge with re-linking — O(N log N).
|
|
4
|
-
*
|
|
5
|
-
* 1. Build a doubly-linked list of frames
|
|
6
|
-
* 2. Insert all edges into a min-heap
|
|
7
|
-
* 3. Pop the lowest-score edge (most similar pair)
|
|
8
|
-
* 4. Remove the later frame (tgtId), re-link neighbors
|
|
9
|
-
* 5. Push synthetic edge with score = max(left, right)
|
|
10
|
-
* 6. Repeat until surviving count === targetCount
|
|
11
|
-
* 7. First and last frames are never removed (boundary preservation)
|
|
12
|
-
*
|
|
13
|
-
* Stale heap entries (involving removed frames) are lazily skipped on pop.
|
|
14
|
-
*/
|
|
15
|
-
export declare function pruneTo(graph: ScoreEdge[], frames: FrameNode[], targetCount: number): Set<number>;
|
|
16
|
-
/**
|
|
17
|
-
* Non-Maximum Suppression (NMS) for consecutive edge runs.
|
|
18
|
-
*
|
|
19
|
-
* Consecutive edges share overlapping frames (edge i: frame i->i+1,
|
|
20
|
-
* edge i+1: frame i+1->i+2), so consecutive passing edges indicate
|
|
21
|
-
* the same visual transition region. This function groups consecutive
|
|
22
|
-
* passing edge indices into "runs" and keeps all distinct peaks per run.
|
|
23
|
-
*
|
|
24
|
-
* Multi-peak detection: within each run, strict local maxima (score higher
|
|
25
|
-
* than both neighbors) are identified. Each local maximum represents a
|
|
26
|
-
* distinct visual transition. If no strict local maxima exist (plateau or
|
|
27
|
-
* monotonic sequence), the global peak of the run is selected as fallback.
|
|
28
|
-
*
|
|
29
|
-
* Single-element runs are unaffected (isolated transitions preserved).
|
|
30
|
-
*
|
|
31
|
-
* @param graph - full ScoreEdge array (for targetId lookup)
|
|
32
|
-
* @param passingIndices - edge indices that passed threshold filtering (sorted ascending)
|
|
33
|
-
* @param normalizedScores - normalized score array (same length as graph)
|
|
34
|
-
* @returns Set of targetIds to add to surviving set (one or more per run)
|
|
35
|
-
*/
|
|
36
|
-
export declare function suppressConsecutiveRuns(graph: ScoreEdge[], passingIndices: number[], normalizedScores: number[]): Set<number>;
|
|
37
|
-
/**
|
|
38
|
-
* Threshold-based pruning with NMS -- O(N).
|
|
39
|
-
*
|
|
40
|
-
* 1. Scores are normalized to [0, 1] via percentile normalization.
|
|
41
|
-
* 2. Edges with normalized score >= threshold are collected.
|
|
42
|
-
* 3. Non-Maximum Suppression groups consecutive passing edges and keeps
|
|
43
|
-
* only the peak per run, preventing near-duplicate frame selection
|
|
44
|
-
* from a single visual transition.
|
|
45
|
-
*
|
|
46
|
-
* First and last frames are always preserved (boundary protection).
|
|
47
|
-
*/
|
|
48
|
-
export declare function pruneByThreshold(graph: ScoreEdge[], frames: FrameNode[], threshold: number): Set<number>;
|
|
49
|
-
/**
|
|
50
|
-
* Combined threshold + count pruning -- 2-stage pipeline.
|
|
51
|
-
*
|
|
52
|
-
* Stage 1: pruneByThreshold -- keep all frames with normalized score >= threshold
|
|
53
|
-
* Stage 2: if result exceeds maxCount, rebuild subgraph with synthetic edges
|
|
54
|
-
* (min-score over each gap) and apply pruneTo on the surviving subset
|
|
55
|
-
*
|
|
56
|
-
* Edge reconstruction: for consecutive survivors A, B with removed frames
|
|
57
|
-
* [x1, x2, ...] between them, the synthetic edge score is:
|
|
58
|
-
* min(score(A->x1), score(x1->x2), ..., score(xN->B))
|
|
59
|
-
* This preserves the "weakest link" semantics.
|
|
60
|
-
*/
|
|
61
|
-
export declare function pruneByThresholdWithCap(graph: ScoreEdge[], frames: FrameNode[], threshold: number, maxCount: number): Set<number>;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ProgressPhase, SieveInput, SieveOptionsBase, SieveResult } from '../types/index.js';
|
|
2
|
-
export type SieveWorkerOptions = Omit<SieveOptionsBase, 'onProgress'> & SieveInput;
|
|
3
|
-
/**
|
|
4
|
-
* Run the pipeline, choosing the best execution strategy:
|
|
5
|
-
*
|
|
6
|
-
* - Production (bundled .mjs): Worker thread — spinner never freezes
|
|
7
|
-
* - Dev mode (tsx .ts): Main thread — simpler, spinner may stutter during CPU work
|
|
8
|
-
*/
|
|
9
|
-
export declare function runPipelineInWorker(options: SieveWorkerOptions, onProgress: (phase: ProgressPhase, percent: number) => void): Promise<SieveResult>;
|
package/dist/core/workspace.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { FrameNode, ProcessContext } from '../types/index.js';
|
|
2
|
-
export declare function createWorkspace(sessionId: string): Promise<string>;
|
|
3
|
-
export declare function finalizeOutput(ctx: ProcessContext, selectedFrames: FrameNode[]): Promise<string[]>;
|
|
4
|
-
export declare function cleanupWorkspace(workspacePath: string): Promise<void>;
|
|
5
|
-
/**
|
|
6
|
-
* Remove stale workspace directories left by previous interrupted runs.
|
|
7
|
-
* Only deletes directories older than 1 hour to avoid removing active workspaces.
|
|
8
|
-
*/
|
|
9
|
-
export declare function cleanupStaleWorkspaces(): Promise<void>;
|
|
10
|
-
/**
|
|
11
|
-
* Write a video buffer to a temp file in the workspace and return the path.
|
|
12
|
-
* Used by 'buffer' input mode.
|
|
13
|
-
*/
|
|
14
|
-
export declare function writeInputBuffer(buffer: Buffer, workspacePath: string): Promise<string>;
|
|
15
|
-
/**
|
|
16
|
-
* Write an array of frame Buffers as JPG files and return FrameNode[].
|
|
17
|
-
* Used by 'frames' input mode.
|
|
18
|
-
*/
|
|
19
|
-
export declare function writeInputFrames(frames: Buffer[], workspacePath: string): Promise<FrameNode[]>;
|
|
20
|
-
/**
|
|
21
|
-
* Read selected FrameNode files as Buffers with JPEG compression.
|
|
22
|
-
* Used to return output buffers in 'buffer' and 'frames' modes.
|
|
23
|
-
*/
|
|
24
|
-
export declare function readFramesAsBuffers(frameNodes: FrameNode[], quality: number): Promise<Buffer[]>;
|
package/dist/index.d.ts
DELETED
package/dist/types/index.d.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
export type ProgressPhase = 'EXTRACTING' | 'ANALYZING' | 'PRUNING' | 'FINALIZING';
|
|
2
|
-
export type SieveInput = {
|
|
3
|
-
mode: 'file';
|
|
4
|
-
inputPath: string;
|
|
5
|
-
} | {
|
|
6
|
-
mode: 'buffer';
|
|
7
|
-
inputBuffer: Buffer;
|
|
8
|
-
} | {
|
|
9
|
-
mode: 'frames';
|
|
10
|
-
inputFrames: Buffer[];
|
|
11
|
-
};
|
|
12
|
-
export interface SieveOptionsBase {
|
|
13
|
-
count?: number;
|
|
14
|
-
threshold?: number;
|
|
15
|
-
outputPath?: string;
|
|
16
|
-
fps?: number;
|
|
17
|
-
maxFrames?: number;
|
|
18
|
-
scale?: number;
|
|
19
|
-
quality?: number;
|
|
20
|
-
iouThreshold?: number;
|
|
21
|
-
animationThreshold?: number;
|
|
22
|
-
debug?: boolean;
|
|
23
|
-
onProgress?: (phase: ProgressPhase, percent: number) => void;
|
|
24
|
-
}
|
|
25
|
-
export type SieveOptions = SieveOptionsBase & SieveInput;
|
|
26
|
-
export interface ResolvedOptions {
|
|
27
|
-
mode: 'file' | 'buffer' | 'frames';
|
|
28
|
-
inputPath?: string;
|
|
29
|
-
count: number;
|
|
30
|
-
threshold: number;
|
|
31
|
-
pruneMode: 'threshold-with-cap';
|
|
32
|
-
outputPath: string;
|
|
33
|
-
fps: number;
|
|
34
|
-
maxFrames: number;
|
|
35
|
-
scale: number;
|
|
36
|
-
quality: number;
|
|
37
|
-
iouThreshold: number;
|
|
38
|
-
animationThreshold: number;
|
|
39
|
-
debug: boolean;
|
|
40
|
-
}
|
|
41
|
-
export interface SieveResult {
|
|
42
|
-
success: boolean;
|
|
43
|
-
originalFramesCount: number;
|
|
44
|
-
prunedFramesCount: number;
|
|
45
|
-
outputFiles: string[];
|
|
46
|
-
outputBuffers?: Buffer[];
|
|
47
|
-
animations?: AnimationMetadata[];
|
|
48
|
-
video?: VideoMetadata;
|
|
49
|
-
executionTimeMs: number;
|
|
50
|
-
}
|
|
51
|
-
export interface AnimationMetadata {
|
|
52
|
-
type: string;
|
|
53
|
-
boundingBox: BoundingBox;
|
|
54
|
-
startFrameId: number;
|
|
55
|
-
endFrameId: number;
|
|
56
|
-
durationMs: number;
|
|
57
|
-
}
|
|
58
|
-
export interface VideoMetadata {
|
|
59
|
-
originalDurationMs: number;
|
|
60
|
-
fps: number;
|
|
61
|
-
resolution: {
|
|
62
|
-
width: number;
|
|
63
|
-
height: number;
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
export interface FrameNode {
|
|
67
|
-
id: number;
|
|
68
|
-
timestamp: number;
|
|
69
|
-
extractPath: string;
|
|
70
|
-
}
|
|
71
|
-
export interface ScoreEdge {
|
|
72
|
-
sourceId: number;
|
|
73
|
-
targetId: number;
|
|
74
|
-
/**
|
|
75
|
-
* Information gain score (G(t)) between adjacent frames.
|
|
76
|
-
* Higher values = greater visual change (state transition) = should be preserved.
|
|
77
|
-
* Lower values = similar frames (little change) = candidates for pruning.
|
|
78
|
-
*
|
|
79
|
-
* Pruner removes frames with the LOWEST scores first (greedy ascending).
|
|
80
|
-
* Maps directly to G(t) from the vision analysis pipeline.
|
|
81
|
-
*/
|
|
82
|
-
score: number;
|
|
83
|
-
}
|
|
84
|
-
export interface BoundingBox {
|
|
85
|
-
x: number;
|
|
86
|
-
y: number;
|
|
87
|
-
width: number;
|
|
88
|
-
height: number;
|
|
89
|
-
}
|
|
90
|
-
export interface DBSCANResult {
|
|
91
|
-
labels: number[];
|
|
92
|
-
boundingBoxes: BoundingBox[];
|
|
93
|
-
}
|
|
94
|
-
export interface ProcessContext {
|
|
95
|
-
options: ResolvedOptions;
|
|
96
|
-
workspacePath: string;
|
|
97
|
-
frames: FrameNode[];
|
|
98
|
-
graph: ScoreEdge[];
|
|
99
|
-
animations?: AnimationMetadata[];
|
|
100
|
-
status: 'INIT' | ProgressPhase | 'SUCCESS' | 'FAILED';
|
|
101
|
-
emitProgress: (percent: number) => void;
|
|
102
|
-
error?: Error;
|
|
103
|
-
}
|
|
104
|
-
export interface AnalysisResult {
|
|
105
|
-
edges: ScoreEdge[];
|
|
106
|
-
animations: AnimationMetadata[];
|
|
107
|
-
}
|
package/dist/utils/logger.d.ts
DELETED
package/dist/utils/math.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interface for objects that have a numeric score.
|
|
3
|
-
*/
|
|
4
|
-
export interface ScoredItem {
|
|
5
|
-
score: number;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Normalize raw scores to [0, 1] range via Robust Hybrid Normalization.
|
|
9
|
-
*
|
|
10
|
-
* This model combines two mathematical approaches to provide a stable "relative" threshold:
|
|
11
|
-
*
|
|
12
|
-
* 1. Logistic-Robust-Z (Intensity):
|
|
13
|
-
* Calculates Z-scores using Median and Median Absolute Deviation (MAD).
|
|
14
|
-
* Maps these to a sigmoid (logistic) curve. This suppresses noise (scores near median)
|
|
15
|
-
* and highlights significant signals (outliers) without letting extreme outliers
|
|
16
|
-
* crush other meaningful transitions.
|
|
17
|
-
*
|
|
18
|
-
* 2. CDF / Percentile Rank (Relative Position):
|
|
19
|
-
* Maps each score to its percentile rank in the sequence. This ensures that 't'
|
|
20
|
-
* always has a consistent meaning as a "relative rank" regardless of absolute values.
|
|
21
|
-
*
|
|
22
|
-
* The final score is a weighted sum (NORMALIZATION_ALPHA) of both.
|
|
23
|
-
*
|
|
24
|
-
* @param items - Array of items with scores to normalize
|
|
25
|
-
* @returns normalized scores array (same length as input)
|
|
26
|
-
*/
|
|
27
|
-
export declare function normalizeScores<T extends ScoredItem>(items: T[]): number[];
|
package/dist/utils/min-heap.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic binary min-heap.
|
|
3
|
-
*
|
|
4
|
-
* Elements are ordered by a numeric `score` field.
|
|
5
|
-
* push/pop: O(log N), size: O(1).
|
|
6
|
-
*/
|
|
7
|
-
export declare class MinHeap<T extends {
|
|
8
|
-
score: number;
|
|
9
|
-
}> {
|
|
10
|
-
private readonly h;
|
|
11
|
-
get size(): number;
|
|
12
|
-
push(entry: T): void;
|
|
13
|
-
pop(): T | undefined;
|
|
14
|
-
private siftUp;
|
|
15
|
-
private siftDown;
|
|
16
|
-
}
|
package/dist/utils/paths.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export declare function ensureDir(dirPath: string): Promise<void>;
|
|
2
|
-
export declare function fileExists(filePath: string): Promise<boolean>;
|
|
3
|
-
/**
|
|
4
|
-
* Expand leading ~ to homedir. Node's path.resolve() does not expand ~,
|
|
5
|
-
* so paths like ~/Desktop/foo depend on process.cwd() and can produce
|
|
6
|
-
* different results when run from different directories.
|
|
7
|
-
*/
|
|
8
|
-
export declare function expandTilde(p: string): string;
|
|
9
|
-
/**
|
|
10
|
-
* Resolve path to absolute. Expands ~ to homedir first so that the result
|
|
11
|
-
* does not depend on process.cwd().
|
|
12
|
-
*/
|
|
13
|
-
export declare function resolveAbsolute(p: string): string;
|
|
14
|
-
/**
|
|
15
|
-
* Derive default output directory name from input file path.
|
|
16
|
-
* e.g., /path/to/video.mp4 -> /path/to/video_scenes
|
|
17
|
-
*/
|
|
18
|
-
export declare function deriveOutputPath(inputPath: string): string;
|