remotion 4.1.0-alpha5 → 4.1.0-alpha8
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/cjs/Composition.d.ts +21 -6
- package/dist/cjs/Composition.js +4 -15
- package/dist/cjs/CompositionManager.d.ts +4 -4
- package/dist/cjs/Img.d.ts +1 -1
- package/dist/cjs/RemotionRoot.js +6 -4
- package/dist/cjs/ResolveCompositionConfig.js +17 -2
- package/dist/cjs/audio/Audio.d.ts +2 -2
- package/dist/cjs/audio/AudioForDevelopment.d.ts +1 -1
- package/dist/cjs/audio/AudioForRendering.d.ts +1 -1
- package/dist/cjs/config/input-props.d.ts +1 -1
- package/dist/cjs/config/input-props.js +2 -1
- package/dist/cjs/freeze.js +6 -2
- package/dist/cjs/index.d.ts +7 -4
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/input-props-serialization.d.ts +14 -0
- package/dist/cjs/input-props-serialization.js +49 -0
- package/dist/cjs/internals.d.ts +67 -58
- package/dist/cjs/internals.js +7 -0
- package/dist/cjs/loop/index.js +1 -2
- package/dist/cjs/resolve-video-config.d.ts +2 -1
- package/dist/cjs/resolve-video-config.js +20 -33
- package/dist/cjs/series/index.js +1 -2
- package/dist/cjs/spring/index.js +1 -1
- package/dist/cjs/static-file.js +11 -2
- package/dist/cjs/timeline-position-state.d.ts +5 -3
- package/dist/cjs/timeline-position-state.js +25 -7
- package/dist/cjs/validation/validate-dimensions.d.ts +1 -1
- package/dist/cjs/validation/validate-dimensions.js +2 -2
- package/dist/cjs/validation/validate-duration-in-frames.d.ts +2 -3
- package/dist/cjs/validation/validate-duration-in-frames.js +6 -2
- package/dist/cjs/validation/validate-fps.d.ts +1 -1
- package/dist/cjs/validation/validate-fps.js +2 -2
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/video/Video.d.ts +1 -1
- package/dist/cjs/video/VideoForDevelopment.d.ts +1 -1
- package/dist/cjs/video/VideoForRendering.d.ts +1 -1
- package/dist/esm/index.mjs +253 -175
- package/dist/esm/version.mjs +1 -1
- package/package.json +1 -1
package/dist/esm/index.mjs
CHANGED
|
@@ -58,7 +58,7 @@ function truthy(value) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
// Automatically generated on publish
|
|
61
|
-
const VERSION = '4.1.0-
|
|
61
|
+
const VERSION = '4.1.0-alpha8';
|
|
62
62
|
|
|
63
63
|
const checkMultipleRemotionVersions = () => {
|
|
64
64
|
if (typeof globalThis === 'undefined') {
|
|
@@ -292,6 +292,142 @@ const CompositionManager = createContext({
|
|
|
292
292
|
currentCompositionMetadata: null,
|
|
293
293
|
});
|
|
294
294
|
|
|
295
|
+
const problematicCharacters = {
|
|
296
|
+
'%3A': ':',
|
|
297
|
+
'%2F': '/',
|
|
298
|
+
'%3F': '?',
|
|
299
|
+
'%23': '#',
|
|
300
|
+
'%5B': '[',
|
|
301
|
+
'%5D': ']',
|
|
302
|
+
'%40': '@',
|
|
303
|
+
'%21': '!',
|
|
304
|
+
'%24': '$',
|
|
305
|
+
'%26': '&',
|
|
306
|
+
'%27': "'",
|
|
307
|
+
'%28': '(',
|
|
308
|
+
'%29': ')',
|
|
309
|
+
'%2A': '*',
|
|
310
|
+
'%2B': '+',
|
|
311
|
+
'%2C': ',',
|
|
312
|
+
'%3B': ';',
|
|
313
|
+
};
|
|
314
|
+
const didWarn$1 = {};
|
|
315
|
+
const warnOnce$1 = (message) => {
|
|
316
|
+
if (didWarn$1[message]) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
console.warn(message);
|
|
320
|
+
didWarn$1[message] = true;
|
|
321
|
+
};
|
|
322
|
+
const includesHexOfUnsafeChar = (path) => {
|
|
323
|
+
for (const key of Object.keys(problematicCharacters)) {
|
|
324
|
+
if (path.includes(key)) {
|
|
325
|
+
return { containsHex: true, hexCode: key };
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return { containsHex: false };
|
|
329
|
+
};
|
|
330
|
+
const trimLeadingSlash = (path) => {
|
|
331
|
+
if (path.startsWith('/')) {
|
|
332
|
+
return trimLeadingSlash(path.substring(1));
|
|
333
|
+
}
|
|
334
|
+
return path;
|
|
335
|
+
};
|
|
336
|
+
const inner = (path) => {
|
|
337
|
+
if (typeof window !== 'undefined' && window.remotion_staticBase) {
|
|
338
|
+
return `${window.remotion_staticBase}/${trimLeadingSlash(path)}`;
|
|
339
|
+
}
|
|
340
|
+
return `/${trimLeadingSlash(path)}`;
|
|
341
|
+
};
|
|
342
|
+
const encodeBySplitting = (path) => {
|
|
343
|
+
const splitBySlash = path.split('/');
|
|
344
|
+
const encodedArray = splitBySlash.map((element) => {
|
|
345
|
+
return encodeURIComponent(element);
|
|
346
|
+
});
|
|
347
|
+
const merged = encodedArray.join('/');
|
|
348
|
+
return merged;
|
|
349
|
+
};
|
|
350
|
+
/**
|
|
351
|
+
* @description Reference a file from the public/ folder. If the file does not appear in the autocomplete, type the path manually.
|
|
352
|
+
* @see [Documentation](https://www.remotion.dev/docs/staticfile)
|
|
353
|
+
*/
|
|
354
|
+
const staticFile = (path) => {
|
|
355
|
+
if (path.startsWith('http://') || path.startsWith('https://')) {
|
|
356
|
+
throw new TypeError(`staticFile() does not support remote URLs - got "${path}". Instead, pass the URL without wrapping it in staticFile(). See: https://remotion.dev/docs/staticfile-remote-urls`);
|
|
357
|
+
}
|
|
358
|
+
if (path.startsWith('..') || path.startsWith('./')) {
|
|
359
|
+
throw new TypeError(`staticFile() does not support relative paths - got "${path}". Instead, pass the name of a file that is inside the public/ folder. See: https://remotion.dev/docs/staticfile-relative-paths`);
|
|
360
|
+
}
|
|
361
|
+
if (path.startsWith('/Users') ||
|
|
362
|
+
path.startsWith('/home') ||
|
|
363
|
+
path.startsWith('/tmp') ||
|
|
364
|
+
path.startsWith('/etc') ||
|
|
365
|
+
path.startsWith('/opt') ||
|
|
366
|
+
path.startsWith('/var') ||
|
|
367
|
+
path.startsWith('C:') ||
|
|
368
|
+
path.startsWith('D:') ||
|
|
369
|
+
path.startsWith('E:')) {
|
|
370
|
+
throw new TypeError(`staticFile() does not support absolute paths - got "${path}". Instead, pass the name of a file that is inside the public/ folder. See: https://remotion.dev/docs/staticfile-relative-paths`);
|
|
371
|
+
}
|
|
372
|
+
if (path.startsWith('public/')) {
|
|
373
|
+
throw new TypeError(`Do not include the public/ prefix when using staticFile() - got "${path}". See: https://remotion.dev/docs/staticfile-relative-paths`);
|
|
374
|
+
}
|
|
375
|
+
const includesHex = includesHexOfUnsafeChar(path);
|
|
376
|
+
if (includesHex.containsHex) {
|
|
377
|
+
warnOnce$1(`WARNING: You seem to pass an already encoded path (path contains ${includesHex.hexCode}). Since Remotion 4.0, the encoding is done by staticFile() itself. You may want to remove a encodeURIComponent() wrapping.`);
|
|
378
|
+
}
|
|
379
|
+
const preprocessed = encodeBySplitting(path);
|
|
380
|
+
const preparsed = inner(preprocessed);
|
|
381
|
+
if (!preparsed.startsWith('/')) {
|
|
382
|
+
return `/${preparsed}`;
|
|
383
|
+
}
|
|
384
|
+
return preparsed;
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// Must keep this file in sync with the one in packages/lambda/src/shared/serialize-props.ts!
|
|
388
|
+
const DATE_TOKEN = 'remotion-date:';
|
|
389
|
+
const FILE_TOKEN = 'remotion-file:';
|
|
390
|
+
const serializeJSONWithDate = ({ data, indent, staticBase, }) => {
|
|
391
|
+
let customDateUsed = false;
|
|
392
|
+
let customFileUsed = false;
|
|
393
|
+
let mapUsed = false;
|
|
394
|
+
let setUsed = false;
|
|
395
|
+
const serializedString = JSON.stringify(data, function (key, value) {
|
|
396
|
+
const item = this[key];
|
|
397
|
+
if (item instanceof Date) {
|
|
398
|
+
customDateUsed = true;
|
|
399
|
+
return `${DATE_TOKEN}${item.toISOString()}`;
|
|
400
|
+
}
|
|
401
|
+
if (item instanceof Map) {
|
|
402
|
+
mapUsed = true;
|
|
403
|
+
return value;
|
|
404
|
+
}
|
|
405
|
+
if (item instanceof Set) {
|
|
406
|
+
setUsed = true;
|
|
407
|
+
return value;
|
|
408
|
+
}
|
|
409
|
+
if (typeof item === 'string' &&
|
|
410
|
+
staticBase !== null &&
|
|
411
|
+
item.startsWith(staticBase)) {
|
|
412
|
+
customFileUsed = true;
|
|
413
|
+
return `${FILE_TOKEN}${item.replace(staticBase + '/', '')}`;
|
|
414
|
+
}
|
|
415
|
+
return value;
|
|
416
|
+
}, indent);
|
|
417
|
+
return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
|
|
418
|
+
};
|
|
419
|
+
const deserializeJSONWithCustomFields = (data) => {
|
|
420
|
+
return JSON.parse(data, (_, value) => {
|
|
421
|
+
if (typeof value === 'string' && value.startsWith(DATE_TOKEN)) {
|
|
422
|
+
return new Date(value.replace(DATE_TOKEN, ''));
|
|
423
|
+
}
|
|
424
|
+
if (typeof value === 'string' && value.startsWith(FILE_TOKEN)) {
|
|
425
|
+
return staticFile(value.replace(FILE_TOKEN, ''));
|
|
426
|
+
}
|
|
427
|
+
return value;
|
|
428
|
+
});
|
|
429
|
+
};
|
|
430
|
+
|
|
295
431
|
let didWarnSSRImport = false;
|
|
296
432
|
const warnOnceSSRImport = () => {
|
|
297
433
|
if (didWarnSSRImport) {
|
|
@@ -315,7 +451,7 @@ const getInputProps = () => {
|
|
|
315
451
|
if (!param) {
|
|
316
452
|
return {};
|
|
317
453
|
}
|
|
318
|
-
const parsed =
|
|
454
|
+
const parsed = deserializeJSONWithCustomFields(param);
|
|
319
455
|
return parsed;
|
|
320
456
|
};
|
|
321
457
|
|
|
@@ -344,7 +480,7 @@ const EditorPropsProvider = ({ children }) => {
|
|
|
344
480
|
return (jsx(EditorPropsContext.Provider, { value: ctx, children: children }));
|
|
345
481
|
};
|
|
346
482
|
|
|
347
|
-
|
|
483
|
+
function validateDimension(amount, nameOfProp, location) {
|
|
348
484
|
if (typeof amount !== 'number') {
|
|
349
485
|
throw new Error(`The "${nameOfProp}" prop ${location} must be a number, but you passed a value of type ${typeof amount}`);
|
|
350
486
|
}
|
|
@@ -360,9 +496,13 @@ const validateDimension = (amount, nameOfProp, location) => {
|
|
|
360
496
|
if (amount <= 0) {
|
|
361
497
|
throw new TypeError(`The "${nameOfProp}" prop ${location} must be positive, but got ${amount}.`);
|
|
362
498
|
}
|
|
363
|
-
}
|
|
499
|
+
}
|
|
364
500
|
|
|
365
|
-
|
|
501
|
+
function validateDurationInFrames(durationInFrames, options) {
|
|
502
|
+
const { allowFloats, component } = options;
|
|
503
|
+
if (typeof durationInFrames === 'undefined') {
|
|
504
|
+
throw new Error(`The "durationInFrames" prop ${component} is missing.`);
|
|
505
|
+
}
|
|
366
506
|
if (typeof durationInFrames !== 'number') {
|
|
367
507
|
throw new Error(`The "durationInFrames" prop ${component} must be a number, but you passed a value of type ${typeof durationInFrames}`);
|
|
368
508
|
}
|
|
@@ -375,21 +515,35 @@ const validateDurationInFrames = ({ allowFloats, component, durationInFrames, })
|
|
|
375
515
|
if (!Number.isFinite(durationInFrames)) {
|
|
376
516
|
throw new TypeError(`The "durationInFrames" prop ${component} must be finite, but got ${durationInFrames}.`);
|
|
377
517
|
}
|
|
378
|
-
}
|
|
518
|
+
}
|
|
379
519
|
|
|
380
|
-
|
|
381
|
-
|
|
520
|
+
function validateFps(fps, location, isGif) {
|
|
521
|
+
if (typeof fps !== 'number') {
|
|
522
|
+
throw new Error(`"fps" must be a number, but you passed a value of type ${typeof fps} ${location}`);
|
|
523
|
+
}
|
|
524
|
+
if (!Number.isFinite(fps)) {
|
|
525
|
+
throw new Error(`"fps" must be a finite, but you passed ${fps} ${location}`);
|
|
526
|
+
}
|
|
527
|
+
if (isNaN(fps)) {
|
|
528
|
+
throw new Error(`"fps" must not be NaN, but got ${fps} ${location}`);
|
|
529
|
+
}
|
|
530
|
+
if (fps <= 0) {
|
|
531
|
+
throw new TypeError(`"fps" must be positive, but got ${fps} ${location}`);
|
|
532
|
+
}
|
|
533
|
+
if (isGif && fps > 50) {
|
|
534
|
+
throw new TypeError(`The FPS for a GIF cannot be higher than 50. Use the --every-nth-frame option to lower the FPS: https://remotion.dev/docs/render-as-gif`);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined, signal, inputProps, }) => {
|
|
539
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
382
540
|
const calculatedProm = composition.calculateMetadata
|
|
383
541
|
? composition.calculateMetadata({
|
|
384
542
|
defaultProps: (_a = composition.defaultProps) !== null && _a !== void 0 ? _a : {},
|
|
385
543
|
props: {
|
|
386
544
|
...((_b = composition.defaultProps) !== null && _b !== void 0 ? _b : {}),
|
|
387
545
|
...(editorPropsOrUndefined !== null && editorPropsOrUndefined !== void 0 ? editorPropsOrUndefined : {}),
|
|
388
|
-
...
|
|
389
|
-
getRemotionEnvironment() === 'player-development' ||
|
|
390
|
-
getRemotionEnvironment() === 'player-production'
|
|
391
|
-
? {}
|
|
392
|
-
: (_c = getInputProps()) !== null && _c !== void 0 ? _c : {}),
|
|
546
|
+
...inputProps,
|
|
393
547
|
},
|
|
394
548
|
abortSignal: signal,
|
|
395
549
|
})
|
|
@@ -422,42 +576,34 @@ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined,
|
|
|
422
576
|
return {
|
|
423
577
|
...data,
|
|
424
578
|
id: composition.id,
|
|
425
|
-
defaultProps: (
|
|
426
|
-
props:
|
|
579
|
+
defaultProps: (_c = composition.defaultProps) !== null && _c !== void 0 ? _c : {},
|
|
580
|
+
props: {
|
|
581
|
+
...((_d = composition.defaultProps) !== null && _d !== void 0 ? _d : {}),
|
|
582
|
+
...(inputProps !== null && inputProps !== void 0 ? inputProps : {}),
|
|
583
|
+
},
|
|
427
584
|
};
|
|
428
585
|
}
|
|
429
586
|
return {
|
|
430
587
|
...data,
|
|
431
588
|
id: composition.id,
|
|
432
|
-
defaultProps: (
|
|
433
|
-
props: (
|
|
589
|
+
defaultProps: (_e = composition.defaultProps) !== null && _e !== void 0 ? _e : {},
|
|
590
|
+
props: (_g = (_f = calculatedProm.props) !== null && _f !== void 0 ? _f : composition.defaultProps) !== null && _g !== void 0 ? _g : {},
|
|
434
591
|
};
|
|
435
592
|
};
|
|
436
593
|
const validateCalculated = ({ composition, calculated, }) => {
|
|
437
594
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
438
|
-
const
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
validateDimension(
|
|
444
|
-
const height = (_d = (_c = calculated === null || calculated === void 0 ? void 0 : calculated.height) !== null && _c !== void 0 ? _c : composition.height) !== null && _d !== void 0 ? _d : null;
|
|
445
|
-
if (!height) {
|
|
446
|
-
throw new TypeError('Composition height was neither specified via the `height` prop nor the `calculateMetadata()` function.');
|
|
447
|
-
}
|
|
448
|
-
validateDimension(width, 'height', potentialErrorLocation);
|
|
595
|
+
const calculateMetadataErrorLocation = `calculated by calculateMetadata() for the composition "${composition.id}"`;
|
|
596
|
+
const defaultErrorLocation = `of the "<Composition />" component with the id "${composition.id}"`;
|
|
597
|
+
const width = (_b = (_a = calculated === null || calculated === void 0 ? void 0 : calculated.width) !== null && _a !== void 0 ? _a : composition.width) !== null && _b !== void 0 ? _b : undefined;
|
|
598
|
+
validateDimension(width, 'width', (calculated === null || calculated === void 0 ? void 0 : calculated.width) ? calculateMetadataErrorLocation : defaultErrorLocation);
|
|
599
|
+
const height = (_d = (_c = calculated === null || calculated === void 0 ? void 0 : calculated.height) !== null && _c !== void 0 ? _c : composition.height) !== null && _d !== void 0 ? _d : undefined;
|
|
600
|
+
validateDimension(height, 'height', (calculated === null || calculated === void 0 ? void 0 : calculated.height) ? calculateMetadataErrorLocation : defaultErrorLocation);
|
|
449
601
|
const fps = (_f = (_e = calculated === null || calculated === void 0 ? void 0 : calculated.fps) !== null && _e !== void 0 ? _e : composition.fps) !== null && _f !== void 0 ? _f : null;
|
|
450
|
-
|
|
451
|
-
throw new TypeError('Composition fps was neither specified via the `fps` prop nor the `calculateMetadata()` function.');
|
|
452
|
-
}
|
|
602
|
+
validateFps(fps, (calculated === null || calculated === void 0 ? void 0 : calculated.fps) ? calculateMetadataErrorLocation : defaultErrorLocation, false);
|
|
453
603
|
const durationInFrames = (_h = (_g = calculated === null || calculated === void 0 ? void 0 : calculated.durationInFrames) !== null && _g !== void 0 ? _g : composition.durationInFrames) !== null && _h !== void 0 ? _h : null;
|
|
454
|
-
|
|
455
|
-
throw new TypeError('Composition durationInFrames was neither specified via the `durationInFrames` prop nor the `calculateMetadata()` function.');
|
|
456
|
-
}
|
|
457
|
-
validateDurationInFrames({
|
|
458
|
-
durationInFrames,
|
|
459
|
-
component: potentialErrorLocation,
|
|
604
|
+
validateDurationInFrames(durationInFrames, {
|
|
460
605
|
allowFloats: false,
|
|
606
|
+
component: `of the "<Composition />" component with the id "${composition.id}"`,
|
|
461
607
|
});
|
|
462
608
|
return { width, height, fps, durationInFrames };
|
|
463
609
|
};
|
|
@@ -484,12 +630,23 @@ const ResolveCompositionConfig = ({ children }) => {
|
|
|
484
630
|
: {};
|
|
485
631
|
}, [allEditorProps, renderModalComposition]);
|
|
486
632
|
const doResolution = useCallback((composition, editorProps) => {
|
|
633
|
+
var _a;
|
|
487
634
|
const controller = new AbortController();
|
|
488
635
|
if (currentCompositionMetadata) {
|
|
489
636
|
return controller;
|
|
490
637
|
}
|
|
638
|
+
const inputProps = typeof window === 'undefined' ||
|
|
639
|
+
getRemotionEnvironment() === 'player-development' ||
|
|
640
|
+
getRemotionEnvironment() === 'player-production'
|
|
641
|
+
? {}
|
|
642
|
+
: (_a = getInputProps()) !== null && _a !== void 0 ? _a : {};
|
|
491
643
|
const { signal } = controller;
|
|
492
|
-
const promOrNot = resolveVideoConfig({
|
|
644
|
+
const promOrNot = resolveVideoConfig({
|
|
645
|
+
composition,
|
|
646
|
+
editorProps,
|
|
647
|
+
inputProps,
|
|
648
|
+
signal,
|
|
649
|
+
});
|
|
493
650
|
if (typeof promOrNot === 'object' && 'then' in promOrNot) {
|
|
494
651
|
setResolvedConfigs((r) => ({
|
|
495
652
|
...r,
|
|
@@ -623,7 +780,11 @@ const useResolvedVideoConfig = (preferredCompositionId) => {
|
|
|
623
780
|
return {
|
|
624
781
|
type: 'success',
|
|
625
782
|
result: {
|
|
626
|
-
|
|
783
|
+
width: composition.width,
|
|
784
|
+
height: composition.height,
|
|
785
|
+
fps: composition.fps,
|
|
786
|
+
id: composition.id,
|
|
787
|
+
durationInFrames: composition.durationInFrames,
|
|
627
788
|
defaultProps: (_b = composition.defaultProps) !== null && _b !== void 0 ? _b : {},
|
|
628
789
|
props: {
|
|
629
790
|
...((_c = composition.defaultProps) !== null && _c !== void 0 ? _c : {}),
|
|
@@ -677,7 +838,7 @@ const useVideo = () => {
|
|
|
677
838
|
};
|
|
678
839
|
|
|
679
840
|
const TimelineContext = createContext({
|
|
680
|
-
frame:
|
|
841
|
+
frame: {},
|
|
681
842
|
playing: false,
|
|
682
843
|
playbackRate: 1,
|
|
683
844
|
rootId: '',
|
|
@@ -697,16 +858,32 @@ const SetTimelineContext = createContext({
|
|
|
697
858
|
throw new Error('default');
|
|
698
859
|
},
|
|
699
860
|
});
|
|
861
|
+
const makeKey = (composition) => {
|
|
862
|
+
return `remotion.time.${composition}`;
|
|
863
|
+
};
|
|
864
|
+
const persistCurrentFrame = (frame, composition) => {
|
|
865
|
+
localStorage.setItem(makeKey(composition), String(frame));
|
|
866
|
+
};
|
|
867
|
+
const getFrameForComposition = (composition) => {
|
|
868
|
+
var _a, _b;
|
|
869
|
+
const frame = localStorage.getItem(makeKey(composition));
|
|
870
|
+
return frame
|
|
871
|
+
? Number(frame)
|
|
872
|
+
: (_b = (typeof window === 'undefined' ? 0 : (_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0)) !== null && _b !== void 0 ? _b : 0;
|
|
873
|
+
};
|
|
700
874
|
const useTimelinePosition = () => {
|
|
875
|
+
var _a, _b;
|
|
701
876
|
const videoConfig = useVideo();
|
|
702
877
|
const state = useContext(TimelineContext);
|
|
703
|
-
// A dynamically calculated duration using calculateMetadata()
|
|
704
|
-
// may lead to the frame being bigger than the duration.
|
|
705
|
-
// If we have the config, we clamp the frame to the duration.
|
|
706
878
|
if (!videoConfig) {
|
|
707
|
-
return
|
|
879
|
+
return typeof window === 'undefined'
|
|
880
|
+
? 0
|
|
881
|
+
: (_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0;
|
|
708
882
|
}
|
|
709
|
-
|
|
883
|
+
const unclamped = (_b = state.frame[videoConfig.id]) !== null && _b !== void 0 ? _b : (typeof window !== 'undefined' && window.remotion_isPlayer
|
|
884
|
+
? 0
|
|
885
|
+
: getFrameForComposition(videoConfig.id));
|
|
886
|
+
return Math.min(videoConfig.durationInFrames - 1, unclamped);
|
|
710
887
|
};
|
|
711
888
|
const useTimelineSetFrame = () => {
|
|
712
889
|
const { setFrame } = useContext(SetTimelineContext);
|
|
@@ -722,6 +899,8 @@ var TimelinePosition = /*#__PURE__*/Object.freeze({
|
|
|
722
899
|
__proto__: null,
|
|
723
900
|
TimelineContext: TimelineContext,
|
|
724
901
|
SetTimelineContext: SetTimelineContext,
|
|
902
|
+
persistCurrentFrame: persistCurrentFrame,
|
|
903
|
+
getFrameForComposition: getFrameForComposition,
|
|
725
904
|
useTimelinePosition: useTimelinePosition,
|
|
726
905
|
useTimelineSetFrame: useTimelineSetFrame,
|
|
727
906
|
usePlayingState: usePlayingState
|
|
@@ -923,8 +1102,7 @@ const useCurrentFrame = () => {
|
|
|
923
1102
|
const Loop = ({ durationInFrames, times = Infinity, children, name, ...props }) => {
|
|
924
1103
|
const currentFrame = useCurrentFrame();
|
|
925
1104
|
const { durationInFrames: compDuration } = useVideoConfig();
|
|
926
|
-
validateDurationInFrames({
|
|
927
|
-
durationInFrames,
|
|
1105
|
+
validateDurationInFrames(durationInFrames, {
|
|
928
1106
|
component: 'of the <Loop /> component',
|
|
929
1107
|
allowFloats: true,
|
|
930
1108
|
});
|
|
@@ -1283,13 +1461,13 @@ const evaluateVolume = ({ frame, volume, mediaVolume = 1, allowAmplificationDuri
|
|
|
1283
1461
|
return Math.max(0, Math.min(maxVolume, evaluated));
|
|
1284
1462
|
};
|
|
1285
1463
|
|
|
1286
|
-
const didWarn
|
|
1287
|
-
const warnOnce
|
|
1288
|
-
if (didWarn
|
|
1464
|
+
const didWarn = {};
|
|
1465
|
+
const warnOnce = (message) => {
|
|
1466
|
+
if (didWarn[message]) {
|
|
1289
1467
|
return;
|
|
1290
1468
|
}
|
|
1291
1469
|
console.warn(message);
|
|
1292
|
-
didWarn
|
|
1470
|
+
didWarn[message] = true;
|
|
1293
1471
|
};
|
|
1294
1472
|
const useMediaInTimeline = ({ volume, mediaVolume, mediaRef, src, mediaType, playbackRate, }) => {
|
|
1295
1473
|
const videoConfig = useVideoConfig();
|
|
@@ -1327,7 +1505,7 @@ const useMediaInTimeline = ({ volume, mediaVolume, mediaRef, src, mediaType, pla
|
|
|
1327
1505
|
}, [duration, startsAt, volume, mediaVolume]);
|
|
1328
1506
|
useEffect(() => {
|
|
1329
1507
|
if (typeof volume === 'number' && volume !== initialVolume) {
|
|
1330
|
-
warnOnce
|
|
1508
|
+
warnOnce(`Remotion: The ${mediaType} with src ${src} has changed it's volume. Prefer the callback syntax for setting volume to get better timeline display: https://www.remotion.dev/docs/using-audio/#controlling-volume`);
|
|
1331
1509
|
}
|
|
1332
1510
|
}, [initialVolume, mediaType, src, volume]);
|
|
1333
1511
|
useEffect(() => {
|
|
@@ -2399,24 +2577,6 @@ const validateDefaultAndInputProps = (defaultProps, name, compositionId) => {
|
|
|
2399
2577
|
}
|
|
2400
2578
|
};
|
|
2401
2579
|
|
|
2402
|
-
const validateFps = (fps, location, isGif) => {
|
|
2403
|
-
if (typeof fps !== 'number') {
|
|
2404
|
-
throw new Error(`"fps" must be a number, but you passed a value of type ${typeof fps} ${location}`);
|
|
2405
|
-
}
|
|
2406
|
-
if (!Number.isFinite(fps)) {
|
|
2407
|
-
throw new Error(`"fps" must be a finite, but you passed ${fps} ${location}`);
|
|
2408
|
-
}
|
|
2409
|
-
if (isNaN(fps)) {
|
|
2410
|
-
throw new Error(`"fps" must not be NaN, but got ${fps} ${location}`);
|
|
2411
|
-
}
|
|
2412
|
-
if (fps <= 0) {
|
|
2413
|
-
throw new TypeError(`"fps" must be positive, but got ${fps} ${location}`);
|
|
2414
|
-
}
|
|
2415
|
-
if (isGif && fps > 50) {
|
|
2416
|
-
throw new TypeError(`The FPS for a GIF cannot be higher than 50. Use the --every-nth-frame option to lower the FPS: https://remotion.dev/docs/render-as-gif`);
|
|
2417
|
-
}
|
|
2418
|
-
};
|
|
2419
|
-
|
|
2420
2580
|
const Fallback = () => {
|
|
2421
2581
|
useEffect(() => {
|
|
2422
2582
|
const fallback = delayRender('Waiting for Root component to unsuspend');
|
|
@@ -2451,20 +2611,12 @@ const Composition = ({ width, height, fps, durationInFrames, id, defaultProps, s
|
|
|
2451
2611
|
throw new Error('No id for composition passed.');
|
|
2452
2612
|
}
|
|
2453
2613
|
validateCompositionId(id);
|
|
2454
|
-
validateDimension(width, 'width', 'of the <Composition/> component');
|
|
2455
|
-
validateDimension(height, 'height', 'of the <Composition/> component');
|
|
2456
|
-
validateDurationInFrames({
|
|
2457
|
-
durationInFrames,
|
|
2458
|
-
component: 'of the <Composition/> component',
|
|
2459
|
-
allowFloats: false,
|
|
2460
|
-
});
|
|
2461
|
-
validateFps(fps, 'as a prop of the <Composition/> component', false);
|
|
2462
2614
|
validateDefaultAndInputProps(defaultProps, 'defaultProps', id);
|
|
2463
2615
|
registerComposition({
|
|
2464
|
-
durationInFrames,
|
|
2465
|
-
fps,
|
|
2466
|
-
height,
|
|
2467
|
-
width,
|
|
2616
|
+
durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : undefined,
|
|
2617
|
+
fps: fps !== null && fps !== void 0 ? fps : undefined,
|
|
2618
|
+
height: height !== null && height !== void 0 ? height : undefined,
|
|
2619
|
+
width: width !== null && width !== void 0 ? width : undefined,
|
|
2468
2620
|
id,
|
|
2469
2621
|
folderName,
|
|
2470
2622
|
component: lazy,
|
|
@@ -2718,6 +2870,7 @@ class Easing {
|
|
|
2718
2870
|
* @see [Documentation](https://www.remotion.dev/docs/freeze)
|
|
2719
2871
|
*/
|
|
2720
2872
|
const Freeze = ({ frame, children }) => {
|
|
2873
|
+
const videoConfig = useVideoConfig();
|
|
2721
2874
|
if (typeof frame === 'undefined') {
|
|
2722
2875
|
throw new Error(`The <Freeze /> component requires a 'frame' prop, but none was passed.`);
|
|
2723
2876
|
}
|
|
@@ -2738,9 +2891,11 @@ const Freeze = ({ frame, children }) => {
|
|
|
2738
2891
|
imperativePlaying: {
|
|
2739
2892
|
current: false,
|
|
2740
2893
|
},
|
|
2741
|
-
frame
|
|
2894
|
+
frame: {
|
|
2895
|
+
[videoConfig.id]: frame,
|
|
2896
|
+
},
|
|
2742
2897
|
};
|
|
2743
|
-
}, [context, frame]);
|
|
2898
|
+
}, [context, frame, videoConfig.id]);
|
|
2744
2899
|
return (jsx(TimelineContext.Provider, { value: value, children: jsx(SequenceContext.Provider, { value: null, children: children }) }));
|
|
2745
2900
|
};
|
|
2746
2901
|
|
|
@@ -3461,9 +3616,8 @@ const waitForRoot = (fn) => {
|
|
|
3461
3616
|
};
|
|
3462
3617
|
|
|
3463
3618
|
const RemotionRoot = ({ children, numberOfAudioTags }) => {
|
|
3464
|
-
var _a;
|
|
3465
3619
|
const [remotionRootId] = useState(() => String(random(null)));
|
|
3466
|
-
const [frame, setFrame] = useState(
|
|
3620
|
+
const [frame, setFrame] = useState({});
|
|
3467
3621
|
const [playing, setPlaying] = useState(false);
|
|
3468
3622
|
const imperativePlaying = useRef(false);
|
|
3469
3623
|
const [fastRefreshes, setFastRefreshes] = useState(0);
|
|
@@ -3472,9 +3626,12 @@ const RemotionRoot = ({ children, numberOfAudioTags }) => {
|
|
|
3472
3626
|
if (typeof window !== 'undefined') {
|
|
3473
3627
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
3474
3628
|
useLayoutEffect(() => {
|
|
3475
|
-
window.remotion_setFrame = (f) => {
|
|
3629
|
+
window.remotion_setFrame = (f, composition) => {
|
|
3476
3630
|
const id = delayRender(`Setting the current frame to ${f}`);
|
|
3477
|
-
setFrame(
|
|
3631
|
+
setFrame((s) => ({
|
|
3632
|
+
...s,
|
|
3633
|
+
[composition]: f,
|
|
3634
|
+
}));
|
|
3478
3635
|
requestAnimationFrame(() => continueRender(id));
|
|
3479
3636
|
};
|
|
3480
3637
|
window.remotion_isPlayer = false;
|
|
@@ -3668,6 +3825,11 @@ const Internals = {
|
|
|
3668
3825
|
REMOTION_STUDIO_CONTAINER_ELEMENT,
|
|
3669
3826
|
AssetManager,
|
|
3670
3827
|
bundleName: 'bundle.js',
|
|
3828
|
+
persistCurrentFrame,
|
|
3829
|
+
useTimelineSetFrame,
|
|
3830
|
+
serializeJSONWithDate,
|
|
3831
|
+
deserializeJSONWithCustomFields,
|
|
3832
|
+
FILE_TOKEN,
|
|
3671
3833
|
};
|
|
3672
3834
|
|
|
3673
3835
|
const flattenChildren = (children) => {
|
|
@@ -3717,8 +3879,7 @@ const Series = ({ children }) => {
|
|
|
3717
3879
|
const { durationInFrames, children: _children, from, ...passedProps } = castedChild.props; // `from` is not accepted and must be filtered out if used in JS
|
|
3718
3880
|
if (i !== flattenedChildren.length - 1 ||
|
|
3719
3881
|
durationInFramesProp !== Infinity) {
|
|
3720
|
-
validateDurationInFrames({
|
|
3721
|
-
durationInFrames: durationInFramesProp,
|
|
3882
|
+
validateDurationInFrames(durationInFramesProp, {
|
|
3722
3883
|
component: `of a <Series.Sequence /> component`,
|
|
3723
3884
|
allowFloats: true,
|
|
3724
3885
|
});
|
|
@@ -3970,7 +4131,7 @@ function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durati
|
|
|
3970
4131
|
};
|
|
3971
4132
|
const frame = (reverse
|
|
3972
4133
|
? (passedDurationInFrames !== null && passedDurationInFrames !== void 0 ? passedDurationInFrames : naturalDurationGetter.get()) - passedFrame
|
|
3973
|
-
: passedFrame) - delay;
|
|
4134
|
+
: passedFrame) - (reverse ? -delay : delay);
|
|
3974
4135
|
const spr = springCalculation({
|
|
3975
4136
|
fps,
|
|
3976
4137
|
frame: passedDurationInFrames === undefined
|
|
@@ -3989,89 +4150,6 @@ function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durati
|
|
|
3989
4150
|
return Math.max(spr.current, to);
|
|
3990
4151
|
}
|
|
3991
4152
|
|
|
3992
|
-
const problematicCharacters = {
|
|
3993
|
-
'%3A': ':',
|
|
3994
|
-
'%2F': '/',
|
|
3995
|
-
'%3F': '?',
|
|
3996
|
-
'%23': '#',
|
|
3997
|
-
'%5B': '[',
|
|
3998
|
-
'%5D': ']',
|
|
3999
|
-
'%40': '@',
|
|
4000
|
-
'%21': '!',
|
|
4001
|
-
'%24': '$',
|
|
4002
|
-
'%26': '&',
|
|
4003
|
-
'%27': "'",
|
|
4004
|
-
'%28': '(',
|
|
4005
|
-
'%29': ')',
|
|
4006
|
-
'%2A': '*',
|
|
4007
|
-
'%2B': '+',
|
|
4008
|
-
'%2C': ',',
|
|
4009
|
-
'%3B': ';',
|
|
4010
|
-
};
|
|
4011
|
-
const didWarn = {};
|
|
4012
|
-
const warnOnce = (message) => {
|
|
4013
|
-
if (didWarn[message]) {
|
|
4014
|
-
return;
|
|
4015
|
-
}
|
|
4016
|
-
console.warn(message);
|
|
4017
|
-
didWarn[message] = true;
|
|
4018
|
-
};
|
|
4019
|
-
const includesHexOfUnsafeChar = (path) => {
|
|
4020
|
-
for (const key of Object.keys(problematicCharacters)) {
|
|
4021
|
-
if (path.includes(key)) {
|
|
4022
|
-
return { containsHex: true, hexCode: key };
|
|
4023
|
-
}
|
|
4024
|
-
}
|
|
4025
|
-
return { containsHex: false };
|
|
4026
|
-
};
|
|
4027
|
-
const trimLeadingSlash = (path) => {
|
|
4028
|
-
if (path.startsWith('/')) {
|
|
4029
|
-
return trimLeadingSlash(path.substring(1));
|
|
4030
|
-
}
|
|
4031
|
-
return path;
|
|
4032
|
-
};
|
|
4033
|
-
const inner = (path) => {
|
|
4034
|
-
if (typeof window !== 'undefined' && window.remotion_staticBase) {
|
|
4035
|
-
return `${window.remotion_staticBase}/${trimLeadingSlash(path)}`;
|
|
4036
|
-
}
|
|
4037
|
-
return `/${trimLeadingSlash(path)}`;
|
|
4038
|
-
};
|
|
4039
|
-
/**
|
|
4040
|
-
* @description Reference a file from the public/ folder. If the file does not appear in the autocomplete, type the path manually.
|
|
4041
|
-
* @see [Documentation](https://www.remotion.dev/docs/staticfile)
|
|
4042
|
-
*/
|
|
4043
|
-
const staticFile = (path) => {
|
|
4044
|
-
if (path.startsWith('http://') || path.startsWith('https://')) {
|
|
4045
|
-
throw new TypeError(`staticFile() does not support remote URLs - got "${path}". Instead, pass the URL without wrapping it in staticFile(). See: https://remotion.dev/docs/staticfile-remote-urls`);
|
|
4046
|
-
}
|
|
4047
|
-
if (path.startsWith('..') || path.startsWith('./')) {
|
|
4048
|
-
throw new TypeError(`staticFile() does not support relative paths - got "${path}". Instead, pass the name of a file that is inside the public/ folder. See: https://remotion.dev/docs/staticfile-relative-paths`);
|
|
4049
|
-
}
|
|
4050
|
-
if (path.startsWith('/Users') ||
|
|
4051
|
-
path.startsWith('/home') ||
|
|
4052
|
-
path.startsWith('/tmp') ||
|
|
4053
|
-
path.startsWith('/etc') ||
|
|
4054
|
-
path.startsWith('/opt') ||
|
|
4055
|
-
path.startsWith('/var') ||
|
|
4056
|
-
path.startsWith('C:') ||
|
|
4057
|
-
path.startsWith('D:') ||
|
|
4058
|
-
path.startsWith('E:')) {
|
|
4059
|
-
throw new TypeError(`staticFile() does not support absolute paths - got "${path}". Instead, pass the name of a file that is inside the public/ folder. See: https://remotion.dev/docs/staticfile-relative-paths`);
|
|
4060
|
-
}
|
|
4061
|
-
if (path.startsWith('public/')) {
|
|
4062
|
-
throw new TypeError(`Do not include the public/ prefix when using staticFile() - got "${path}". See: https://remotion.dev/docs/staticfile-relative-paths`);
|
|
4063
|
-
}
|
|
4064
|
-
const includesHex = includesHexOfUnsafeChar(path);
|
|
4065
|
-
if (includesHex.containsHex) {
|
|
4066
|
-
warnOnce(`WARNING: You seem to pass an already encoded path (path contains ${includesHex.hexCode}). The encoding gets automatically handled by staticFile() `);
|
|
4067
|
-
}
|
|
4068
|
-
const preparsed = inner(encodeURIComponent(path));
|
|
4069
|
-
if (!preparsed.startsWith('/')) {
|
|
4070
|
-
return `/${preparsed}`;
|
|
4071
|
-
}
|
|
4072
|
-
return preparsed;
|
|
4073
|
-
};
|
|
4074
|
-
|
|
4075
4153
|
/**
|
|
4076
4154
|
* @description A `<Still />` is a `<Composition />` that is only 1 frame long.
|
|
4077
4155
|
* @see [Documentation](https://www.remotion.dev/docs/still)
|
|
@@ -4622,7 +4700,7 @@ const Config = new Proxy(proxyObj, {
|
|
|
4622
4700
|
console.warn('+ Replace:');
|
|
4623
4701
|
console.warn('import {Config} from "@remotion/cli/config";');
|
|
4624
4702
|
console.warn();
|
|
4625
|
-
console.warn('For more information, see https://
|
|
4703
|
+
console.warn('For more information, see https://www.remotion.dev/docs/4-0-migration.');
|
|
4626
4704
|
process.exit(1);
|
|
4627
4705
|
};
|
|
4628
4706
|
},
|
package/dist/esm/version.mjs
CHANGED