simple-ffmpegjs 0.1.0 → 0.2.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/types/index.d.ts CHANGED
@@ -1,128 +1,411 @@
1
- export type ClipType =
2
- | "video"
3
- | "audio"
4
- | "text"
5
- | "music"
6
- | "backgroundAudio"
7
- | "image";
8
-
9
- export interface BaseClip {
10
- type: ClipType;
11
- url?: string;
12
- position: number;
13
- end: number;
14
- }
1
+ declare namespace SIMPLEFFMPEG {
2
+ // ─────────────────────────────────────────────────────────────────────────────
3
+ // Error Classes
4
+ // ─────────────────────────────────────────────────────────────────────────────
15
5
 
16
- export interface VideoClip extends BaseClip {
17
- type: "video";
18
- url: string;
19
- cutFrom?: number;
20
- transition?: { type: string; duration: number };
21
- }
6
+ /** Base error class for all simple-ffmpeg errors */
7
+ class SimpleffmpegError extends Error {
8
+ name: "SimpleffmpegError";
9
+ }
22
10
 
23
- export interface AudioClip extends BaseClip {
24
- type: "audio";
25
- url: string;
26
- cutFrom?: number;
27
- volume?: number;
28
- }
11
+ /** Thrown when clip validation fails */
12
+ class ValidationError extends SimpleffmpegError {
13
+ name: "ValidationError";
14
+ errors: string[];
15
+ warnings: string[];
16
+ }
29
17
 
30
- export interface BackgroundMusicClip extends BaseClip {
31
- type: "music" | "backgroundAudio";
32
- url: string;
33
- cutFrom?: number;
34
- volume?: number;
35
- }
18
+ /** Thrown when FFmpeg command execution fails */
19
+ class FFmpegError extends SimpleffmpegError {
20
+ name: "FFmpegError";
21
+ stderr: string;
22
+ command: string;
23
+ exitCode: number | null;
24
+ }
36
25
 
37
- export interface ImageClip extends BaseClip {
38
- type: "image";
39
- url: string;
40
- kenBurns?:
41
- | "zoom-in"
42
- | "zoom-out"
43
- | "pan-left"
44
- | "pan-right"
45
- | "pan-up"
46
- | "pan-down";
47
- }
26
+ /** Thrown when a media file cannot be found or accessed */
27
+ class MediaNotFoundError extends SimpleffmpegError {
28
+ name: "MediaNotFoundError";
29
+ path: string;
30
+ }
48
31
 
49
- export type TextMode = "static" | "word-replace" | "word-sequential";
50
- export type TextAnimationType =
51
- | "none"
52
- | "fade-in"
53
- | "fade-in-out"
54
- | "pop"
55
- | "pop-bounce";
56
-
57
- export interface TextWordWindow {
58
- text: string;
59
- start: number;
60
- end: number;
61
- }
32
+ /** Thrown when export is cancelled via AbortSignal */
33
+ class ExportCancelledError extends SimpleffmpegError {
34
+ name: "ExportCancelledError";
35
+ }
62
36
 
63
- export interface TextClip {
64
- type: "text";
65
- text?: string;
66
- position: number;
67
- end: number;
68
- mode?: TextMode;
69
- words?: TextWordWindow[];
70
- wordTimestamps?: number[];
71
-
72
- // Font
73
- fontFile?: string;
74
- fontFamily?: string; // defaults to 'Sans' via fontconfig
75
- fontSize?: number; // default 48
76
- fontColor?: string; // default '#FFFFFF'
77
-
78
- // Position
79
- centerX?: number;
80
- centerY?: number;
81
- x?: number;
82
- y?: number;
83
-
84
- // Styling
85
- borderColor?: string;
86
- borderWidth?: number;
87
- shadowColor?: string;
88
- shadowX?: number;
89
- shadowY?: number;
90
- backgroundColor?: string;
91
- backgroundOpacity?: number;
92
- padding?: number;
93
-
94
- // Animation
95
- animation?: {
96
- type: TextAnimationType;
97
- in?: number; // seconds
98
- out?: number; // seconds
99
- };
100
- }
37
+ // ─────────────────────────────────────────────────────────────────────────────
38
+ // Clip Types
39
+ // ─────────────────────────────────────────────────────────────────────────────
40
+
41
+ type ClipType =
42
+ | "video"
43
+ | "audio"
44
+ | "text"
45
+ | "music"
46
+ | "backgroundAudio"
47
+ | "image";
48
+
49
+ interface BaseClip {
50
+ type: ClipType;
51
+ url?: string;
52
+ position: number;
53
+ end: number;
54
+ }
55
+
56
+ interface VideoClip extends BaseClip {
57
+ type: "video";
58
+ url: string;
59
+ cutFrom?: number;
60
+ volume?: number;
61
+ transition?: { type: string; duration: number };
62
+ }
63
+
64
+ interface AudioClip extends BaseClip {
65
+ type: "audio";
66
+ url: string;
67
+ cutFrom?: number;
68
+ volume?: number;
69
+ }
70
+
71
+ interface BackgroundMusicClip extends BaseClip {
72
+ type: "music" | "backgroundAudio";
73
+ url: string;
74
+ cutFrom?: number;
75
+ volume?: number;
76
+ }
77
+
78
+ interface ImageClip extends BaseClip {
79
+ type: "image";
80
+ url: string;
81
+ kenBurns?:
82
+ | "zoom-in"
83
+ | "zoom-out"
84
+ | "pan-left"
85
+ | "pan-right"
86
+ | "pan-up"
87
+ | "pan-down";
88
+ }
89
+
90
+ type TextMode = "static" | "word-replace" | "word-sequential";
91
+ type TextAnimationType =
92
+ | "none"
93
+ | "fade-in"
94
+ | "fade-in-out"
95
+ | "pop"
96
+ | "pop-bounce";
97
+
98
+ interface TextWordWindow {
99
+ text: string;
100
+ start: number;
101
+ end: number;
102
+ }
103
+
104
+ interface TextClip {
105
+ type: "text";
106
+ text?: string;
107
+ position: number;
108
+ end: number;
109
+ mode?: TextMode;
110
+ words?: TextWordWindow[];
111
+ wordTimestamps?: number[];
112
+
113
+ // Font
114
+ fontFile?: string;
115
+ fontFamily?: string; // defaults to 'Sans' via fontconfig
116
+ fontSize?: number; // default 48
117
+ fontColor?: string; // default '#FFFFFF'
118
+
119
+ // Position (xPercent/yPercent are percentages 0-1, x/y are pixels)
120
+ /** Horizontal position as percentage (0 = left, 0.5 = center, 1 = right) */
121
+ xPercent?: number;
122
+ /** Vertical position as percentage (0 = top, 0.5 = center, 1 = bottom) */
123
+ yPercent?: number;
124
+ /** Absolute X position in pixels */
125
+ x?: number;
126
+ /** Absolute Y position in pixels */
127
+ y?: number;
128
+
129
+ // Styling
130
+ borderColor?: string;
131
+ borderWidth?: number;
132
+ shadowColor?: string;
133
+ shadowX?: number;
134
+ shadowY?: number;
135
+ backgroundColor?: string;
136
+ backgroundOpacity?: number;
137
+ padding?: number;
138
+
139
+ // Animation
140
+ animation?: {
141
+ type: TextAnimationType;
142
+ in?: number; // seconds
143
+ out?: number; // seconds
144
+ };
145
+ }
146
+
147
+ type Clip =
148
+ | VideoClip
149
+ | AudioClip
150
+ | BackgroundMusicClip
151
+ | ImageClip
152
+ | TextClip;
153
+
154
+ // ─────────────────────────────────────────────────────────────────────────────
155
+ // Options
156
+ // ─────────────────────────────────────────────────────────────────────────────
157
+
158
+ interface SIMPLEFFMPEGOptions {
159
+ /** Frames per second (default: 30) */
160
+ fps?: number;
161
+ /** Output width in pixels (default: 1920) */
162
+ width?: number;
163
+ /** Output height in pixels (default: 1080) */
164
+ height?: number;
165
+ /** Validation mode: 'warn' logs warnings, 'strict' throws on warnings (default: 'warn') */
166
+ validationMode?: "warn" | "strict";
167
+ /** How to handle visual gaps: 'none' throws error, 'black' fills with black frames (default: 'none') */
168
+ fillGaps?: "none" | "black";
169
+ }
170
+
171
+ /** Progress information passed to onProgress callback */
172
+ interface ProgressInfo {
173
+ /** Current frame number being processed */
174
+ frame?: number;
175
+ /** Current processing speed in frames per second */
176
+ fps?: number;
177
+ /** Time processed in seconds */
178
+ timeProcessed?: number;
179
+ /** Progress percentage (0-100) */
180
+ percent?: number;
181
+ /** Processing speed multiplier (e.g., 2.0 = 2x realtime) */
182
+ speed?: number;
183
+ /** Current bitrate in kbits/s */
184
+ bitrate?: number;
185
+ /** Current output size in bytes */
186
+ size?: number;
187
+ }
188
+
189
+ /** Metadata to embed in output file */
190
+ interface MetadataOptions {
191
+ title?: string;
192
+ artist?: string;
193
+ album?: string;
194
+ comment?: string;
195
+ date?: string;
196
+ genre?: string;
197
+ /** Custom metadata key-value pairs */
198
+ custom?: Record<string, string>;
199
+ }
200
+
201
+ /** Thumbnail generation options */
202
+ interface ThumbnailOptions {
203
+ /** Output path for thumbnail image */
204
+ outputPath: string;
205
+ /** Time in seconds to capture (default: 0) */
206
+ time?: number;
207
+ /** Thumbnail width (maintains aspect if height omitted) */
208
+ width?: number;
209
+ /** Thumbnail height (maintains aspect if width omitted) */
210
+ height?: number;
211
+ }
212
+
213
+ /** Hardware acceleration options */
214
+ type HardwareAcceleration =
215
+ | "auto"
216
+ | "videotoolbox"
217
+ | "nvenc"
218
+ | "vaapi"
219
+ | "qsv"
220
+ | "none";
101
221
 
102
- export type Clip =
103
- | VideoClip
104
- | AudioClip
105
- | BackgroundMusicClip
106
- | ImageClip
107
- | TextClip;
108
-
109
- export interface SIMPLEFFMPEGOptions {
110
- fps?: number;
111
- width?: number;
112
- height?: number;
113
- validationMode?: "warn" | "strict";
222
+ /** Video codec options */
223
+ type VideoCodec =
224
+ | "libx264"
225
+ | "libx265"
226
+ | "libvpx-vp9"
227
+ | "libaom-av1"
228
+ | "prores_ks"
229
+ | "h264_videotoolbox"
230
+ | "hevc_videotoolbox"
231
+ | "h264_nvenc"
232
+ | "hevc_nvenc"
233
+ | "h264_vaapi"
234
+ | "hevc_vaapi"
235
+ | "h264_qsv"
236
+ | "hevc_qsv"
237
+ | string;
238
+
239
+ /** Audio codec options */
240
+ type AudioCodec =
241
+ | "aac"
242
+ | "libmp3lame"
243
+ | "libopus"
244
+ | "pcm_s16le"
245
+ | "flac"
246
+ | "copy"
247
+ | string;
248
+
249
+ /** Encoding preset options */
250
+ type EncodingPreset =
251
+ | "ultrafast"
252
+ | "superfast"
253
+ | "veryfast"
254
+ | "faster"
255
+ | "fast"
256
+ | "medium"
257
+ | "slow"
258
+ | "slower"
259
+ | "veryslow";
260
+
261
+ /** Resolution presets */
262
+ type ResolutionPreset = "480p" | "720p" | "1080p" | "1440p" | "4k";
263
+
264
+ interface ExportOptions {
265
+ // ─────────────────────────────────────────────────────────────────────────
266
+ // Output
267
+ // ─────────────────────────────────────────────────────────────────────────
268
+
269
+ /** Output file path (default: './output.mp4') */
270
+ outputPath?: string;
271
+
272
+ // ─────────────────────────────────────────────────────────────────────────
273
+ // Video Encoding
274
+ // ─────────────────────────────────────────────────────────────────────────
275
+
276
+ /** Video codec (default: 'libx264') */
277
+ videoCodec?: VideoCodec;
278
+ /** Quality level 0-51, lower is better (default: 23) */
279
+ crf?: number;
280
+ /** Encoding speed/quality tradeoff (default: 'medium') */
281
+ preset?: EncodingPreset;
282
+ /** Target video bitrate (e.g., '5M', '2500k'). Overrides CRF when set. */
283
+ videoBitrate?: string;
284
+
285
+ // ─────────────────────────────────────────────────────────────────────────
286
+ // Audio Encoding
287
+ // ─────────────────────────────────────────────────────────────────────────
288
+
289
+ /** Audio codec (default: 'aac') */
290
+ audioCodec?: AudioCodec;
291
+ /** Audio bitrate (default: '192k') */
292
+ audioBitrate?: string;
293
+ /** Audio sample rate in Hz (default: 48000) */
294
+ audioSampleRate?: number;
295
+
296
+ // ─────────────────────────────────────────────────────────────────────────
297
+ // Hardware Acceleration
298
+ // ─────────────────────────────────────────────────────────────────────────
299
+
300
+ /** Hardware acceleration mode (default: 'none') */
301
+ hwaccel?: HardwareAcceleration;
302
+
303
+ // ─────────────────────────────────────────────────────────────────────────
304
+ // Output Resolution
305
+ // ─────────────────────────────────────────────────────────────────────────
306
+
307
+ /** Output width in pixels (scales the output) */
308
+ outputWidth?: number;
309
+ /** Output height in pixels (scales the output) */
310
+ outputHeight?: number;
311
+ /** Resolution preset ('720p', '1080p', '4k', etc.) */
312
+ outputResolution?: ResolutionPreset;
313
+
314
+ // ─────────────────────────────────────────────────────────────────────────
315
+ // Advanced Options
316
+ // ─────────────────────────────────────────────────────────────────────────
317
+
318
+ /** Export audio only (no video) */
319
+ audioOnly?: boolean;
320
+ /** Enable two-pass encoding for better quality at target bitrate */
321
+ twoPass?: boolean;
322
+ /** Metadata to embed in output file */
323
+ metadata?: MetadataOptions;
324
+ /** Generate a thumbnail from the output */
325
+ thumbnail?: ThumbnailOptions;
326
+
327
+ // ─────────────────────────────────────────────────────────────────────────
328
+ // Debug & Logging
329
+ // ─────────────────────────────────────────────────────────────────────────
330
+
331
+ /** Enable verbose logging */
332
+ verbose?: boolean;
333
+ /** FFmpeg log level (default: 'warning') */
334
+ logLevel?:
335
+ | "quiet"
336
+ | "panic"
337
+ | "fatal"
338
+ | "error"
339
+ | "warning"
340
+ | "info"
341
+ | "verbose"
342
+ | "debug";
343
+ /** Save FFmpeg command to file for debugging */
344
+ saveCommand?: string;
345
+
346
+ // ─────────────────────────────────────────────────────────────────────────
347
+ // Callbacks & Control
348
+ // ─────────────────────────────────────────────────────────────────────────
349
+
350
+ /** Progress callback for monitoring export progress */
351
+ onProgress?: (progress: ProgressInfo) => void;
352
+ /** AbortSignal for cancelling the export */
353
+ signal?: AbortSignal;
354
+
355
+ // ─────────────────────────────────────────────────────────────────────────
356
+ // Text Batching (Advanced)
357
+ // ─────────────────────────────────────────────────────────────────────────
358
+
359
+ /** Maximum text overlay nodes per FFmpeg pass (default: 75) */
360
+ textMaxNodesPerPass?: number;
361
+ /** Video codec for intermediate text passes (default: 'libx264') */
362
+ intermediateVideoCodec?: string;
363
+ /** CRF for intermediate text passes (default: 18) */
364
+ intermediateCrf?: number;
365
+ /** Preset for intermediate text passes (default: 'veryfast') */
366
+ intermediatePreset?: string;
367
+ }
368
+
369
+ /** Result from preview() method */
370
+ interface PreviewResult {
371
+ /** The full FFmpeg command that would be executed */
372
+ command: string;
373
+ /** The filter_complex string */
374
+ filterComplex: string;
375
+ /** Total expected duration in seconds */
376
+ totalDuration: number;
377
+ }
114
378
  }
115
379
 
116
- export interface ExportOptions {
117
- outputPath?: string;
118
- textMaxNodesPerPass?: number;
119
- intermediateVideoCodec?: string;
120
- intermediateCrf?: number;
121
- intermediatePreset?: string;
380
+ declare class SIMPLEFFMPEG {
381
+ constructor(options?: SIMPLEFFMPEG.SIMPLEFFMPEGOptions);
382
+
383
+ /**
384
+ * Load clips into the project
385
+ * @param clips Array of clip descriptors (video, audio, text, image, music)
386
+ */
387
+ load(clips: SIMPLEFFMPEG.Clip[]): Promise<void[]>;
388
+
389
+ /**
390
+ * Get a preview of the FFmpeg command without executing it (dry-run)
391
+ * @param options Export options
392
+ */
393
+ preview(
394
+ options?: SIMPLEFFMPEG.ExportOptions
395
+ ): Promise<SIMPLEFFMPEG.PreviewResult>;
396
+
397
+ /**
398
+ * Export the project to a video file
399
+ * @param options Export options including outputPath, onProgress, and signal
400
+ */
401
+ export(options?: SIMPLEFFMPEG.ExportOptions): Promise<string>;
122
402
  }
123
403
 
124
- export default class SIMPLEFFMPEG {
125
- constructor(options: SIMPLEFFMPEGOptions);
126
- load(clips: Clip[]): Promise<void[]>;
127
- export(options: ExportOptions): Promise<string>;
404
+ /**
405
+ * Synthetic default export type for ESM default-import IntelliSense
406
+ */
407
+ declare namespace _defaultExportType {
408
+ export { SIMPLEFFMPEG as default };
128
409
  }
410
+
411
+ export = SIMPLEFFMPEG;
package/index.js DELETED
@@ -1 +0,0 @@
1
- module.exports = require("./src/simpleffmpeg");