@doedja/scenecut 1.0.0 → 1.0.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.
package/README.md CHANGED
@@ -1,280 +1,280 @@
1
- # scenecut
2
-
3
- Fast, accurate scene change detection for Node.js using Xvid's motion estimation algorithm compiled to WebAssembly.
4
-
5
- ## Features
6
-
7
- - **Fast**: WebAssembly-accelerated motion estimation (35-45 fps on typical hardware)
8
- - **Accurate**: Uses Xvid's proven motion estimation algorithm from vapoursynth-wwxd
9
- - **Multiple output formats**: Aegisub keyframes, timecodes, CSV, JSON
10
- - **Easy to use**: Simple CLI and programmatic API
11
- - **Cross-platform**: Works on Windows, Linux, and macOS
12
-
13
- ## Installation
14
-
15
- ### Global Installation (CLI)
16
-
17
- ```bash
18
- npm install -g @doedja/scenecut
19
- ```
20
-
21
- ### Local Installation (API)
22
-
23
- ```bash
24
- npm install @doedja/scenecut
25
- ```
26
-
27
- ## CLI Usage
28
-
29
- ### Basic Usage
30
-
31
- ```bash
32
- # Simple - detects scenes and saves to Aegisub format (default)
33
- # Creates input_keyframes.txt
34
- scenecut "input.mkv"
35
-
36
- # Specify custom output filename
37
- scenecut "video.mkv" -o keyframes.txt
38
-
39
- # For timecode output
40
- scenecut "video.mp4" --format timecode -o timecodes.txt
41
-
42
- # JSON format with full metadata
43
- scenecut "movie.avi" --format json
44
-
45
- # CSV format for spreadsheet analysis
46
- scenecut "movie.avi" --format csv -o scenes.csv
47
- ```
48
-
49
- ### CLI Options
50
-
51
- | Option | Alias | Description | Default |
52
- |--------|-------|-------------|---------|
53
- | `--format` | `-f` | Output format: `aegisub`, `json`, `csv`, `timecode` | `aegisub` |
54
- | `--output` | `-o` | Output file path | `{filename}_keyframes.txt` |
55
- | `--sensitivity` | `-s` | Detection sensitivity: `low`, `medium`, `high` | `medium` |
56
- | `--quiet` | `-q` | Suppress progress output | `false` |
57
- | `--verbose` | `-v` | Show detailed output including each scene | `false` |
58
- | `--help` | `-h` | Show help message | - |
59
-
60
- ### Examples
61
-
62
- ```bash
63
- # Default - creates anime_keyframes.txt in Aegisub format
64
- scenecut "anime.mkv"
65
-
66
- # High sensitivity for subtle scene changes
67
- scenecut "anime.mkv" --sensitivity high
68
-
69
- # JSON format with full metadata
70
- scenecut "video.mp4" --format json -o results.json
71
-
72
- # Verbose mode with detailed scene information
73
- scenecut "movie.mkv" --verbose
74
- ```
75
-
76
- ## Output Formats
77
-
78
- ### Aegisub Format (`.txt`)
79
-
80
- Aegisub keyframes format for subtitle timing:
81
-
82
- ```
83
- # keyframe format v1
84
- fps 23.976
85
- 0
86
- 143
87
- 287
88
- ```
89
-
90
- **Aegisub Workflow:**
91
- 1. Generate keyframes: `scenecut "video.mkv" -f aegisub -o keyframes.txt`
92
- 2. In Aegisub: **Video** → **Open Keyframes** → Select `keyframes.txt`
93
- 3. Keyframes appear as visual markers on the timeline for precise subtitle timing
94
-
95
- ### Timecode Format (`.txt`)
96
-
97
- Simple timecode list (HH:MM:SS.mmm):
98
-
99
- ```
100
- 00:00:00.000
101
- 00:00:05.964
102
- 00:00:11.970
103
- ```
104
-
105
- ### CSV Format (`.csv`)
106
-
107
- Spreadsheet-compatible format:
108
-
109
- ```csv
110
- frame,timestamp,timecode
111
- 0,0.0,00:00:00.000
112
- 143,5.964,00:00:05.964
113
- 287,11.970,00:00:11.970
114
- ```
115
-
116
- ### JSON Format (`.json`)
117
-
118
- Complete metadata and scene information:
119
-
120
- ```json
121
- {
122
- "scenes": [
123
- {
124
- "frameNumber": 0,
125
- "timestamp": 0.0,
126
- "timecode": "00:00:00.000"
127
- },
128
- {
129
- "frameNumber": 143,
130
- "timestamp": 5.964,
131
- "timecode": "00:00:05.964"
132
- }
133
- ],
134
- "metadata": {
135
- "totalFrames": 3000,
136
- "duration": 125.08,
137
- "fps": 23.976,
138
- "resolution": {
139
- "width": 1920,
140
- "height": 1080
141
- }
142
- }
143
- }
144
- ```
145
-
146
- ## Programmatic API
147
-
148
- ### Basic Usage
149
-
150
- ```javascript
151
- const { detectSceneChanges } = require('@doedja/scenecut');
152
-
153
- (async () => {
154
- const results = await detectSceneChanges('input.mp4');
155
-
156
- console.log(`Found ${results.scenes.length} scenes`);
157
- results.scenes.forEach(scene => {
158
- console.log(`Scene at frame ${scene.frameNumber} (${scene.timecode})`);
159
- });
160
- })();
161
- ```
162
-
163
- ### Advanced Usage with Options
164
-
165
- ```javascript
166
- const { detectSceneChanges } = require('@doedja/scenecut');
167
-
168
- const results = await detectSceneChanges('input.mp4', {
169
- sensitivity: 'high', // 'low' | 'medium' | 'high'
170
- searchRange: 'medium', // Motion search range
171
-
172
- // Progress callback
173
- onProgress: (progress) => {
174
- console.log(`Progress: ${progress.percent}%`);
175
- console.log(`Frame: ${progress.currentFrame}/${progress.totalFrames}`);
176
- console.log(`FPS: ${progress.fps}, ETA: ${progress.eta}s`);
177
- },
178
-
179
- // Scene detection callback
180
- onScene: (scene) => {
181
- console.log(`Scene detected at frame ${scene.frameNumber}`);
182
- console.log(`Timecode: ${scene.timecode}`);
183
- }
184
- });
185
-
186
- console.log('Detection complete!');
187
- console.log(`Total scenes: ${results.scenes.length}`);
188
- console.log(`Video duration: ${results.metadata.duration}s`);
189
- console.log(`Resolution: ${results.metadata.resolution.width}x${results.metadata.resolution.height}`);
190
- ```
191
-
192
- ### API Reference
193
-
194
- #### `detectSceneChanges(videoPath, options?)`
195
-
196
- Detects scene changes in a video file.
197
-
198
- **Parameters:**
199
- - `videoPath` (string): Path to input video file
200
- - `options` (object, optional):
201
- - `sensitivity` ('low' | 'medium' | 'high'): Detection sensitivity (default: 'medium')
202
- - `searchRange` ('auto' | 'small' | 'medium' | 'large'): Motion search range (default: 'medium')
203
- - `onProgress` (function): Callback for progress updates
204
- - `onScene` (function): Callback for each detected scene
205
-
206
- **Returns:** Promise<DetectionResult>
207
-
208
- **DetectionResult:**
209
- ```typescript
210
- {
211
- scenes: Array<{
212
- frameNumber: number;
213
- timestamp: number; // Seconds
214
- timecode: string; // HH:MM:SS.mmm
215
- }>;
216
- metadata: {
217
- totalFrames: number;
218
- duration: number; // Seconds
219
- fps: number;
220
- resolution: {
221
- width: number;
222
- height: number;
223
- };
224
- };
225
- }
226
- ```
227
-
228
- ## Supported Video Formats
229
-
230
- Keyframes supports any video format that FFmpeg can decode, including:
231
-
232
- - MP4 (`.mp4`, `.m4v`)
233
- - Matroska (`.mkv`)
234
- - AVI (`.avi`)
235
- - WebM (`.webm`)
236
- - MOV (`.mov`)
237
- - FLV (`.flv`)
238
- - And many more...
239
-
240
- ## How It Works
241
-
242
- Keyframes uses Xvid's motion estimation algorithm to detect scene changes:
243
-
244
- 1. **Frame Extraction**: FFmpeg extracts grayscale frames from the video
245
- 2. **Motion Analysis**: WebAssembly-compiled C code analyzes motion vectors between consecutive frames
246
- 3. **Scene Detection**: Frames with high motion complexity are identified as scene changes
247
- 4. **Output Formatting**: Results are formatted according to the requested output format
248
-
249
- The algorithm is based on [vapoursynth-wwxd](https://github.com/dubhater/vapoursynth-wwxd) by dubhater, which itself uses Xvid's motion estimation code.
250
-
251
- ## Performance
252
-
253
- Optimized for speed and accuracy:
254
- - **Processing speed**: 35-45 fps on 1080p video (modern hardware)
255
- - **Memory usage**: ~200-300 MB with efficient buffer management
256
- - **Accuracy**: Matches vapoursynth-wwxd output (100% accurate)
257
- - **Optimizations**: WASM SIMD, pre-allocated buffers, ring buffer streaming
258
-
259
- ## Requirements
260
-
261
- - **Node.js**: 18.0.0 or higher
262
- - **FFmpeg**: Automatically installed via `@ffmpeg-installer/ffmpeg`
263
-
264
- ## License
265
-
266
- GPL-2.0
267
-
268
- This project is based on:
269
- - [vapoursynth-wwxd](https://github.com/dubhater/vapoursynth-wwxd) by dubhater (GPL-2.0)
270
- - Xvid's motion estimation algorithm (GPL-2.0)
271
-
272
- ## Contributing
273
-
274
- Contributions are welcome! Please feel free to submit issues or pull requests.
275
-
276
- ## Credits
277
-
278
- - Original vapoursynth-wwxd plugin: [dubhater](https://github.com/dubhater)
279
- - Xvid motion estimation algorithm: [Xvid Team](https://www.xvid.com)
280
- - JavaScript/WASM port: This project
1
+ # scenecut
2
+
3
+ Fast, accurate scene change detection for Node.js using Xvid's motion estimation algorithm compiled to WebAssembly.
4
+
5
+ ## Features
6
+
7
+ - **Fast**: WebAssembly-accelerated motion estimation (35-45 fps on typical hardware)
8
+ - **Accurate**: Uses Xvid's proven motion estimation algorithm from vapoursynth-wwxd
9
+ - **Multiple output formats**: Aegisub keyframes, timecodes, CSV, JSON
10
+ - **Easy to use**: Simple CLI and programmatic API
11
+ - **Cross-platform**: Works on Windows, Linux, and macOS
12
+
13
+ ## Installation
14
+
15
+ ### Global Installation (CLI)
16
+
17
+ ```bash
18
+ npm install -g @doedja/scenecut
19
+ ```
20
+
21
+ ### Local Installation (API)
22
+
23
+ ```bash
24
+ npm install @doedja/scenecut
25
+ ```
26
+
27
+ ## CLI Usage
28
+
29
+ ### Basic Usage
30
+
31
+ ```bash
32
+ # Simple - detects scenes and saves to Aegisub format (default)
33
+ # Creates input_keyframes.txt
34
+ scenecut "input.mkv"
35
+
36
+ # Specify custom output filename
37
+ scenecut "video.mkv" -o keyframes.txt
38
+
39
+ # For timecode output
40
+ scenecut "video.mp4" --format timecode -o timecodes.txt
41
+
42
+ # JSON format with full metadata
43
+ scenecut "movie.avi" --format json
44
+
45
+ # CSV format for spreadsheet analysis
46
+ scenecut "movie.avi" --format csv -o scenes.csv
47
+ ```
48
+
49
+ ### CLI Options
50
+
51
+ | Option | Alias | Description | Default |
52
+ |--------|-------|-------------|---------|
53
+ | `--format` | `-f` | Output format: `aegisub`, `json`, `csv`, `timecode` | `aegisub` |
54
+ | `--output` | `-o` | Output file path | `{filename}_keyframes.txt` |
55
+ | `--sensitivity` | `-s` | Detection sensitivity: `low`, `medium`, `high` | `medium` |
56
+ | `--quiet` | `-q` | Suppress progress output | `false` |
57
+ | `--verbose` | `-v` | Show detailed output including each scene | `false` |
58
+ | `--help` | `-h` | Show help message | - |
59
+
60
+ ### Examples
61
+
62
+ ```bash
63
+ # Default - creates anime_keyframes.txt in Aegisub format
64
+ scenecut "anime.mkv"
65
+
66
+ # High sensitivity for subtle scene changes
67
+ scenecut "anime.mkv" --sensitivity high
68
+
69
+ # JSON format with full metadata
70
+ scenecut "video.mp4" --format json -o results.json
71
+
72
+ # Verbose mode with detailed scene information
73
+ scenecut "movie.mkv" --verbose
74
+ ```
75
+
76
+ ## Output Formats
77
+
78
+ ### Aegisub Format (`.txt`)
79
+
80
+ Aegisub keyframes format for subtitle timing:
81
+
82
+ ```
83
+ # keyframe format v1
84
+ fps 23.976
85
+ 0
86
+ 143
87
+ 287
88
+ ```
89
+
90
+ **Aegisub Workflow:**
91
+ 1. Generate keyframes: `scenecut "video.mkv" -f aegisub -o keyframes.txt`
92
+ 2. In Aegisub: **Video** → **Open Keyframes** → Select `keyframes.txt`
93
+ 3. Keyframes appear as visual markers on the timeline for precise subtitle timing
94
+
95
+ ### Timecode Format (`.txt`)
96
+
97
+ Simple timecode list (HH:MM:SS.mmm):
98
+
99
+ ```
100
+ 00:00:00.000
101
+ 00:00:05.964
102
+ 00:00:11.970
103
+ ```
104
+
105
+ ### CSV Format (`.csv`)
106
+
107
+ Spreadsheet-compatible format:
108
+
109
+ ```csv
110
+ frame,timestamp,timecode
111
+ 0,0.0,00:00:00.000
112
+ 143,5.964,00:00:05.964
113
+ 287,11.970,00:00:11.970
114
+ ```
115
+
116
+ ### JSON Format (`.json`)
117
+
118
+ Complete metadata and scene information:
119
+
120
+ ```json
121
+ {
122
+ "scenes": [
123
+ {
124
+ "frameNumber": 0,
125
+ "timestamp": 0.0,
126
+ "timecode": "00:00:00.000"
127
+ },
128
+ {
129
+ "frameNumber": 143,
130
+ "timestamp": 5.964,
131
+ "timecode": "00:00:05.964"
132
+ }
133
+ ],
134
+ "metadata": {
135
+ "totalFrames": 3000,
136
+ "duration": 125.08,
137
+ "fps": 23.976,
138
+ "resolution": {
139
+ "width": 1920,
140
+ "height": 1080
141
+ }
142
+ }
143
+ }
144
+ ```
145
+
146
+ ## Programmatic API
147
+
148
+ ### Basic Usage
149
+
150
+ ```javascript
151
+ const { detectSceneChanges } = require('@doedja/scenecut');
152
+
153
+ (async () => {
154
+ const results = await detectSceneChanges('input.mp4');
155
+
156
+ console.log(`Found ${results.scenes.length} scenes`);
157
+ results.scenes.forEach(scene => {
158
+ console.log(`Scene at frame ${scene.frameNumber} (${scene.timecode})`);
159
+ });
160
+ })();
161
+ ```
162
+
163
+ ### Advanced Usage with Options
164
+
165
+ ```javascript
166
+ const { detectSceneChanges } = require('@doedja/scenecut');
167
+
168
+ const results = await detectSceneChanges('input.mp4', {
169
+ sensitivity: 'high', // 'low' | 'medium' | 'high'
170
+ searchRange: 'medium', // Motion search range
171
+
172
+ // Progress callback
173
+ onProgress: (progress) => {
174
+ console.log(`Progress: ${progress.percent}%`);
175
+ console.log(`Frame: ${progress.currentFrame}/${progress.totalFrames}`);
176
+ console.log(`FPS: ${progress.fps}, ETA: ${progress.eta}s`);
177
+ },
178
+
179
+ // Scene detection callback
180
+ onScene: (scene) => {
181
+ console.log(`Scene detected at frame ${scene.frameNumber}`);
182
+ console.log(`Timecode: ${scene.timecode}`);
183
+ }
184
+ });
185
+
186
+ console.log('Detection complete!');
187
+ console.log(`Total scenes: ${results.scenes.length}`);
188
+ console.log(`Video duration: ${results.metadata.duration}s`);
189
+ console.log(`Resolution: ${results.metadata.resolution.width}x${results.metadata.resolution.height}`);
190
+ ```
191
+
192
+ ### API Reference
193
+
194
+ #### `detectSceneChanges(videoPath, options?)`
195
+
196
+ Detects scene changes in a video file.
197
+
198
+ **Parameters:**
199
+ - `videoPath` (string): Path to input video file
200
+ - `options` (object, optional):
201
+ - `sensitivity` ('low' | 'medium' | 'high'): Detection sensitivity (default: 'medium')
202
+ - `searchRange` ('auto' | 'small' | 'medium' | 'large'): Motion search range (default: 'medium')
203
+ - `onProgress` (function): Callback for progress updates
204
+ - `onScene` (function): Callback for each detected scene
205
+
206
+ **Returns:** Promise<DetectionResult>
207
+
208
+ **DetectionResult:**
209
+ ```typescript
210
+ {
211
+ scenes: Array<{
212
+ frameNumber: number;
213
+ timestamp: number; // Seconds
214
+ timecode: string; // HH:MM:SS.mmm
215
+ }>;
216
+ metadata: {
217
+ totalFrames: number;
218
+ duration: number; // Seconds
219
+ fps: number;
220
+ resolution: {
221
+ width: number;
222
+ height: number;
223
+ };
224
+ };
225
+ }
226
+ ```
227
+
228
+ ## Supported Video Formats
229
+
230
+ Keyframes supports any video format that FFmpeg can decode, including:
231
+
232
+ - MP4 (`.mp4`, `.m4v`)
233
+ - Matroska (`.mkv`)
234
+ - AVI (`.avi`)
235
+ - WebM (`.webm`)
236
+ - MOV (`.mov`)
237
+ - FLV (`.flv`)
238
+ - And many more...
239
+
240
+ ## How It Works
241
+
242
+ Keyframes uses Xvid's motion estimation algorithm to detect scene changes:
243
+
244
+ 1. **Frame Extraction**: FFmpeg extracts grayscale frames from the video
245
+ 2. **Motion Analysis**: WebAssembly-compiled C code analyzes motion vectors between consecutive frames
246
+ 3. **Scene Detection**: Frames with high motion complexity are identified as scene changes
247
+ 4. **Output Formatting**: Results are formatted according to the requested output format
248
+
249
+ The algorithm is based on [vapoursynth-wwxd](https://github.com/dubhater/vapoursynth-wwxd) by dubhater, which itself uses Xvid's motion estimation code.
250
+
251
+ ## Performance
252
+
253
+ Optimized for speed and accuracy:
254
+ - **Processing speed**: 35-45 fps on 1080p video (modern hardware)
255
+ - **Memory usage**: ~200-300 MB with efficient buffer management
256
+ - **Accuracy**: Matches vapoursynth-wwxd output (100% accurate)
257
+ - **Optimizations**: WASM SIMD, pre-allocated buffers, ring buffer streaming
258
+
259
+ ## Requirements
260
+
261
+ - **Node.js**: 18.0.0 or higher
262
+ - **FFmpeg**: Automatically installed via `@ffmpeg-installer/ffmpeg`
263
+
264
+ ## License
265
+
266
+ GPL-2.0
267
+
268
+ This project is based on:
269
+ - [vapoursynth-wwxd](https://github.com/dubhater/vapoursynth-wwxd) by dubhater (GPL-2.0)
270
+ - Xvid's motion estimation algorithm (GPL-2.0)
271
+
272
+ ## Contributing
273
+
274
+ Contributions are welcome! Please feel free to submit issues or pull requests.
275
+
276
+ ## Credits
277
+
278
+ - Original vapoursynth-wwxd plugin: [dubhater](https://github.com/dubhater)
279
+ - Xvid motion estimation algorithm: [Xvid Team](https://www.xvid.com)
280
+ - JavaScript/WASM port: This project