remotion 4.0.177 → 4.0.178

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.
@@ -12,6 +12,7 @@ const NativeLayers_js_1 = require("./NativeLayers.js");
12
12
  const ResolveCompositionConfig_js_1 = require("./ResolveCompositionConfig.js");
13
13
  const delay_render_js_1 = require("./delay-render.js");
14
14
  const get_remotion_environment_js_1 = require("./get-remotion-environment.js");
15
+ const input_props_serialization_js_1 = require("./input-props-serialization.js");
15
16
  const is_player_js_1 = require("./is-player.js");
16
17
  const loading_indicator_js_1 = require("./loading-indicator.js");
17
18
  const nonce_js_1 = require("./nonce.js");
@@ -78,7 +79,7 @@ const Composition = ({ width, height, fps, durationInFrames, id, defaultProps, s
78
79
  id,
79
80
  folderName,
80
81
  component: lazy,
81
- defaultProps: defaultProps,
82
+ defaultProps: (0, input_props_serialization_js_1.serializeThenDeserializeInStudio)((defaultProps !== null && defaultProps !== void 0 ? defaultProps : {})),
82
83
  nonce,
83
84
  parentFolderName: parentName,
84
85
  schema: schema !== null && schema !== void 0 ? schema : null,
@@ -56,7 +56,7 @@ const ResolveCompositionConfig = ({ children }) => {
56
56
  return controller;
57
57
  }
58
58
  const { signal } = controller;
59
- const promOrNot = (0, resolve_video_config_js_1.resolveVideoConfig)({
59
+ const result = (0, resolve_video_config_js_1.resolveVideoConfigOrCatch)({
60
60
  compositionId,
61
61
  calculateMetadata,
62
62
  originalProps: combinedProps,
@@ -67,6 +67,17 @@ const ResolveCompositionConfig = ({ children }) => {
67
67
  compositionHeight,
68
68
  compositionWidth,
69
69
  });
70
+ if (result.type === 'error') {
71
+ setResolvedConfigs((r) => ({
72
+ ...r,
73
+ [compositionId]: {
74
+ type: 'error',
75
+ error: result.error,
76
+ },
77
+ }));
78
+ return controller;
79
+ }
80
+ const promOrNot = result.result;
70
81
  if (typeof promOrNot === 'object' && 'then' in promOrNot) {
71
82
  setResolvedConfigs((r) => {
72
83
  const prev = r[compositionId];
@@ -13,3 +13,4 @@ export declare const serializeJSONWithDate: ({ data, indent, staticBase, }: {
13
13
  staticBase: string | null;
14
14
  }) => SerializedJSONWithCustomFields;
15
15
  export declare const deserializeJSONWithCustomFields: <T = Record<string, unknown>>(data: string) => T;
16
+ export declare const serializeThenDeserializeInStudio: (props: Record<string, unknown>) => Record<string, unknown>;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  // Must keep this file in sync with the one in packages/lambda/src/shared/serialize-props.ts!
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.deserializeJSONWithCustomFields = exports.serializeJSONWithDate = exports.FILE_TOKEN = exports.DATE_TOKEN = void 0;
4
+ exports.serializeThenDeserializeInStudio = exports.deserializeJSONWithCustomFields = exports.serializeJSONWithDate = exports.FILE_TOKEN = exports.DATE_TOKEN = void 0;
5
+ const get_remotion_environment_js_1 = require("./get-remotion-environment.js");
5
6
  const static_file_js_1 = require("./static-file.js");
6
7
  exports.DATE_TOKEN = 'remotion-date:';
7
8
  exports.FILE_TOKEN = 'remotion-file:';
@@ -10,29 +11,35 @@ const serializeJSONWithDate = ({ data, indent, staticBase, }) => {
10
11
  let customFileUsed = false;
11
12
  let mapUsed = false;
12
13
  let setUsed = false;
13
- const serializedString = JSON.stringify(data, function (key, value) {
14
- const item = this[key];
15
- if (item instanceof Date) {
16
- customDateUsed = true;
17
- return `${exports.DATE_TOKEN}${item.toISOString()}`;
18
- }
19
- if (item instanceof Map) {
20
- mapUsed = true;
21
- return value;
22
- }
23
- if (item instanceof Set) {
24
- setUsed = true;
14
+ try {
15
+ const serializedString = JSON.stringify(data, function (key, value) {
16
+ const item = this[key];
17
+ if (item instanceof Date) {
18
+ customDateUsed = true;
19
+ return `${exports.DATE_TOKEN}${item.toISOString()}`;
20
+ }
21
+ if (item instanceof Map) {
22
+ mapUsed = true;
23
+ return value;
24
+ }
25
+ if (item instanceof Set) {
26
+ setUsed = true;
27
+ return value;
28
+ }
29
+ if (typeof item === 'string' &&
30
+ staticBase !== null &&
31
+ item.startsWith(staticBase)) {
32
+ customFileUsed = true;
33
+ return `${exports.FILE_TOKEN}${item.replace(staticBase + '/', '')}`;
34
+ }
25
35
  return value;
26
- }
27
- if (typeof item === 'string' &&
28
- staticBase !== null &&
29
- item.startsWith(staticBase)) {
30
- customFileUsed = true;
31
- return `${exports.FILE_TOKEN}${item.replace(staticBase + '/', '')}`;
32
- }
33
- return value;
34
- }, indent);
35
- return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
36
+ }, indent);
37
+ return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
38
+ }
39
+ catch (err) {
40
+ throw new Error('Could not serialize the passed input props to JSON: ' +
41
+ err.message);
42
+ }
36
43
  };
37
44
  exports.serializeJSONWithDate = serializeJSONWithDate;
38
45
  const deserializeJSONWithCustomFields = (data) => {
@@ -47,3 +54,16 @@ const deserializeJSONWithCustomFields = (data) => {
47
54
  });
48
55
  };
49
56
  exports.deserializeJSONWithCustomFields = deserializeJSONWithCustomFields;
57
+ const serializeThenDeserializeInStudio = (props) => {
58
+ // Serializing once in the Studio, to catch potential serialization errors before
59
+ // you only get them during rendering
60
+ if ((0, get_remotion_environment_js_1.getRemotionEnvironment)().isStudio) {
61
+ return (0, exports.deserializeJSONWithCustomFields)((0, exports.serializeJSONWithDate)({
62
+ data: props,
63
+ indent: 2,
64
+ staticBase: window.remotion_staticBase,
65
+ }).serializedString);
66
+ }
67
+ return props;
68
+ };
69
+ exports.serializeThenDeserializeInStudio = serializeThenDeserializeInStudio;
@@ -2,7 +2,7 @@ import type { AnyZodObject } from 'zod';
2
2
  import type { CalculateMetadataFunction } from './Composition.js';
3
3
  import type { InferProps } from './props-if-has-props.js';
4
4
  import type { VideoConfig } from './video-config.js';
5
- export declare const resolveVideoConfig: ({ calculateMetadata, signal, defaultProps, originalProps, compositionId, compositionDurationInFrames, compositionFps, compositionHeight, compositionWidth, }: {
5
+ type ResolveVideoConfigParams = {
6
6
  compositionId: string;
7
7
  compositionWidth: number | null;
8
8
  compositionHeight: number | null;
@@ -12,4 +12,13 @@ export declare const resolveVideoConfig: ({ calculateMetadata, signal, defaultPr
12
12
  signal: AbortSignal;
13
13
  defaultProps: Record<string, unknown>;
14
14
  originalProps: Record<string, unknown>;
15
- }) => VideoConfig | Promise<VideoConfig>;
15
+ };
16
+ export declare const resolveVideoConfig: ({ calculateMetadata, signal, defaultProps, originalProps, compositionId, compositionDurationInFrames, compositionFps, compositionHeight, compositionWidth, }: ResolveVideoConfigParams) => VideoConfig | Promise<VideoConfig>;
17
+ export declare const resolveVideoConfigOrCatch: (params: ResolveVideoConfigParams) => {
18
+ type: 'success';
19
+ result: VideoConfig | Promise<VideoConfig>;
20
+ } | {
21
+ type: 'error';
22
+ error: Error;
23
+ };
24
+ export {};
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveVideoConfig = void 0;
3
+ exports.resolveVideoConfigOrCatch = exports.resolveVideoConfig = void 0;
4
+ const input_props_serialization_js_1 = require("./input-props-serialization.js");
4
5
  const validate_default_codec_js_1 = require("./validation/validate-default-codec.js");
5
6
  const validate_dimensions_js_1 = require("./validation/validate-dimensions.js");
6
7
  const validate_duration_in_frames_js_1 = require("./validation/validate-duration-in-frames.js");
@@ -53,8 +54,8 @@ const resolveVideoConfig = ({ calculateMetadata, signal, defaultProps, originalP
53
54
  fps,
54
55
  durationInFrames,
55
56
  id: compositionId,
56
- defaultProps,
57
- props: (_a = c.props) !== null && _a !== void 0 ? _a : originalProps,
57
+ defaultProps: (0, input_props_serialization_js_1.serializeThenDeserializeInStudio)(defaultProps),
58
+ props: (0, input_props_serialization_js_1.serializeThenDeserializeInStudio)((_a = c.props) !== null && _a !== void 0 ? _a : originalProps),
58
59
  defaultCodec: defaultCodec !== null && defaultCodec !== void 0 ? defaultCodec : null,
59
60
  };
60
61
  });
@@ -71,17 +72,33 @@ const resolveVideoConfig = ({ calculateMetadata, signal, defaultProps, originalP
71
72
  return {
72
73
  ...data,
73
74
  id: compositionId,
74
- defaultProps: defaultProps !== null && defaultProps !== void 0 ? defaultProps : {},
75
- props: originalProps,
75
+ defaultProps: (0, input_props_serialization_js_1.serializeThenDeserializeInStudio)(defaultProps !== null && defaultProps !== void 0 ? defaultProps : {}),
76
+ props: (0, input_props_serialization_js_1.serializeThenDeserializeInStudio)(originalProps),
76
77
  defaultCodec: null,
77
78
  };
78
79
  }
79
80
  return {
80
81
  ...data,
81
82
  id: compositionId,
82
- defaultProps: defaultProps !== null && defaultProps !== void 0 ? defaultProps : {},
83
- props: (_a = calculatedProm.props) !== null && _a !== void 0 ? _a : originalProps,
83
+ defaultProps: (0, input_props_serialization_js_1.serializeThenDeserializeInStudio)(defaultProps !== null && defaultProps !== void 0 ? defaultProps : {}),
84
+ props: (0, input_props_serialization_js_1.serializeThenDeserializeInStudio)((_a = calculatedProm.props) !== null && _a !== void 0 ? _a : originalProps),
84
85
  defaultCodec: (_b = calculatedProm.defaultCodec) !== null && _b !== void 0 ? _b : null,
85
86
  };
86
87
  };
87
88
  exports.resolveVideoConfig = resolveVideoConfig;
89
+ const resolveVideoConfigOrCatch = (params) => {
90
+ try {
91
+ const promiseOrReturnValue = (0, exports.resolveVideoConfig)(params);
92
+ return {
93
+ type: 'success',
94
+ result: promiseOrReturnValue,
95
+ };
96
+ }
97
+ catch (err) {
98
+ return {
99
+ type: 'error',
100
+ error: err,
101
+ };
102
+ }
103
+ };
104
+ exports.resolveVideoConfigOrCatch = resolveVideoConfigOrCatch;
@@ -28,7 +28,8 @@ const react_1 = __importStar(require("react"));
28
28
  // Expected, it can be any component props
29
29
  const useLazyComponent = (compProps) => {
30
30
  const lazy = (0, react_1.useMemo)(() => {
31
- if ('lazyComponent' in compProps) {
31
+ if ('lazyComponent' in compProps &&
32
+ typeof compProps.lazyComponent !== 'undefined') {
32
33
  return react_1.default.lazy(compProps.lazyComponent);
33
34
  }
34
35
  if ('component' in compProps) {
@@ -3,4 +3,4 @@
3
3
  * @see [Documentation](https://remotion.dev/docs/version)
4
4
  * @returns {string} The current version of the remotion package
5
5
  */
6
- export declare const VERSION = "4.0.177";
6
+ export declare const VERSION = "4.0.178";
@@ -7,4 +7,4 @@ exports.VERSION = void 0;
7
7
  * @see [Documentation](https://remotion.dev/docs/version)
8
8
  * @returns {string} The current version of the remotion package
9
9
  */
10
- exports.VERSION = '4.0.177';
10
+ exports.VERSION = '4.0.178';
@@ -102,9 +102,9 @@ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate,
102
102
  toneMapped,
103
103
  });
104
104
  }, [toneMapped, currentTime, src, transparent]);
105
- const onErr = (0, react_1.useCallback)((e) => {
105
+ const onErr = (0, react_1.useCallback)(() => {
106
106
  if (onError) {
107
- onError === null || onError === void 0 ? void 0 : onError(e);
107
+ onError === null || onError === void 0 ? void 0 : onError(new Error('Failed to load image with src ' + actualSrc));
108
108
  }
109
109
  else {
110
110
  (0, cancel_render_js_1.cancelRender)('Failed to load image with src ' + actualSrc);
@@ -4,7 +4,7 @@ import type { RemotionMainVideoProps } from './props';
4
4
  * @description allows you to include a video file in your Remotion project. It wraps the native HTMLVideoElement.
5
5
  * @see [Documentation](https://www.remotion.dev/docs/video)
6
6
  */
7
- export declare const Video: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>, "nonce" | "onEnded" | "autoPlay" | "controls"> & {
7
+ export declare const Video: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>, "nonce" | "onError" | "onEnded" | "autoPlay" | "controls"> & {
8
8
  name?: string | undefined;
9
9
  volume?: import("../volume-prop.js").VolumeProp | undefined;
10
10
  playbackRate?: number | undefined;
@@ -16,6 +16,7 @@ export declare const Video: React.ForwardRefExoticComponent<Omit<Omit<React.Deta
16
16
  delayRenderTimeoutInMilliseconds?: number | undefined;
17
17
  loopVolumeCurveBehavior?: import("../audio/use-audio-frame.js").LoopVolumeCurveBehavior | undefined;
18
18
  delayRenderRetries?: number | undefined;
19
+ onError?: ((err: Error) => void) | undefined;
19
20
  } & RemotionMainVideoProps & {
20
21
  /**
21
22
  * @deprecated For internal use only
@@ -19,7 +19,7 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
19
19
  const videoRef = (0, react_1.useRef)(null);
20
20
  const { volume, muted, playbackRate, onlyWarnForMediaSeekingError, src, onDuration,
21
21
  // @ts-expect-error
22
- acceptableTimeShift, acceptableTimeShiftInSeconds, toneFrequency, name, _remotionInternalNativeLoopPassed, _remotionInternalStack, _remotionDebugSeeking, style, pauseWhenBuffering, showInTimeline, loopVolumeCurveBehavior, ...nativeProps } = props;
22
+ acceptableTimeShift, acceptableTimeShiftInSeconds, toneFrequency, name, _remotionInternalNativeLoopPassed, _remotionInternalStack, _remotionDebugSeeking, style, pauseWhenBuffering, showInTimeline, loopVolumeCurveBehavior, onError, ...nativeProps } = props;
23
23
  const volumePropFrame = (0, use_audio_frame_js_1.useFrameForVolumeProp)(loopVolumeCurveBehavior !== null && loopVolumeCurveBehavior !== void 0 ? loopVolumeCurveBehavior : 'repeat');
24
24
  const { fps, durationInFrames } = (0, use_video_config_js_1.useVideoConfig)();
25
25
  const parentSequence = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
@@ -83,24 +83,32 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
83
83
  }
84
84
  const errorHandler = () => {
85
85
  var _a;
86
- if (current === null || current === void 0 ? void 0 : current.error) {
86
+ if (current.error) {
87
87
  // eslint-disable-next-line no-console
88
88
  console.error('Error occurred in video', current === null || current === void 0 ? void 0 : current.error);
89
89
  // If user is handling the error, we don't cause an unhandled exception
90
- if (props.onError) {
90
+ if (onError) {
91
+ const err = new Error(`Code ${current.error.code}: ${current.error.message}`);
92
+ onError(err);
91
93
  return;
92
94
  }
93
95
  throw new Error(`The browser threw an error while playing the video ${src}: Code ${current.error.code} - ${(_a = current === null || current === void 0 ? void 0 : current.error) === null || _a === void 0 ? void 0 : _a.message}. See https://remotion.dev/docs/media-playback-error for help. Pass an onError() prop to handle the error.`);
94
96
  }
95
97
  else {
96
- throw new Error('The browser threw an error');
98
+ // If user is handling the error, we don't cause an unhandled exception
99
+ if (onError) {
100
+ const err = new Error(`The browser threw an error while playing the video ${src}`);
101
+ onError(err);
102
+ return;
103
+ }
104
+ throw new Error('The browser threw an error while playing the video');
97
105
  }
98
106
  };
99
107
  current.addEventListener('error', errorHandler, { once: true });
100
108
  return () => {
101
109
  current.removeEventListener('error', errorHandler);
102
110
  };
103
- }, [props.onError, src]);
111
+ }, [onError, src]);
104
112
  const currentOnDurationCallback = (0, react_1.useRef)();
105
113
  currentOnDurationCallback.current = onDuration;
106
114
  (0, react_1.useEffect)(() => {
@@ -1,6 +1,6 @@
1
1
  import type { ForwardRefExoticComponent, RefAttributes } from 'react';
2
2
  import React from 'react';
3
- export declare const VideoForRendering: ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>, "nonce" | "onEnded" | "autoPlay" | "controls"> & {
3
+ export declare const VideoForRendering: ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>, "nonce" | "onError" | "onEnded" | "autoPlay" | "controls"> & {
4
4
  name?: string | undefined;
5
5
  volume?: import("../volume-prop.js").VolumeProp | undefined;
6
6
  playbackRate?: number | undefined;
@@ -12,6 +12,7 @@ export declare const VideoForRendering: ForwardRefExoticComponent<Omit<React.Det
12
12
  delayRenderTimeoutInMilliseconds?: number | undefined;
13
13
  loopVolumeCurveBehavior?: import("../audio/use-audio-frame.js").LoopVolumeCurveBehavior | undefined;
14
14
  delayRenderRetries?: number | undefined;
15
+ onError?: ((err: Error) => void) | undefined;
15
16
  } & {
16
17
  readonly onDuration: (src: string, durationInSeconds: number) => void;
17
18
  } & RefAttributes<HTMLVideoElement>>;
@@ -203,6 +203,6 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
203
203
  };
204
204
  }, [src, onDuration, delayRenderRetries, delayRenderTimeoutInMilliseconds]);
205
205
  }
206
- return (0, jsx_runtime_1.jsx)("video", { ref: videoRef, ...props, onError: onError });
206
+ return (0, jsx_runtime_1.jsx)("video", { ref: videoRef, ...props });
207
207
  };
208
208
  exports.VideoForRendering = (0, react_1.forwardRef)(VideoForRenderingForwardFunction);
@@ -10,7 +10,7 @@ export type RemotionMainVideoProps = {
10
10
  _remotionInternalNativeLoopPassed?: boolean;
11
11
  _remotionDebugSeeking?: boolean;
12
12
  };
13
- export type RemotionVideoProps = Omit<React.DetailedHTMLProps<React.VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>, 'autoPlay' | 'controls' | 'onEnded' | 'nonce'> & {
13
+ export type RemotionVideoProps = Omit<React.DetailedHTMLProps<React.VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>, 'autoPlay' | 'controls' | 'onEnded' | 'nonce' | 'onError'> & {
14
14
  name?: string;
15
15
  volume?: VolumeProp;
16
16
  playbackRate?: number;
@@ -22,6 +22,7 @@ export type RemotionVideoProps = Omit<React.DetailedHTMLProps<React.VideoHTMLAtt
22
22
  delayRenderTimeoutInMilliseconds?: number;
23
23
  loopVolumeCurveBehavior?: LoopVolumeCurveBehavior;
24
24
  delayRenderRetries?: number;
25
+ onError?: (err: Error) => void;
25
26
  };
26
27
  type DeprecatedOffthreadVideoProps = {
27
28
  /**
@@ -38,7 +39,7 @@ export type OffthreadVideoProps = {
38
39
  volume?: VolumeProp;
39
40
  playbackRate?: number;
40
41
  muted?: boolean;
41
- onError?: React.ReactEventHandler<HTMLVideoElement | HTMLImageElement>;
42
+ onError?: (err: Error) => void;
42
43
  acceptableTimeShiftInSeconds?: number;
43
44
  allowAmplificationDuringRender?: boolean;
44
45
  toneFrequency?: number;
@@ -47,6 +48,7 @@ export type OffthreadVideoProps = {
47
48
  pauseWhenBuffering?: boolean;
48
49
  loopVolumeCurveBehavior?: LoopVolumeCurveBehavior;
49
50
  delayRenderTimeoutInMilliseconds?: number;
51
+ delayRenderRetries?: number;
50
52
  /**
51
53
  * @deprecated For internal use only
52
54
  */
@@ -138,7 +138,7 @@ function truthy(value) {
138
138
  }
139
139
 
140
140
  // src/version.ts
141
- var VERSION = "4.0.177";
141
+ var VERSION = "4.0.178";
142
142
 
143
143
  // src/multiple-versions-warning.ts
144
144
  var checkMultipleRemotionVersions = () => {
@@ -527,6 +527,41 @@ var staticFile = (path) => {
527
527
  // src/input-props-serialization.ts
528
528
  var DATE_TOKEN = "remotion-date:";
529
529
  var FILE_TOKEN = "remotion-file:";
530
+ var serializeJSONWithDate = ({
531
+ data,
532
+ indent,
533
+ staticBase
534
+ }) => {
535
+ let customDateUsed = false;
536
+ let customFileUsed = false;
537
+ let mapUsed = false;
538
+ let setUsed = false;
539
+ try {
540
+ const serializedString = JSON.stringify(data, function(key, value) {
541
+ const item = this[key];
542
+ if (item instanceof Date) {
543
+ customDateUsed = true;
544
+ return `${DATE_TOKEN}${item.toISOString()}`;
545
+ }
546
+ if (item instanceof Map) {
547
+ mapUsed = true;
548
+ return value;
549
+ }
550
+ if (item instanceof Set) {
551
+ setUsed = true;
552
+ return value;
553
+ }
554
+ if (typeof item === "string" && staticBase !== null && item.startsWith(staticBase)) {
555
+ customFileUsed = true;
556
+ return `${FILE_TOKEN}${item.replace(staticBase + "/", "")}`;
557
+ }
558
+ return value;
559
+ }, indent);
560
+ return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
561
+ } catch (err) {
562
+ throw new Error("Could not serialize the passed input props to JSON: " + err.message);
563
+ }
564
+ };
530
565
  var deserializeJSONWithCustomFields = (data) => {
531
566
  return JSON.parse(data, (_, value) => {
532
567
  if (typeof value === "string" && value.startsWith(DATE_TOKEN)) {
@@ -538,6 +573,16 @@ var deserializeJSONWithCustomFields = (data) => {
538
573
  return value;
539
574
  });
540
575
  };
576
+ var serializeThenDeserializeInStudio = (props) => {
577
+ if (getRemotionEnvironment().isStudio) {
578
+ return deserializeJSONWithCustomFields(serializeJSONWithDate({
579
+ data: props,
580
+ indent: 2,
581
+ staticBase: window.remotion_staticBase
582
+ }).serializedString);
583
+ }
584
+ return props;
585
+ };
541
586
 
542
587
  // src/config/input-props.ts
543
588
  var didWarnSSRImport = false;
@@ -711,8 +756,8 @@ var resolveVideoConfig = ({
711
756
  fps,
712
757
  durationInFrames,
713
758
  id: compositionId,
714
- defaultProps,
715
- props: c.props ?? originalProps,
759
+ defaultProps: serializeThenDeserializeInStudio(defaultProps),
760
+ props: serializeThenDeserializeInStudio(c.props ?? originalProps),
716
761
  defaultCodec: defaultCodec ?? null
717
762
  };
718
763
  });
@@ -729,19 +774,33 @@ var resolveVideoConfig = ({
729
774
  return {
730
775
  ...data,
731
776
  id: compositionId,
732
- defaultProps: defaultProps ?? {},
733
- props: originalProps,
777
+ defaultProps: serializeThenDeserializeInStudio(defaultProps ?? {}),
778
+ props: serializeThenDeserializeInStudio(originalProps),
734
779
  defaultCodec: null
735
780
  };
736
781
  }
737
782
  return {
738
783
  ...data,
739
784
  id: compositionId,
740
- defaultProps: defaultProps ?? {},
741
- props: calculatedProm.props ?? originalProps,
785
+ defaultProps: serializeThenDeserializeInStudio(defaultProps ?? {}),
786
+ props: serializeThenDeserializeInStudio(calculatedProm.props ?? originalProps),
742
787
  defaultCodec: calculatedProm.defaultCodec ?? null
743
788
  };
744
789
  };
790
+ var resolveVideoConfigOrCatch = (params) => {
791
+ try {
792
+ const promiseOrReturnValue = resolveVideoConfig(params);
793
+ return {
794
+ type: "success",
795
+ result: promiseOrReturnValue
796
+ };
797
+ } catch (err) {
798
+ return {
799
+ type: "error",
800
+ error: err
801
+ };
802
+ }
803
+ };
745
804
 
746
805
  // src/ResolveCompositionConfig.tsx
747
806
  import {
@@ -788,7 +847,7 @@ var ResolveCompositionConfig = ({ children }) => {
788
847
  return controller;
789
848
  }
790
849
  const { signal } = controller;
791
- const promOrNot = resolveVideoConfig({
850
+ const result = resolveVideoConfigOrCatch({
792
851
  compositionId,
793
852
  calculateMetadata,
794
853
  originalProps: combinedProps,
@@ -799,6 +858,17 @@ var ResolveCompositionConfig = ({ children }) => {
799
858
  compositionHeight,
800
859
  compositionWidth
801
860
  });
861
+ if (result.type === "error") {
862
+ setResolvedConfigs((r) => ({
863
+ ...r,
864
+ [compositionId]: {
865
+ type: "error",
866
+ error: result.error
867
+ }
868
+ }));
869
+ return controller;
870
+ }
871
+ const promOrNot = result.result;
802
872
  if (typeof promOrNot === "object" && "then" in promOrNot) {
803
873
  setResolvedConfigs((r) => {
804
874
  const prev = r[compositionId];
@@ -3825,7 +3895,7 @@ var portalNode = () => {
3825
3895
  import React16, {useMemo as useMemo23} from "react";
3826
3896
  var useLazyComponent = (compProps) => {
3827
3897
  const lazy = useMemo23(() => {
3828
- if ("lazyComponent" in compProps) {
3898
+ if ("lazyComponent" in compProps && typeof compProps.lazyComponent !== "undefined") {
3829
3899
  return React16.lazy(compProps.lazyComponent);
3830
3900
  }
3831
3901
  if ("component" in compProps) {
@@ -3926,7 +3996,7 @@ var Composition = ({
3926
3996
  id,
3927
3997
  folderName,
3928
3998
  component: lazy,
3929
- defaultProps,
3999
+ defaultProps: serializeThenDeserializeInStudio(defaultProps ?? {}),
3930
4000
  nonce: nonce5,
3931
4001
  parentFolderName: parentName,
3932
4002
  schema: schema ?? null,
@@ -5786,9 +5856,9 @@ var OffthreadVideoForRendering = ({
5786
5856
  toneMapped
5787
5857
  });
5788
5858
  }, [toneMapped, currentTime, src, transparent]);
5789
- const onErr = useCallback13((e) => {
5859
+ const onErr = useCallback13(() => {
5790
5860
  if (onError) {
5791
- onError?.(e);
5861
+ onError?.(new Error("Failed to load image with src " + actualSrc));
5792
5862
  } else {
5793
5863
  cancelRender("Failed to load image with src " + actualSrc);
5794
5864
  }
@@ -5837,6 +5907,7 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
5837
5907
  pauseWhenBuffering,
5838
5908
  showInTimeline,
5839
5909
  loopVolumeCurveBehavior,
5910
+ onError,
5840
5911
  ...nativeProps
5841
5912
  } = props2;
5842
5913
  const volumePropFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
@@ -5899,21 +5970,28 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
5899
5970
  return;
5900
5971
  }
5901
5972
  const errorHandler = () => {
5902
- if (current?.error) {
5973
+ if (current.error) {
5903
5974
  console.error("Error occurred in video", current?.error);
5904
- if (props2.onError) {
5975
+ if (onError) {
5976
+ const err = new Error(`Code ${current.error.code}: ${current.error.message}`);
5977
+ onError(err);
5905
5978
  return;
5906
5979
  }
5907
5980
  throw new Error(`The browser threw an error while playing the video ${src}: Code ${current.error.code} - ${current?.error?.message}. See https://remotion.dev/docs/media-playback-error for help. Pass an onError() prop to handle the error.`);
5908
5981
  } else {
5909
- throw new Error("The browser threw an error");
5982
+ if (onError) {
5983
+ const err = new Error(`The browser threw an error while playing the video ${src}`);
5984
+ onError(err);
5985
+ return;
5986
+ }
5987
+ throw new Error("The browser threw an error while playing the video");
5910
5988
  }
5911
5989
  };
5912
5990
  current.addEventListener("error", errorHandler, { once: true });
5913
5991
  return () => {
5914
5992
  current.removeEventListener("error", errorHandler);
5915
5993
  };
5916
- }, [props2.onError, src]);
5994
+ }, [onError, src]);
5917
5995
  const currentOnDurationCallback = useRef13();
5918
5996
  currentOnDurationCallback.current = onDuration;
5919
5997
  useEffect22(() => {
@@ -6314,8 +6392,7 @@ var VideoForRenderingForwardFunction = ({
6314
6392
  }
6315
6393
  return jsx32("video", {
6316
6394
  ref: videoRef,
6317
- ...props2,
6318
- onError
6395
+ ...props2
6319
6396
  });
6320
6397
  };
6321
6398
  var VideoForRendering = forwardRef10(VideoForRenderingForwardFunction);
@@ -245,27 +245,31 @@ var serializeJSONWithDate = ({
245
245
  let customFileUsed = false;
246
246
  let mapUsed = false;
247
247
  let setUsed = false;
248
- const serializedString = JSON.stringify(data, function(key, value) {
249
- const item = this[key];
250
- if (item instanceof Date) {
251
- customDateUsed = true;
252
- return `${DATE_TOKEN}${item.toISOString()}`;
253
- }
254
- if (item instanceof Map) {
255
- mapUsed = true;
256
- return value;
257
- }
258
- if (item instanceof Set) {
259
- setUsed = true;
248
+ try {
249
+ const serializedString = JSON.stringify(data, function(key, value) {
250
+ const item = this[key];
251
+ if (item instanceof Date) {
252
+ customDateUsed = true;
253
+ return `${DATE_TOKEN}${item.toISOString()}`;
254
+ }
255
+ if (item instanceof Map) {
256
+ mapUsed = true;
257
+ return value;
258
+ }
259
+ if (item instanceof Set) {
260
+ setUsed = true;
261
+ return value;
262
+ }
263
+ if (typeof item === "string" && staticBase !== null && item.startsWith(staticBase)) {
264
+ customFileUsed = true;
265
+ return `${FILE_TOKEN}${item.replace(staticBase + "/", "")}`;
266
+ }
260
267
  return value;
261
- }
262
- if (typeof item === "string" && staticBase !== null && item.startsWith(staticBase)) {
263
- customFileUsed = true;
264
- return `${FILE_TOKEN}${item.replace(staticBase + "/", "")}`;
265
- }
266
- return value;
267
- }, indent);
268
- return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
268
+ }, indent);
269
+ return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
270
+ } catch (err) {
271
+ throw new Error("Could not serialize the passed input props to JSON: " + err.message);
272
+ }
269
273
  };
270
274
  var deserializeJSONWithCustomFields = (data) => {
271
275
  return JSON.parse(data, (_, value) => {
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "4.0.177";
2
+ var VERSION = "4.0.178";
3
3
  export {
4
4
  VERSION
5
5
  };
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
+ "repository": {
3
+ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/core"
4
+ },
2
5
  "name": "remotion",
3
- "version": "4.0.177",
4
- "description": "Render videos in React",
6
+ "version": "4.0.178",
7
+ "description": "Make videos programmatically",
5
8
  "main": "dist/cjs/index.js",
6
9
  "types": "dist/cjs/index.d.ts",
7
10
  "module": "dist/esm/index.mjs",
8
- "repository": {
9
- "url": "https://github.com/remotion-dev/remotion"
10
- },
11
11
  "bugs": {
12
12
  "url": "https://github.com/remotion-dev/remotion/issues"
13
13
  },
@@ -18,18 +18,10 @@
18
18
  "react-dom": ">=16.8.0"
19
19
  },
20
20
  "devDependencies": {
21
- "@jonny/eslint-config": "3.0.281",
22
21
  "@testing-library/react": "14.0.0",
23
22
  "@happy-dom/global-registrator": "14.5.1",
24
23
  "happy-dom": "14.5.1",
25
- "@types/node": "18.14.6",
26
- "@types/react": "18.3.1",
27
- "@types/react-dom": "18.3.0",
28
- "eslint": "8.56.0",
29
- "eslint-plugin-require-extensions": "^0.1.2",
30
24
  "jsdom": "21.1.0",
31
- "prettier": "3.2.5",
32
- "prettier-plugin-organize-imports": "3.2.4",
33
25
  "react": "18.3.1",
34
26
  "react-dom": "18.3.1",
35
27
  "vitest": "0.31.1",
@@ -77,6 +69,7 @@
77
69
  ]
78
70
  }
79
71
  },
72
+ "homepage": "https://www.remotion.dev/docs/remotion",
80
73
  "scripts": {
81
74
  "formatting": "prettier src --check",
82
75
  "lint": "eslint src --ext ts,tsx",