@remotion/studio-shared 4.0.471 → 4.0.473
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/dist/api-requests.d.ts +131 -5
- package/dist/asset-drag-data.d.ts +8 -0
- package/dist/asset-drag-data.js +38 -0
- package/dist/codemods.d.ts +9 -0
- package/dist/detect-file-type.d.ts +71 -0
- package/dist/detect-file-type.js +295 -0
- package/dist/effect-clipboard-data.d.ts +70 -0
- package/dist/effect-clipboard-data.js +172 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +46 -1
- package/dist/keyframe-interpolation-function.d.ts +19 -0
- package/dist/keyframe-interpolation-function.js +69 -0
- package/dist/optimistic-add-keyframe.d.ts +5 -3
- package/dist/optimistic-add-keyframe.js +55 -36
- package/dist/optimistic-delete-keyframe.js +2 -5
- package/dist/optimistic-move-keyframe.d.ts +23 -0
- package/dist/optimistic-move-keyframe.js +142 -0
- package/dist/optimistic-update-for-code-values.js +1 -1
- package/dist/optimistic-update-for-effect-code-values.js +1 -1
- package/dist/optimistic-update-keyframe-settings.d.ts +13 -0
- package/dist/optimistic-update-keyframe-settings.js +60 -0
- package/dist/required-package.d.ts +3 -0
- package/dist/required-package.js +27 -0
- package/dist/schema-field-info.d.ts +1 -1
- package/dist/schema-field-info.js +52 -15
- package/package.json +4 -4
package/dist/api-requests.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { AudioCodec, ChromeMode, Codec, ColorSpace, LogLevel, PixelFormat, StillImageFormat, VideoImageFormat, X264Preset } from '@remotion/renderer';
|
|
2
2
|
import type { HardwareAccelerationOption } from '@remotion/renderer/client';
|
|
3
|
-
import type { _InternalTypes, CannotUpdateSequenceReason, CanUpdateEffectPropsResponse, CanUpdateSequencePropsResponseFalse, CanUpdateSequencePropsResponseTrue, CanUpdateSequencePropStatus, SequenceNodePath, SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
|
|
3
|
+
import type { _InternalTypes, CannotUpdateSequenceReason, CanUpdateEffectPropsResponse, CanUpdateSequencePropsResponseFalse, CanUpdateSequencePropsResponseTrue, CanUpdateSequencePropStatus, ExtrapolateType, SequenceNodePath, SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
|
|
4
4
|
import type { RecastCodemod, VisualControlChange } from './codemods';
|
|
5
|
+
import type { EffectClipboardParam, EffectClipboardPasteType, EffectClipboardSnapshot } from './effect-clipboard-data';
|
|
5
6
|
import type { PackageManager } from './package-manager';
|
|
6
7
|
import type { ProjectInfo } from './project-info';
|
|
7
8
|
import type { CompletedClientRender, RequiredChromiumOptions } from './render-job';
|
|
@@ -163,6 +164,13 @@ export type DeleteStaticFileResponse = {
|
|
|
163
164
|
success: boolean;
|
|
164
165
|
existed: boolean;
|
|
165
166
|
};
|
|
167
|
+
export type RenameStaticFileRequest = {
|
|
168
|
+
oldRelativePath: string;
|
|
169
|
+
newRelativePath: string;
|
|
170
|
+
};
|
|
171
|
+
export type RenameStaticFileResponse = {
|
|
172
|
+
success: boolean;
|
|
173
|
+
};
|
|
166
174
|
export type CanUpdateDefaultPropsResponse = {
|
|
167
175
|
canUpdate: true;
|
|
168
176
|
currentDefaultProps: Record<string, unknown>;
|
|
@@ -219,8 +227,8 @@ export type SaveSequencePropEdit = {
|
|
|
219
227
|
export type SaveSequencePropsRequest = {
|
|
220
228
|
edits: SaveSequencePropEdit[];
|
|
221
229
|
clientId: string;
|
|
222
|
-
undoLabel: string
|
|
223
|
-
redoLabel: string
|
|
230
|
+
undoLabel: string;
|
|
231
|
+
redoLabel: string;
|
|
224
232
|
};
|
|
225
233
|
export type SaveSequencePropsResult = {
|
|
226
234
|
fileName: string;
|
|
@@ -235,16 +243,22 @@ export type SaveSequencePropsResponse = {
|
|
|
235
243
|
canUpdate: false;
|
|
236
244
|
reason: CannotUpdateSequenceReason;
|
|
237
245
|
};
|
|
238
|
-
|
|
246
|
+
type SaveEffectPropsRequestBase = {
|
|
239
247
|
fileName: string;
|
|
240
248
|
sequenceNodePath: SequencePropsSubscriptionKey;
|
|
241
249
|
effectIndex: number;
|
|
242
250
|
key: string;
|
|
243
|
-
value: string;
|
|
244
251
|
defaultValue: string | null;
|
|
245
252
|
schema: SequenceSchema;
|
|
246
253
|
clientId: string;
|
|
247
254
|
};
|
|
255
|
+
export type SaveEffectPropsRequest = (SaveEffectPropsRequestBase & {
|
|
256
|
+
type: 'value';
|
|
257
|
+
value: string;
|
|
258
|
+
}) | (SaveEffectPropsRequestBase & {
|
|
259
|
+
type: 'effect-param';
|
|
260
|
+
effectParam: EffectClipboardParam;
|
|
261
|
+
});
|
|
248
262
|
export type SaveEffectPropsResponse = CanUpdateEffectPropsResponse;
|
|
249
263
|
export type AddEffectRequest = {
|
|
250
264
|
fileName: string;
|
|
@@ -275,6 +289,21 @@ export type ReorderEffectResponse = {
|
|
|
275
289
|
reason: string;
|
|
276
290
|
stack: string;
|
|
277
291
|
};
|
|
292
|
+
export type ReorderSequencePosition = 'before' | 'after';
|
|
293
|
+
export type ReorderSequenceRequest = {
|
|
294
|
+
fileName: string;
|
|
295
|
+
sourceNodePath: SequencePropsSubscriptionKey;
|
|
296
|
+
targetNodePath: SequencePropsSubscriptionKey;
|
|
297
|
+
position: ReorderSequencePosition;
|
|
298
|
+
clientId: string;
|
|
299
|
+
};
|
|
300
|
+
export type ReorderSequenceResponse = {
|
|
301
|
+
success: true;
|
|
302
|
+
} | {
|
|
303
|
+
success: false;
|
|
304
|
+
reason: string;
|
|
305
|
+
stack: string;
|
|
306
|
+
};
|
|
278
307
|
export type DeleteSequenceKeyframe = {
|
|
279
308
|
fileName: string;
|
|
280
309
|
nodePath: SequencePropsSubscriptionKey;
|
|
@@ -282,6 +311,14 @@ export type DeleteSequenceKeyframe = {
|
|
|
282
311
|
frame: number;
|
|
283
312
|
schema: SequenceSchema;
|
|
284
313
|
};
|
|
314
|
+
export type MoveSequenceKeyframe = {
|
|
315
|
+
fileName: string;
|
|
316
|
+
nodePath: SequencePropsSubscriptionKey;
|
|
317
|
+
key: string;
|
|
318
|
+
fromFrame: number;
|
|
319
|
+
toFrame: number;
|
|
320
|
+
schema: SequenceSchema;
|
|
321
|
+
};
|
|
285
322
|
export type AddSequenceKeyframeRequest = {
|
|
286
323
|
fileName: string;
|
|
287
324
|
nodePath: SequencePropsSubscriptionKey;
|
|
@@ -300,6 +337,15 @@ export type DeleteEffectKeyframe = {
|
|
|
300
337
|
frame: number;
|
|
301
338
|
schema: SequenceSchema;
|
|
302
339
|
};
|
|
340
|
+
export type MoveEffectKeyframe = {
|
|
341
|
+
fileName: string;
|
|
342
|
+
sequenceNodePath: SequencePropsSubscriptionKey;
|
|
343
|
+
effectIndex: number;
|
|
344
|
+
key: string;
|
|
345
|
+
fromFrame: number;
|
|
346
|
+
toFrame: number;
|
|
347
|
+
schema: SequenceSchema;
|
|
348
|
+
};
|
|
303
349
|
export type DeleteKeyframesRequest = {
|
|
304
350
|
sequenceKeyframes: DeleteSequenceKeyframe[];
|
|
305
351
|
effectKeyframes: DeleteEffectKeyframe[];
|
|
@@ -308,6 +354,14 @@ export type DeleteKeyframesRequest = {
|
|
|
308
354
|
export type DeleteKeyframesResponse = {
|
|
309
355
|
success: true;
|
|
310
356
|
};
|
|
357
|
+
export type MoveKeyframesRequest = {
|
|
358
|
+
sequenceKeyframes: MoveSequenceKeyframe[];
|
|
359
|
+
effectKeyframes: MoveEffectKeyframe[];
|
|
360
|
+
clientId: string;
|
|
361
|
+
};
|
|
362
|
+
export type MoveKeyframesResponse = {
|
|
363
|
+
success: true;
|
|
364
|
+
};
|
|
311
365
|
export type AddEffectKeyframeRequest = {
|
|
312
366
|
fileName: string;
|
|
313
367
|
sequenceNodePath: SequencePropsSubscriptionKey;
|
|
@@ -319,6 +373,32 @@ export type AddEffectKeyframeRequest = {
|
|
|
319
373
|
clientId: string;
|
|
320
374
|
};
|
|
321
375
|
export type AddEffectKeyframeResponse = SaveEffectPropsResponse;
|
|
376
|
+
export type KeyframeSettings = {
|
|
377
|
+
clamping: {
|
|
378
|
+
left: ExtrapolateType;
|
|
379
|
+
right: ExtrapolateType;
|
|
380
|
+
} | undefined;
|
|
381
|
+
posterize: number | undefined;
|
|
382
|
+
};
|
|
383
|
+
export type UpdateSequenceKeyframeSettingsRequest = {
|
|
384
|
+
fileName: string;
|
|
385
|
+
nodePath: SequencePropsSubscriptionKey;
|
|
386
|
+
key: string;
|
|
387
|
+
settings: KeyframeSettings;
|
|
388
|
+
schema: SequenceSchema;
|
|
389
|
+
clientId: string;
|
|
390
|
+
};
|
|
391
|
+
export type UpdateSequenceKeyframeSettingsResponse = SaveSequencePropsResponse;
|
|
392
|
+
export type UpdateEffectKeyframeSettingsRequest = {
|
|
393
|
+
fileName: string;
|
|
394
|
+
sequenceNodePath: SequencePropsSubscriptionKey;
|
|
395
|
+
effectIndex: number;
|
|
396
|
+
key: string;
|
|
397
|
+
settings: KeyframeSettings;
|
|
398
|
+
schema: SequenceSchema;
|
|
399
|
+
clientId: string;
|
|
400
|
+
};
|
|
401
|
+
export type UpdateEffectKeyframeSettingsResponse = SaveEffectPropsResponse;
|
|
322
402
|
type BaseDeleteEffectRequestItem = {
|
|
323
403
|
fileName: string;
|
|
324
404
|
sequenceNodePath: SequencePropsSubscriptionKey;
|
|
@@ -337,6 +417,20 @@ export type DeleteEffectResponse = {
|
|
|
337
417
|
reason: string;
|
|
338
418
|
stack: string;
|
|
339
419
|
};
|
|
420
|
+
export type PasteEffectsRequest = {
|
|
421
|
+
targetFileName: string;
|
|
422
|
+
targetSequenceNodePath: SequencePropsSubscriptionKey;
|
|
423
|
+
type: EffectClipboardPasteType;
|
|
424
|
+
effects: EffectClipboardSnapshot[];
|
|
425
|
+
clientId: string;
|
|
426
|
+
};
|
|
427
|
+
export type PasteEffectsResponse = {
|
|
428
|
+
success: true;
|
|
429
|
+
} | {
|
|
430
|
+
success: false;
|
|
431
|
+
reason: string;
|
|
432
|
+
stack: string;
|
|
433
|
+
};
|
|
340
434
|
export type DeleteJsxNodeRequestItem = {
|
|
341
435
|
fileName: string;
|
|
342
436
|
nodePath: SequenceNodePath;
|
|
@@ -366,6 +460,14 @@ export type InsertableCompositionElement = {
|
|
|
366
460
|
type: 'solid';
|
|
367
461
|
width: number;
|
|
368
462
|
height: number;
|
|
463
|
+
} | {
|
|
464
|
+
type: 'asset';
|
|
465
|
+
assetType: 'image' | 'video' | 'gif' | 'audio';
|
|
466
|
+
src: string;
|
|
467
|
+
dimensions: {
|
|
468
|
+
width: number;
|
|
469
|
+
height: number;
|
|
470
|
+
} | null;
|
|
369
471
|
};
|
|
370
472
|
export type InsertJsxElementRequest = {
|
|
371
473
|
compositionFile: string;
|
|
@@ -379,6 +481,15 @@ export type InsertJsxElementResponse = {
|
|
|
379
481
|
reason: string;
|
|
380
482
|
stack: string;
|
|
381
483
|
};
|
|
484
|
+
export type DownloadRemoteAssetRequest = {
|
|
485
|
+
url: string;
|
|
486
|
+
};
|
|
487
|
+
export type DownloadRemoteAssetResponse = {
|
|
488
|
+
assetPath: string;
|
|
489
|
+
sizeInBytes: number;
|
|
490
|
+
created: boolean;
|
|
491
|
+
element: InsertableCompositionElement;
|
|
492
|
+
};
|
|
382
493
|
export type UpdateAvailableRequest = {};
|
|
383
494
|
export type UpdateAvailableResponse = {
|
|
384
495
|
currentVersion: string;
|
|
@@ -411,6 +522,13 @@ export type RedoResponse = {
|
|
|
411
522
|
success: false;
|
|
412
523
|
reason: string;
|
|
413
524
|
};
|
|
525
|
+
export type LogStudioErrorRequest = {
|
|
526
|
+
name: string | null;
|
|
527
|
+
message: string;
|
|
528
|
+
stack: string | null;
|
|
529
|
+
symbolicatedStackFrames: SymbolicatedStackFrame[] | null;
|
|
530
|
+
};
|
|
531
|
+
export type LogStudioErrorResponse = {};
|
|
414
532
|
export type ApiRoutes = {
|
|
415
533
|
'/api/composition-component-info': ReqAndRes<CompositionComponentInfoRequest, CompositionComponentInfoResponse>;
|
|
416
534
|
'/api/cancel': ReqAndRes<CancelRenderRequest, CancelRenderResponse>;
|
|
@@ -434,20 +552,28 @@ export type ApiRoutes = {
|
|
|
434
552
|
'/api/save-effect-props': ReqAndRes<SaveEffectPropsRequest, SaveEffectPropsResponse>;
|
|
435
553
|
'/api/add-effect': ReqAndRes<AddEffectRequest, AddEffectResponse>;
|
|
436
554
|
'/api/reorder-effect': ReqAndRes<ReorderEffectRequest, ReorderEffectResponse>;
|
|
555
|
+
'/api/reorder-sequence': ReqAndRes<ReorderSequenceRequest, ReorderSequenceResponse>;
|
|
437
556
|
'/api/delete-keyframes': ReqAndRes<DeleteKeyframesRequest, DeleteKeyframesResponse>;
|
|
557
|
+
'/api/move-keyframes': ReqAndRes<MoveKeyframesRequest, MoveKeyframesResponse>;
|
|
438
558
|
'/api/add-sequence-keyframe': ReqAndRes<AddSequenceKeyframeRequest, AddSequenceKeyframeResponse>;
|
|
439
559
|
'/api/add-effect-keyframe': ReqAndRes<AddEffectKeyframeRequest, AddEffectKeyframeResponse>;
|
|
560
|
+
'/api/update-sequence-keyframe-settings': ReqAndRes<UpdateSequenceKeyframeSettingsRequest, UpdateSequenceKeyframeSettingsResponse>;
|
|
561
|
+
'/api/update-effect-keyframe-settings': ReqAndRes<UpdateEffectKeyframeSettingsRequest, UpdateEffectKeyframeSettingsResponse>;
|
|
440
562
|
'/api/delete-effect': ReqAndRes<DeleteEffectRequest, DeleteEffectResponse>;
|
|
563
|
+
'/api/paste-effects': ReqAndRes<PasteEffectsRequest, PasteEffectsResponse>;
|
|
441
564
|
'/api/delete-jsx-node': ReqAndRes<DeleteJsxNodeRequest, DeleteJsxNodeResponse>;
|
|
442
565
|
'/api/duplicate-jsx-node': ReqAndRes<DuplicateJsxNodeRequest, DuplicateJsxNodeResponse>;
|
|
443
566
|
'/api/insert-jsx-element': ReqAndRes<InsertJsxElementRequest, InsertJsxElementResponse>;
|
|
567
|
+
'/api/download-remote-asset': ReqAndRes<DownloadRemoteAssetRequest, DownloadRemoteAssetResponse>;
|
|
444
568
|
'/api/update-available': ReqAndRes<UpdateAvailableRequest, UpdateAvailableResponse>;
|
|
445
569
|
'/api/apply-codemod': ReqAndRes<ApplyCodemodRequest, ApplyCodemodResponse>;
|
|
446
570
|
'/api/project-info': ReqAndRes<ProjectInfoRequest, ProjectInfoResponse>;
|
|
447
571
|
'/api/delete-static-file': ReqAndRes<DeleteStaticFileRequest, DeleteStaticFileResponse>;
|
|
572
|
+
'/api/rename-static-file': ReqAndRes<RenameStaticFileRequest, RenameStaticFileResponse>;
|
|
448
573
|
'/api/restart-studio': ReqAndRes<RestartStudioRequest, RestartStudioResponse>;
|
|
449
574
|
'/api/install-package': ReqAndRes<InstallPackageRequest, InstallPackageResponse>;
|
|
450
575
|
'/api/undo': ReqAndRes<UndoRequest, UndoResponse>;
|
|
451
576
|
'/api/redo': ReqAndRes<RedoRequest, RedoResponse>;
|
|
577
|
+
'/api/log-studio-error': ReqAndRes<LogStudioErrorRequest, LogStudioErrorResponse>;
|
|
452
578
|
};
|
|
453
579
|
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const ASSET_DRAG_MIME_TYPE = "application/vnd.remotion.asset+json";
|
|
2
|
+
export type AssetDragData = {
|
|
3
|
+
type: 'remotion-asset';
|
|
4
|
+
version: 1;
|
|
5
|
+
assetPath: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const makeAssetDragData: (assetPath: string) => AssetDragData;
|
|
8
|
+
export declare const parseAssetDragData: (value: string) => AssetDragData | null;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseAssetDragData = exports.makeAssetDragData = exports.ASSET_DRAG_MIME_TYPE = void 0;
|
|
4
|
+
exports.ASSET_DRAG_MIME_TYPE = 'application/vnd.remotion.asset+json';
|
|
5
|
+
const isRecord = (value) => {
|
|
6
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
7
|
+
};
|
|
8
|
+
const makeAssetDragData = (assetPath) => {
|
|
9
|
+
return {
|
|
10
|
+
type: 'remotion-asset',
|
|
11
|
+
version: 1,
|
|
12
|
+
assetPath,
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
exports.makeAssetDragData = makeAssetDragData;
|
|
16
|
+
const parseAssetDragData = (value) => {
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(value);
|
|
19
|
+
if (!isRecord(parsed)) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
if (parsed.type !== 'remotion-asset' || parsed.version !== 1) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
if (typeof parsed.assetPath !== 'string' || parsed.assetPath.length === 0) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
type: 'remotion-asset',
|
|
30
|
+
version: 1,
|
|
31
|
+
assetPath: parsed.assetPath,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
catch (_a) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
exports.parseAssetDragData = parseAssetDragData;
|
package/dist/codemods.d.ts
CHANGED
|
@@ -25,4 +25,13 @@ export type RecastCodemod = {
|
|
|
25
25
|
} | {
|
|
26
26
|
type: 'delete-composition';
|
|
27
27
|
idToDelete: string;
|
|
28
|
+
} | {
|
|
29
|
+
type: 'rename-folder';
|
|
30
|
+
folderName: string;
|
|
31
|
+
parentName: string | null;
|
|
32
|
+
newName: string;
|
|
33
|
+
} | {
|
|
34
|
+
type: 'delete-folder';
|
|
35
|
+
folderName: string;
|
|
36
|
+
parentName: string | null;
|
|
28
37
|
} | ApplyVisualControlCodemod;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export type FileDimensions = {
|
|
2
|
+
readonly width: number;
|
|
3
|
+
readonly height: number;
|
|
4
|
+
};
|
|
5
|
+
export declare const matchesPattern: (pattern: Uint8Array<ArrayBufferLike>) => (data: Uint8Array<ArrayBufferLike>) => boolean;
|
|
6
|
+
export declare const isRiffAvi: (data: Uint8Array<ArrayBufferLike>) => boolean;
|
|
7
|
+
export declare const isRiffWave: (data: Uint8Array<ArrayBufferLike>) => boolean;
|
|
8
|
+
export declare const isWebm: (data: Uint8Array<ArrayBufferLike>) => boolean;
|
|
9
|
+
export declare const isIsoBaseMedia: (data: Uint8Array<ArrayBufferLike>) => boolean;
|
|
10
|
+
export declare const isTransportStream: (data: Uint8Array<ArrayBufferLike>) => boolean;
|
|
11
|
+
export declare const isMp3: (data: Uint8Array<ArrayBufferLike>) => boolean;
|
|
12
|
+
export declare const isAac: (data: Uint8Array<ArrayBufferLike>) => boolean;
|
|
13
|
+
export declare const isFlac: (data: Uint8Array<ArrayBufferLike>) => boolean;
|
|
14
|
+
export declare const isM3u: (data: Uint8Array<ArrayBufferLike>) => boolean;
|
|
15
|
+
export type RiffType = {
|
|
16
|
+
type: 'riff';
|
|
17
|
+
};
|
|
18
|
+
export type WebmType = {
|
|
19
|
+
type: 'webm';
|
|
20
|
+
};
|
|
21
|
+
export type IsoBaseMediaType = {
|
|
22
|
+
type: 'iso-base-media';
|
|
23
|
+
};
|
|
24
|
+
export type TransportStreamType = {
|
|
25
|
+
type: 'transport-stream';
|
|
26
|
+
};
|
|
27
|
+
export type Mp3Type = {
|
|
28
|
+
type: 'mp3';
|
|
29
|
+
};
|
|
30
|
+
export type AacType = {
|
|
31
|
+
type: 'aac';
|
|
32
|
+
};
|
|
33
|
+
export type WavType = {
|
|
34
|
+
type: 'wav';
|
|
35
|
+
};
|
|
36
|
+
export type GifType = {
|
|
37
|
+
type: 'gif';
|
|
38
|
+
dimensions: FileDimensions | null;
|
|
39
|
+
};
|
|
40
|
+
export type FlacType = {
|
|
41
|
+
type: 'flac';
|
|
42
|
+
};
|
|
43
|
+
export type M3uType = {
|
|
44
|
+
type: 'm3u';
|
|
45
|
+
};
|
|
46
|
+
export type PngType = {
|
|
47
|
+
type: 'png';
|
|
48
|
+
dimensions: FileDimensions | null;
|
|
49
|
+
};
|
|
50
|
+
export type JpegType = {
|
|
51
|
+
type: 'jpeg';
|
|
52
|
+
dimensions: FileDimensions | null;
|
|
53
|
+
};
|
|
54
|
+
export type WebpType = {
|
|
55
|
+
type: 'webp';
|
|
56
|
+
dimensions: FileDimensions | null;
|
|
57
|
+
};
|
|
58
|
+
export type BmpType = {
|
|
59
|
+
type: 'bmp';
|
|
60
|
+
dimensions: FileDimensions | null;
|
|
61
|
+
};
|
|
62
|
+
export type PdfType = {
|
|
63
|
+
type: 'pdf';
|
|
64
|
+
};
|
|
65
|
+
export type UnknownType = {
|
|
66
|
+
type: 'unknown';
|
|
67
|
+
};
|
|
68
|
+
export type FileType = JpegType | WebpType | RiffType | WebmType | WavType | PdfType | AacType | IsoBaseMediaType | TransportStreamType | Mp3Type | GifType | PngType | BmpType | AacType | FlacType | M3uType | UnknownType;
|
|
69
|
+
export type ImageFileType = JpegType | WebpType | GifType | PngType | BmpType;
|
|
70
|
+
export declare const isImageFileType: (fileType: FileType) => fileType is ImageFileType;
|
|
71
|
+
export declare const detectFileType: (data: Uint8Array<ArrayBufferLike>) => FileType;
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectFileType = exports.isImageFileType = exports.isM3u = exports.isFlac = exports.isAac = exports.isMp3 = exports.isTransportStream = exports.isIsoBaseMedia = exports.isWebm = exports.isRiffWave = exports.isRiffAvi = exports.matchesPattern = void 0;
|
|
4
|
+
const webmPattern = new Uint8Array([0x1a, 0x45, 0xdf, 0xa3]);
|
|
5
|
+
const matchesPattern = (pattern) => {
|
|
6
|
+
return (data) => {
|
|
7
|
+
return pattern.every((value, index) => data[index] === value);
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
exports.matchesPattern = matchesPattern;
|
|
11
|
+
const isRiffAvi = (data) => {
|
|
12
|
+
const riffPattern = new Uint8Array([0x52, 0x49, 0x46, 0x46]);
|
|
13
|
+
if (!(0, exports.matchesPattern)(riffPattern)(data.subarray(0, 4))) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
const fileType = data.subarray(8, 12);
|
|
17
|
+
const aviPattern = new Uint8Array([0x41, 0x56, 0x49, 0x20]);
|
|
18
|
+
return (0, exports.matchesPattern)(aviPattern)(fileType);
|
|
19
|
+
};
|
|
20
|
+
exports.isRiffAvi = isRiffAvi;
|
|
21
|
+
const isRiffWave = (data) => {
|
|
22
|
+
const riffPattern = new Uint8Array([0x52, 0x49, 0x46, 0x46]);
|
|
23
|
+
if (!(0, exports.matchesPattern)(riffPattern)(data.subarray(0, 4))) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const fileType = data.subarray(8, 12);
|
|
27
|
+
const wavePattern = new Uint8Array([0x57, 0x41, 0x56, 0x45]);
|
|
28
|
+
return (0, exports.matchesPattern)(wavePattern)(fileType);
|
|
29
|
+
};
|
|
30
|
+
exports.isRiffWave = isRiffWave;
|
|
31
|
+
const isWebm = (data) => {
|
|
32
|
+
return (0, exports.matchesPattern)(webmPattern)(data.subarray(0, 4));
|
|
33
|
+
};
|
|
34
|
+
exports.isWebm = isWebm;
|
|
35
|
+
const isIsoBaseMedia = (data) => {
|
|
36
|
+
const isoBaseMediaMp4Pattern = new TextEncoder().encode('ftyp');
|
|
37
|
+
return (0, exports.matchesPattern)(isoBaseMediaMp4Pattern)(data.subarray(4, 8));
|
|
38
|
+
};
|
|
39
|
+
exports.isIsoBaseMedia = isIsoBaseMedia;
|
|
40
|
+
const isTransportStream = (data) => {
|
|
41
|
+
return data[0] === 0x47 && data[188] === 0x47;
|
|
42
|
+
};
|
|
43
|
+
exports.isTransportStream = isTransportStream;
|
|
44
|
+
const isMp3 = (data) => {
|
|
45
|
+
const mpegPattern = new Uint8Array([0xff, 0xf3]);
|
|
46
|
+
const mpegPattern2 = new Uint8Array([0xff, 0xfb]);
|
|
47
|
+
const id3v4Pattern = new Uint8Array([0x49, 0x44, 0x33, 4]);
|
|
48
|
+
const id3v3Pattern = new Uint8Array([0x49, 0x44, 0x33, 3]);
|
|
49
|
+
const id3v2Pattern = new Uint8Array([0x49, 0x44, 0x33, 2]);
|
|
50
|
+
const subarray = data.subarray(0, 4);
|
|
51
|
+
return ((0, exports.matchesPattern)(mpegPattern)(subarray) ||
|
|
52
|
+
(0, exports.matchesPattern)(mpegPattern2)(subarray) ||
|
|
53
|
+
(0, exports.matchesPattern)(id3v4Pattern)(subarray) ||
|
|
54
|
+
(0, exports.matchesPattern)(id3v3Pattern)(subarray) ||
|
|
55
|
+
(0, exports.matchesPattern)(id3v2Pattern)(subarray));
|
|
56
|
+
};
|
|
57
|
+
exports.isMp3 = isMp3;
|
|
58
|
+
const isAac = (data) => {
|
|
59
|
+
const aacPattern = new Uint8Array([0xff, 0xf1]);
|
|
60
|
+
return (0, exports.matchesPattern)(aacPattern)(data.subarray(0, 2));
|
|
61
|
+
};
|
|
62
|
+
exports.isAac = isAac;
|
|
63
|
+
const isFlac = (data) => {
|
|
64
|
+
const flacPattern = new Uint8Array([0x66, 0x4c, 0x61, 0x43]);
|
|
65
|
+
return (0, exports.matchesPattern)(flacPattern)(data.subarray(0, 4));
|
|
66
|
+
};
|
|
67
|
+
exports.isFlac = isFlac;
|
|
68
|
+
const isM3u = (data) => {
|
|
69
|
+
return new TextDecoder('utf-8').decode(data.slice(0, 7)) === '#EXTM3U';
|
|
70
|
+
};
|
|
71
|
+
exports.isM3u = isM3u;
|
|
72
|
+
const getPngDimensions = (pngData) => {
|
|
73
|
+
if (pngData.length < 24) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const view = new DataView(pngData.buffer, pngData.byteOffset);
|
|
77
|
+
const pngSignature = [137, 80, 78, 71, 13, 10, 26, 10];
|
|
78
|
+
for (let i = 0; i < 8; i++) {
|
|
79
|
+
if (pngData[i] !== pngSignature[i]) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
width: view.getUint32(16, false),
|
|
85
|
+
height: view.getUint32(20, false),
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
const isPng = (data) => {
|
|
89
|
+
const pngPattern = new Uint8Array([0x89, 0x50, 0x4e, 0x47]);
|
|
90
|
+
if ((0, exports.matchesPattern)(pngPattern)(data.subarray(0, 4))) {
|
|
91
|
+
const png = getPngDimensions(data);
|
|
92
|
+
return { dimensions: png, type: 'png' };
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
};
|
|
96
|
+
const getJpegDimensions = (data) => {
|
|
97
|
+
let offset = 0;
|
|
98
|
+
const readUint16BE = (o) => {
|
|
99
|
+
return (data[o] << 8) | data[o + 1];
|
|
100
|
+
};
|
|
101
|
+
if (data.length < 4 || readUint16BE(offset) !== 0xffd8) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
offset += 2;
|
|
105
|
+
while (offset + 3 < data.length) {
|
|
106
|
+
if (data[offset] === 0xff) {
|
|
107
|
+
const marker = data[offset + 1];
|
|
108
|
+
if (marker === 0xc0 || marker === 0xc2) {
|
|
109
|
+
if (offset + 8 >= data.length) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const height = readUint16BE(offset + 5);
|
|
113
|
+
const width = readUint16BE(offset + 7);
|
|
114
|
+
return { width, height };
|
|
115
|
+
}
|
|
116
|
+
const length = readUint16BE(offset + 2);
|
|
117
|
+
if (length <= 0) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
offset += length + 2;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
offset++;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
};
|
|
128
|
+
const isJpeg = (data) => {
|
|
129
|
+
const jpegPattern = new Uint8Array([0xff, 0xd8]);
|
|
130
|
+
const jpeg = (0, exports.matchesPattern)(jpegPattern)(data.subarray(0, 2));
|
|
131
|
+
if (!jpeg) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const dim = getJpegDimensions(data);
|
|
135
|
+
return { dimensions: dim, type: 'jpeg' };
|
|
136
|
+
};
|
|
137
|
+
const getGifDimensions = (data) => {
|
|
138
|
+
if (data.length < 10) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
const view = new DataView(data.buffer, data.byteOffset);
|
|
142
|
+
const width = view.getUint16(6, true);
|
|
143
|
+
const height = view.getUint16(8, true);
|
|
144
|
+
return { width, height };
|
|
145
|
+
};
|
|
146
|
+
const isGif = (data) => {
|
|
147
|
+
const gifPattern = new Uint8Array([0x47, 0x49, 0x46, 0x38]);
|
|
148
|
+
if ((0, exports.matchesPattern)(gifPattern)(data.subarray(0, 4))) {
|
|
149
|
+
return { type: 'gif', dimensions: getGifDimensions(data) };
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
};
|
|
153
|
+
const getWebPDimensions = (bytes) => {
|
|
154
|
+
if (bytes.length < 30) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
if (bytes[0] !== 0x52 ||
|
|
158
|
+
bytes[1] !== 0x49 ||
|
|
159
|
+
bytes[2] !== 0x46 ||
|
|
160
|
+
bytes[3] !== 0x46 ||
|
|
161
|
+
bytes[8] !== 0x57 ||
|
|
162
|
+
bytes[9] !== 0x45 ||
|
|
163
|
+
bytes[10] !== 0x42 ||
|
|
164
|
+
bytes[11] !== 0x50) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
if (bytes[12] === 0x56 && bytes[13] === 0x50 && bytes[14] === 0x38) {
|
|
168
|
+
if (bytes[15] === 0x20) {
|
|
169
|
+
return {
|
|
170
|
+
width: bytes[26] | ((bytes[27] << 8) & 0x3fff),
|
|
171
|
+
height: bytes[28] | ((bytes[29] << 8) & 0x3fff),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (bytes[12] === 0x56 &&
|
|
176
|
+
bytes[13] === 0x50 &&
|
|
177
|
+
bytes[14] === 0x38 &&
|
|
178
|
+
bytes[15] === 0x4c) {
|
|
179
|
+
return {
|
|
180
|
+
width: 1 + (bytes[21] | ((bytes[22] & 0x3f) << 8)),
|
|
181
|
+
height: 1 +
|
|
182
|
+
(((bytes[22] & 0xc0) >> 6) |
|
|
183
|
+
(bytes[23] << 2) |
|
|
184
|
+
((bytes[24] & 0x0f) << 10)),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (bytes[12] === 0x56 &&
|
|
188
|
+
bytes[13] === 0x50 &&
|
|
189
|
+
bytes[14] === 0x38 &&
|
|
190
|
+
bytes[15] === 0x58) {
|
|
191
|
+
return {
|
|
192
|
+
width: 1 + (bytes[24] | (bytes[25] << 8) | (bytes[26] << 16)),
|
|
193
|
+
height: 1 + (bytes[27] | (bytes[28] << 8) | (bytes[29] << 16)),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
};
|
|
198
|
+
const isWebp = (data) => {
|
|
199
|
+
const webpPattern = new Uint8Array([0x52, 0x49, 0x46, 0x46]);
|
|
200
|
+
if ((0, exports.matchesPattern)(webpPattern)(data.subarray(0, 4))) {
|
|
201
|
+
return {
|
|
202
|
+
type: 'webp',
|
|
203
|
+
dimensions: getWebPDimensions(data),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
};
|
|
208
|
+
const getBmpDimensions = (bmpData) => {
|
|
209
|
+
if (bmpData.length < 26) {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
const view = new DataView(bmpData.buffer, bmpData.byteOffset);
|
|
213
|
+
return {
|
|
214
|
+
width: view.getUint32(18, true),
|
|
215
|
+
height: Math.abs(view.getInt32(22, true)),
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
const isBmp = (data) => {
|
|
219
|
+
const bmpPattern = new Uint8Array([0x42, 0x4d]);
|
|
220
|
+
if ((0, exports.matchesPattern)(bmpPattern)(data.subarray(0, 2))) {
|
|
221
|
+
const bmp = getBmpDimensions(data);
|
|
222
|
+
return { dimensions: bmp, type: 'bmp' };
|
|
223
|
+
}
|
|
224
|
+
return null;
|
|
225
|
+
};
|
|
226
|
+
const isPdf = (data) => {
|
|
227
|
+
if (data.length < 4) {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
const pdfPattern = new Uint8Array([0x25, 0x50, 0x44, 0x46]);
|
|
231
|
+
return (0, exports.matchesPattern)(pdfPattern)(data.subarray(0, 4)) ? { type: 'pdf' } : null;
|
|
232
|
+
};
|
|
233
|
+
const isImageFileType = (fileType) => {
|
|
234
|
+
return (fileType.type === 'jpeg' ||
|
|
235
|
+
fileType.type === 'webp' ||
|
|
236
|
+
fileType.type === 'gif' ||
|
|
237
|
+
fileType.type === 'png' ||
|
|
238
|
+
fileType.type === 'bmp');
|
|
239
|
+
};
|
|
240
|
+
exports.isImageFileType = isImageFileType;
|
|
241
|
+
const detectFileType = (data) => {
|
|
242
|
+
if ((0, exports.isRiffWave)(data)) {
|
|
243
|
+
return { type: 'wav' };
|
|
244
|
+
}
|
|
245
|
+
if ((0, exports.isRiffAvi)(data)) {
|
|
246
|
+
return { type: 'riff' };
|
|
247
|
+
}
|
|
248
|
+
if ((0, exports.isAac)(data)) {
|
|
249
|
+
return { type: 'aac' };
|
|
250
|
+
}
|
|
251
|
+
if ((0, exports.isFlac)(data)) {
|
|
252
|
+
return { type: 'flac' };
|
|
253
|
+
}
|
|
254
|
+
if ((0, exports.isM3u)(data)) {
|
|
255
|
+
return { type: 'm3u' };
|
|
256
|
+
}
|
|
257
|
+
const webp = isWebp(data);
|
|
258
|
+
if (webp) {
|
|
259
|
+
return webp;
|
|
260
|
+
}
|
|
261
|
+
if ((0, exports.isWebm)(data)) {
|
|
262
|
+
return { type: 'webm' };
|
|
263
|
+
}
|
|
264
|
+
if ((0, exports.isIsoBaseMedia)(data)) {
|
|
265
|
+
return { type: 'iso-base-media' };
|
|
266
|
+
}
|
|
267
|
+
if ((0, exports.isTransportStream)(data)) {
|
|
268
|
+
return { type: 'transport-stream' };
|
|
269
|
+
}
|
|
270
|
+
if ((0, exports.isMp3)(data)) {
|
|
271
|
+
return { type: 'mp3' };
|
|
272
|
+
}
|
|
273
|
+
const gif = isGif(data);
|
|
274
|
+
if (gif) {
|
|
275
|
+
return gif;
|
|
276
|
+
}
|
|
277
|
+
const png = isPng(data);
|
|
278
|
+
if (png) {
|
|
279
|
+
return png;
|
|
280
|
+
}
|
|
281
|
+
const pdf = isPdf(data);
|
|
282
|
+
if (pdf) {
|
|
283
|
+
return pdf;
|
|
284
|
+
}
|
|
285
|
+
const bmp = isBmp(data);
|
|
286
|
+
if (bmp) {
|
|
287
|
+
return bmp;
|
|
288
|
+
}
|
|
289
|
+
const jpeg = isJpeg(data);
|
|
290
|
+
if (jpeg) {
|
|
291
|
+
return jpeg;
|
|
292
|
+
}
|
|
293
|
+
return { type: 'unknown' };
|
|
294
|
+
};
|
|
295
|
+
exports.detectFileType = detectFileType;
|