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.
@@ -0,0 +1,342 @@
1
+ declare namespace SIMPLEFFMPEG {
2
+ // ─────────────────────────────────────────────────────────────────────────────
3
+ // Error Classes
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+
6
+ /** Base error class for all simple-ffmpeg errors */
7
+ class SimpleffmpegError extends Error {
8
+ name: "SimpleffmpegError";
9
+ }
10
+
11
+ /** Thrown when clip validation fails */
12
+ class ValidationError extends SimpleffmpegError {
13
+ name: "ValidationError";
14
+ errors: string[];
15
+ warnings: string[];
16
+ }
17
+
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
+ }
25
+
26
+ /** Thrown when a media file cannot be found or accessed */
27
+ class MediaNotFoundError extends SimpleffmpegError {
28
+ name: "MediaNotFoundError";
29
+ path: string;
30
+ }
31
+
32
+ /** Thrown when export is cancelled via AbortSignal */
33
+ class ExportCancelledError extends SimpleffmpegError {
34
+ name: "ExportCancelledError";
35
+ }
36
+
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;
116
+ fontSize?: number;
117
+ fontColor?: string;
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;
143
+ out?: number;
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?: Record<string, string>;
198
+ }
199
+
200
+ /** Thumbnail generation options */
201
+ interface ThumbnailOptions {
202
+ outputPath: string;
203
+ time?: number;
204
+ width?: number;
205
+ height?: number;
206
+ }
207
+
208
+ type HardwareAcceleration =
209
+ | "auto"
210
+ | "videotoolbox"
211
+ | "nvenc"
212
+ | "vaapi"
213
+ | "qsv"
214
+ | "none";
215
+
216
+ type VideoCodec =
217
+ | "libx264"
218
+ | "libx265"
219
+ | "libvpx-vp9"
220
+ | "libaom-av1"
221
+ | "prores_ks"
222
+ | "h264_videotoolbox"
223
+ | "hevc_videotoolbox"
224
+ | "h264_nvenc"
225
+ | "hevc_nvenc"
226
+ | "h264_vaapi"
227
+ | "hevc_vaapi"
228
+ | "h264_qsv"
229
+ | "hevc_qsv"
230
+ | string;
231
+
232
+ type AudioCodec =
233
+ | "aac"
234
+ | "libmp3lame"
235
+ | "libopus"
236
+ | "pcm_s16le"
237
+ | "flac"
238
+ | "copy"
239
+ | string;
240
+
241
+ type EncodingPreset =
242
+ | "ultrafast"
243
+ | "superfast"
244
+ | "veryfast"
245
+ | "faster"
246
+ | "fast"
247
+ | "medium"
248
+ | "slow"
249
+ | "slower"
250
+ | "veryslow";
251
+
252
+ type ResolutionPreset = "480p" | "720p" | "1080p" | "1440p" | "4k";
253
+
254
+ interface ExportOptions {
255
+ // Output
256
+ outputPath?: string;
257
+
258
+ // Video Encoding
259
+ videoCodec?: VideoCodec;
260
+ crf?: number;
261
+ preset?: EncodingPreset;
262
+ videoBitrate?: string;
263
+
264
+ // Audio Encoding
265
+ audioCodec?: AudioCodec;
266
+ audioBitrate?: string;
267
+ audioSampleRate?: number;
268
+
269
+ // Hardware Acceleration
270
+ hwaccel?: HardwareAcceleration;
271
+
272
+ // Output Resolution
273
+ outputWidth?: number;
274
+ outputHeight?: number;
275
+ outputResolution?: ResolutionPreset;
276
+
277
+ // Advanced Options
278
+ audioOnly?: boolean;
279
+ twoPass?: boolean;
280
+ metadata?: MetadataOptions;
281
+ thumbnail?: ThumbnailOptions;
282
+
283
+ // Debug & Logging
284
+ verbose?: boolean;
285
+ logLevel?:
286
+ | "quiet"
287
+ | "panic"
288
+ | "fatal"
289
+ | "error"
290
+ | "warning"
291
+ | "info"
292
+ | "verbose"
293
+ | "debug";
294
+ saveCommand?: string;
295
+
296
+ // Callbacks & Control
297
+ onProgress?: (progress: ProgressInfo) => void;
298
+ signal?: AbortSignal;
299
+
300
+ // Text Batching
301
+ textMaxNodesPerPass?: number;
302
+ intermediateVideoCodec?: string;
303
+ intermediateCrf?: number;
304
+ intermediatePreset?: string;
305
+ }
306
+
307
+ /** Result from preview() method */
308
+ interface PreviewResult {
309
+ /** The full FFmpeg command that would be executed */
310
+ command: string;
311
+ /** The filter_complex string */
312
+ filterComplex: string;
313
+ /** Total expected duration in seconds */
314
+ totalDuration: number;
315
+ }
316
+ }
317
+
318
+ declare class SIMPLEFFMPEG {
319
+ constructor(options?: SIMPLEFFMPEG.SIMPLEFFMPEGOptions);
320
+
321
+ /**
322
+ * Load clips into the project
323
+ * @param clips Array of clip descriptors (video, audio, text, image, music)
324
+ */
325
+ load(clips: SIMPLEFFMPEG.Clip[]): Promise<void[]>;
326
+
327
+ /**
328
+ * Get a preview of the FFmpeg command without executing it (dry-run)
329
+ * @param options Export options
330
+ */
331
+ preview(
332
+ options?: SIMPLEFFMPEG.ExportOptions
333
+ ): Promise<SIMPLEFFMPEG.PreviewResult>;
334
+
335
+ /**
336
+ * Export the project to a video file
337
+ * @param options Export options including outputPath, onProgress, and signal
338
+ */
339
+ export(options?: SIMPLEFFMPEG.ExportOptions): Promise<string>;
340
+ }
341
+
342
+ export default SIMPLEFFMPEG;