@doedja/scenecut 1.0.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.
Files changed (41) hide show
  1. package/README.md +280 -0
  2. package/bin/cli.js +293 -0
  3. package/dist/decoder/ffmpeg-decoder.d.ts +50 -0
  4. package/dist/decoder/ffmpeg-decoder.d.ts.map +1 -0
  5. package/dist/decoder/ffmpeg-decoder.js +269 -0
  6. package/dist/decoder/ffmpeg-decoder.js.map +1 -0
  7. package/dist/decoder/frame-buffer.d.ts +81 -0
  8. package/dist/decoder/frame-buffer.d.ts.map +1 -0
  9. package/dist/decoder/frame-buffer.js +123 -0
  10. package/dist/decoder/frame-buffer.js.map +1 -0
  11. package/dist/detection/detector.d.ts +19 -0
  12. package/dist/detection/detector.d.ts.map +1 -0
  13. package/dist/detection/detector.js +126 -0
  14. package/dist/detection/detector.js.map +1 -0
  15. package/dist/detection/wasm-bridge.d.ts +82 -0
  16. package/dist/detection/wasm-bridge.d.ts.map +1 -0
  17. package/dist/detection/wasm-bridge.js +182 -0
  18. package/dist/detection/wasm-bridge.js.map +1 -0
  19. package/dist/detection.wasm.js +2 -0
  20. package/dist/detection.wasm.wasm +0 -0
  21. package/dist/index.d.ts +54 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +63 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/keyframes.cjs.js +985 -0
  26. package/dist/keyframes.cjs.js.map +1 -0
  27. package/dist/keyframes.esm.js +946 -0
  28. package/dist/keyframes.esm.js.map +1 -0
  29. package/dist/types/index.d.ts +225 -0
  30. package/dist/types/index.d.ts.map +1 -0
  31. package/dist/types/index.js +5 -0
  32. package/dist/types/index.js.map +1 -0
  33. package/dist/utils/buffer-pool.d.ts +44 -0
  34. package/dist/utils/buffer-pool.d.ts.map +1 -0
  35. package/dist/utils/buffer-pool.js +81 -0
  36. package/dist/utils/buffer-pool.js.map +1 -0
  37. package/dist/utils/frame-processor.d.ts +48 -0
  38. package/dist/utils/frame-processor.d.ts.map +1 -0
  39. package/dist/utils/frame-processor.js +112 -0
  40. package/dist/utils/frame-processor.js.map +1 -0
  41. package/package.json +77 -0
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Frame Processor - Utilities for frame preprocessing
3
+ */
4
+ /**
5
+ * Format timestamp as timecode (HH:MM:SS.mmm)
6
+ */
7
+ export function formatTimecode(seconds) {
8
+ const hours = Math.floor(seconds / 3600);
9
+ const minutes = Math.floor((seconds % 3600) / 60);
10
+ const secs = Math.floor(seconds % 60);
11
+ const ms = Math.floor((seconds % 1) * 1000);
12
+ return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}.${ms.toString().padStart(3, '0')}`;
13
+ }
14
+ /**
15
+ * Calculate macroblock parameters for frame dimensions
16
+ */
17
+ export function calculateMBParam(width, height) {
18
+ const mb_width = Math.ceil(width / 16);
19
+ const mb_height = Math.ceil(height / 16);
20
+ const edge_size = 64;
21
+ return {
22
+ width,
23
+ height,
24
+ mb_width,
25
+ mb_height,
26
+ edged_width: 16 * mb_width + 2 * edge_size,
27
+ edged_height: 16 * mb_height + 2 * edge_size,
28
+ edge_size
29
+ };
30
+ }
31
+ /**
32
+ * Check if frame dimensions are valid
33
+ */
34
+ export function validateFrameDimensions(width, height) {
35
+ if (width <= 0 || height <= 0) {
36
+ throw new Error(`Invalid frame dimensions: ${width}x${height}`);
37
+ }
38
+ if (width > 8192 || height > 8192) {
39
+ throw new Error(`Frame dimensions too large: ${width}x${height} (max: 8192x8192)`);
40
+ }
41
+ }
42
+ /**
43
+ * Calculate fcode from search range option
44
+ */
45
+ export function calculateFcode(searchRange, width, height) {
46
+ switch (searchRange) {
47
+ case 'small':
48
+ return 2; // 64 pixel range
49
+ case 'medium':
50
+ return 4; // 256 pixel range (default)
51
+ case 'large':
52
+ return 6; // 1024 pixel range
53
+ case 'auto':
54
+ // Auto-adjust based on resolution
55
+ const pixels = width * height;
56
+ if (pixels <= 720 * 480)
57
+ return 3; // SD: 128px
58
+ if (pixels <= 1920 * 1080)
59
+ return 4; // HD: 256px
60
+ return 5; // 4K+: 512px
61
+ default:
62
+ return 4;
63
+ }
64
+ }
65
+ /**
66
+ * Calculate adaptive thresholds based on sensitivity
67
+ */
68
+ export function calculateThresholds(sensitivity) {
69
+ switch (sensitivity) {
70
+ case 'low':
71
+ return { intraThresh: 3000, intraThresh2: 150 }; // Less sensitive
72
+ case 'medium':
73
+ return { intraThresh: 2000, intraThresh2: 90 }; // Default
74
+ case 'high':
75
+ return { intraThresh: 1000, intraThresh2: 50 }; // More sensitive
76
+ case 'custom':
77
+ // Will be overridden by customThresholds
78
+ return { intraThresh: 2000, intraThresh2: 90 };
79
+ default:
80
+ return { intraThresh: 2000, intraThresh2: 90 };
81
+ }
82
+ }
83
+ /**
84
+ * Validate frame data
85
+ */
86
+ export function validateFrame(frame) {
87
+ if (!frame.data || frame.data.length === 0) {
88
+ throw new Error('Frame data is empty');
89
+ }
90
+ const expectedSize = frame.width * frame.height;
91
+ if (frame.data.length < expectedSize) {
92
+ throw new Error(`Frame data size mismatch: expected at least ${expectedSize}, got ${frame.data.length}`);
93
+ }
94
+ validateFrameDimensions(frame.width, frame.height);
95
+ }
96
+ /**
97
+ * Calculate memory usage for frame
98
+ */
99
+ export function calculateFrameMemory(width, height) {
100
+ const mbParam = calculateMBParam(width, height);
101
+ return mbParam.edged_width * mbParam.edged_height;
102
+ }
103
+ /**
104
+ * Estimate processing time based on frame count and resolution
105
+ */
106
+ export function estimateProcessingTime(frameCount, width, height, targetFps = 60) {
107
+ // Rough estimate: higher resolution = slower
108
+ const resolutionFactor = (width * height) / (1920 * 1080);
109
+ const adjustedFps = targetFps / resolutionFactor;
110
+ return frameCount / adjustedFps;
111
+ }
112
+ //# sourceMappingURL=frame-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-processor.js","sourceRoot":"","sources":["../../src/utils/frame-processor.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@doedja/scenecut",
3
+ "version": "1.0.0",
4
+ "description": "Scene change detection for Node.js using Xvid's motion estimation algorithm",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "scenecut": "./bin/cli.js"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/keyframes.esm.js",
13
+ "require": "./dist/keyframes.cjs.js",
14
+ "types": "./dist/index.d.ts"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "bin",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
23
+ "scripts": {
24
+ "build:wasm": "cd src/wasm && bash build.sh",
25
+ "build:ts": "tsc",
26
+ "build:bundle": "rollup -c",
27
+ "build": "npm run build:ts && npm run build:bundle",
28
+ "dev": "tsc --watch",
29
+ "test": "node test-basic.js",
30
+ "test:full": "node test-full.js",
31
+ "lint": "eslint src/**/*.ts",
32
+ "format": "prettier --write \"src/**/*.{ts,js}\"",
33
+ "prepublishOnly": "npm run build"
34
+ },
35
+ "keywords": [
36
+ "scene-detection",
37
+ "video",
38
+ "keyframe",
39
+ "xvid",
40
+ "ffmpeg",
41
+ "video-processing",
42
+ "motion-estimation",
43
+ "wasm",
44
+ "webassembly"
45
+ ],
46
+ "author": "doedja",
47
+ "license": "GPL-2.0",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/doedja/scenecut.git"
51
+ },
52
+ "bugs": {
53
+ "url": "https://github.com/doedja/scenecut/issues"
54
+ },
55
+ "homepage": "https://github.com/doedja/scenecut#readme",
56
+ "dependencies": {
57
+ "@ffmpeg-installer/ffmpeg": "^1.1.0",
58
+ "fluent-ffmpeg": "^2.1.2"
59
+ },
60
+ "devDependencies": {
61
+ "@rollup/plugin-commonjs": "^25.0.7",
62
+ "@rollup/plugin-node-resolve": "^15.2.3",
63
+ "@rollup/plugin-typescript": "^11.1.5",
64
+ "@types/fluent-ffmpeg": "^2.1.24",
65
+ "@types/node": "^20.10.0",
66
+ "@typescript-eslint/eslint-plugin": "^6.19.0",
67
+ "@typescript-eslint/parser": "^6.19.0",
68
+ "eslint": "^8.56.0",
69
+ "prettier": "^3.1.0",
70
+ "rollup": "^4.9.0",
71
+ "typescript": "^5.3.0",
72
+ "vitest": "^1.0.0"
73
+ },
74
+ "engines": {
75
+ "node": ">=18.0.0"
76
+ }
77
+ }