remotion 4.0.327 → 4.0.329

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.
@@ -82,6 +82,7 @@ export * from './AbsoluteFill.js';
82
82
  export * from './animated-image/index.js';
83
83
  export { Artifact } from './Artifact.js';
84
84
  export * from './audio/index.js';
85
+ export type { LoopVolumeCurveBehavior } from './audio/use-audio-frame.js';
85
86
  export { cancelRender } from './cancel-render.js';
86
87
  export { CalculateMetadataFunction, Composition, CompositionProps, CompProps, StillProps, } from './Composition.js';
87
88
  export type { CanvasContent } from './CompositionManagerContext.js';
@@ -116,6 +117,8 @@ export * from './use-video-config.js';
116
117
  export * from './version.js';
117
118
  export * from './video-config.js';
118
119
  export * from './video/index.js';
120
+ export type { OnVideoFrame } from './video/props.js';
121
+ export type { VolumeProp } from './volume-prop.js';
119
122
  export { watchStaticFile } from './watch-static-file.js';
120
123
  export declare const Experimental: {
121
124
  /**
@@ -13,7 +13,56 @@ import type { WatchRemotionStaticFilesPayload } from './watch-static-file.js';
13
13
  import { useRemotionContexts } from './wrap-remotion-context.js';
14
14
  export declare const Internals: {
15
15
  readonly useUnsafeVideoConfig: () => import("./video-config.js").VideoConfig | null;
16
+ readonly useFrameForVolumeProp: (behavior: import("./audio/use-audio-frame.js").LoopVolumeCurveBehavior) => number;
17
+ readonly useTimelinePosition: () => number;
18
+ readonly evaluateVolume: ({ frame, volume, mediaVolume, }: {
19
+ frame: number;
20
+ volume: import("./volume-prop.js").VolumeProp | undefined;
21
+ mediaVolume: number;
22
+ }) => number;
23
+ readonly getAbsoluteSrc: (relativeSrc: string) => string;
16
24
  readonly Timeline: typeof TimelinePosition;
25
+ readonly validateMediaTrimProps: ({ startFrom, endAt, trimBefore, trimAfter, }: {
26
+ startFrom: number | undefined;
27
+ endAt: number | undefined;
28
+ trimBefore: number | undefined;
29
+ trimAfter: number | undefined;
30
+ }) => void;
31
+ readonly validateMediaProps: (props: import("./index.js").RemotionVideoProps | import("./index.js").RemotionAudioProps | import("./index.js").OffthreadVideoProps, component: "Video" | "Audio") => void;
32
+ readonly resolveTrimProps: ({ startFrom, endAt, trimBefore, trimAfter, }: {
33
+ startFrom: number | undefined;
34
+ endAt: number | undefined;
35
+ trimBefore: number | undefined;
36
+ trimAfter: number | undefined;
37
+ }) => {
38
+ trimBeforeValue: number | undefined;
39
+ trimAfterValue: number | undefined;
40
+ };
41
+ readonly VideoForPreview: import("react").ForwardRefExoticComponent<Omit<import("./video/props.js").NativeVideoProps & {
42
+ name?: string;
43
+ volume?: import("./volume-prop.js").VolumeProp;
44
+ playbackRate?: number;
45
+ acceptableTimeShiftInSeconds?: number;
46
+ allowAmplificationDuringRender?: boolean;
47
+ useWebAudioApi?: boolean;
48
+ toneFrequency?: number;
49
+ pauseWhenBuffering?: boolean;
50
+ showInTimeline?: boolean;
51
+ delayRenderTimeoutInMilliseconds?: number;
52
+ loopVolumeCurveBehavior?: import("./audio/use-audio-frame.js").LoopVolumeCurveBehavior;
53
+ delayRenderRetries?: number;
54
+ onError?: (err: Error) => void;
55
+ onAutoPlayError?: null | (() => void);
56
+ } & {
57
+ readonly onlyWarnForMediaSeekingError: boolean;
58
+ readonly onDuration: (src: string, durationInSeconds: number) => void;
59
+ readonly pauseWhenBuffering: boolean;
60
+ readonly _remotionInternalNativeLoopPassed: boolean;
61
+ readonly _remotionInternalStack: string | null;
62
+ readonly showInTimeline: boolean;
63
+ readonly onVideoFrame: null | import("./index.js").OnVideoFrame;
64
+ readonly crossOrigin?: "" | "anonymous" | "use-credentials";
65
+ }, "ref"> & import("react").RefAttributes<HTMLVideoElement>>;
17
66
  readonly CompositionManager: import("react").Context<CompositionManagerContext>;
18
67
  readonly CompositionSetters: import("react").Context<import("./CompositionManagerContext.js").CompositionManagerSetters>;
19
68
  readonly SequenceManager: import("react").Context<import("./SequenceManager.js").SequenceManagerContext>;
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.Internals = void 0;
37
37
  const react_1 = require("react");
38
+ const absolute_src_js_1 = require("./absolute-src.js");
38
39
  const shared_audio_tags_js_1 = require("./audio/shared-audio-tags.js");
39
40
  const use_audio_frame_js_1 = require("./audio/use-audio-frame.js");
40
41
  const buffering_js_1 = require("./buffering.js");
@@ -69,11 +70,15 @@ const use_current_scale_js_1 = require("./use-current-scale.js");
69
70
  const use_lazy_component_js_1 = require("./use-lazy-component.js");
70
71
  const use_unsafe_video_config_js_1 = require("./use-unsafe-video-config.js");
71
72
  const use_video_js_1 = require("./use-video.js");
73
+ const validate_media_props_js_1 = require("./validate-media-props.js");
74
+ const validate_start_from_props_js_1 = require("./validate-start-from-props.js");
72
75
  const validate_artifact_js_1 = require("./validation/validate-artifact.js");
73
76
  const validate_composition_id_js_1 = require("./validation/validate-composition-id.js");
74
77
  const duration_state_js_1 = require("./video/duration-state.js");
75
78
  const video_fragment_js_1 = require("./video/video-fragment.js");
79
+ const VideoForPreview_js_1 = require("./video/VideoForPreview.js");
76
80
  const volume_position_state_js_1 = require("./volume-position-state.js");
81
+ const volume_prop_js_1 = require("./volume-prop.js");
77
82
  const watch_static_file_js_1 = require("./watch-static-file.js");
78
83
  const wrap_remotion_context_js_1 = require("./wrap-remotion-context.js");
79
84
  // needs to be in core package so gets deduplicated in studio
@@ -82,7 +87,15 @@ const compositionSelectorRef = (0, react_1.createRef)();
82
87
  // API and are less likely to use it
83
88
  exports.Internals = {
84
89
  useUnsafeVideoConfig: use_unsafe_video_config_js_1.useUnsafeVideoConfig,
90
+ useFrameForVolumeProp: use_audio_frame_js_1.useFrameForVolumeProp,
91
+ useTimelinePosition: TimelinePosition.useTimelinePosition,
92
+ evaluateVolume: volume_prop_js_1.evaluateVolume,
93
+ getAbsoluteSrc: absolute_src_js_1.getAbsoluteSrc,
85
94
  Timeline: TimelinePosition,
95
+ validateMediaTrimProps: validate_start_from_props_js_1.validateMediaTrimProps,
96
+ validateMediaProps: validate_media_props_js_1.validateMediaProps,
97
+ resolveTrimProps: validate_start_from_props_js_1.resolveTrimProps,
98
+ VideoForPreview: VideoForPreview_js_1.VideoForPreview,
86
99
  CompositionManager: CompositionManagerContext_js_1.CompositionManager,
87
100
  CompositionSetters: CompositionManagerContext_js_1.CompositionSetters,
88
101
  SequenceManager: SequenceManager_js_1.SequenceManager,
@@ -5,6 +5,7 @@ export { random, RandomSeed } from './random.js';
5
5
  export type { VideoConfig } from './video-config';
6
6
  import { processColor } from './interpolate-colors';
7
7
  import { truthy } from './truthy';
8
+ import { validateCodec } from './validation/validate-default-codec';
8
9
  import { validateDimension } from './validation/validate-dimensions';
9
10
  import { validateDurationInFrames } from './validation/validate-duration-in-frames';
10
11
  import { validateFps } from './validation/validate-fps';
@@ -51,4 +52,5 @@ export declare const NoReactInternals: {
51
52
  };
52
53
  DATE_TOKEN: string;
53
54
  FILE_TOKEN: string;
55
+ validateCodec: typeof validateCodec;
54
56
  };
@@ -12,6 +12,7 @@ const interpolate_colors_1 = require("./interpolate-colors");
12
12
  const truthy_1 = require("./truthy");
13
13
  const v5_flag_1 = require("./v5-flag");
14
14
  const validate_frame_1 = require("./validate-frame");
15
+ const validate_default_codec_1 = require("./validation/validate-default-codec");
15
16
  const validate_default_props_1 = require("./validation/validate-default-props");
16
17
  const validate_dimensions_1 = require("./validation/validate-dimensions");
17
18
  const validate_duration_in_frames_1 = require("./validation/validate-duration-in-frames");
@@ -42,4 +43,5 @@ exports.NoReactInternals = {
42
43
  colorNames: interpolate_colors_1.colorNames,
43
44
  DATE_TOKEN: input_props_serialization_js_1.DATE_TOKEN,
44
45
  FILE_TOKEN: input_props_serialization_js_1.FILE_TOKEN,
46
+ validateCodec: validate_default_codec_1.validateCodec,
45
47
  };
@@ -22,7 +22,7 @@ const validateCalculated = ({ calculated, compositionId, compositionFps, composi
22
22
  component: `of the "<Composition />" component with the id "${compositionId}"`,
23
23
  });
24
24
  const defaultCodec = calculated === null || calculated === void 0 ? void 0 : calculated.defaultCodec;
25
- (0, validate_default_codec_js_1.validateDefaultCodec)(defaultCodec, calculateMetadataErrorLocation);
25
+ (0, validate_default_codec_js_1.validateCodec)(defaultCodec, calculateMetadataErrorLocation, 'defaultCodec');
26
26
  const defaultOutName = calculated === null || calculated === void 0 ? void 0 : calculated.defaultOutName;
27
27
  const defaultVideoImageFormat = calculated === null || calculated === void 0 ? void 0 : calculated.defaultVideoImageFormat;
28
28
  const defaultPixelFormat = calculated === null || calculated === void 0 ? void 0 : calculated.defaultPixelFormat;
@@ -1,2 +1,2 @@
1
1
  import type { CodecOrUndefined } from '../codec';
2
- export declare function validateDefaultCodec(defaultCodec: unknown, location: string): asserts defaultCodec is CodecOrUndefined;
2
+ export declare function validateCodec(defaultCodec: unknown, location: string, name: string): asserts defaultCodec is CodecOrUndefined;
@@ -1,15 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateDefaultCodec = validateDefaultCodec;
3
+ exports.validateCodec = validateCodec;
4
4
  const codec_1 = require("../codec");
5
- function validateDefaultCodec(defaultCodec, location) {
5
+ function validateCodec(defaultCodec, location, name) {
6
6
  if (typeof defaultCodec === 'undefined') {
7
7
  return;
8
8
  }
9
9
  if (typeof defaultCodec !== 'string') {
10
- throw new TypeError(`The "defaultCodec" prop ${location} must be a string, but you passed a value of type ${typeof defaultCodec}.`);
10
+ throw new TypeError(`The "${name}" prop ${location} must be a string, but you passed a value of type ${typeof defaultCodec}.`);
11
11
  }
12
12
  if (!codec_1.validCodecs.includes(defaultCodec)) {
13
- throw new Error(`The "defaultCodec" prop ${location} must be one of ${codec_1.validCodecs.join(', ')}, but you passed ${defaultCodec}.`);
13
+ throw new Error(`The "${name}" prop ${location} must be one of ${codec_1.validCodecs.join(', ')}, but you passed ${defaultCodec}.`);
14
14
  }
15
15
  }
@@ -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.327";
6
+ export declare const VERSION = "4.0.329";
@@ -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.327';
10
+ exports.VERSION = '4.0.329';
@@ -11,7 +11,7 @@ export declare const Video: React.ForwardRefExoticComponent<Omit<import("./props
11
11
  pauseWhenBuffering?: boolean;
12
12
  showInTimeline?: boolean;
13
13
  delayRenderTimeoutInMilliseconds?: number;
14
- loopVolumeCurveBehavior?: import("../audio/use-audio-frame.js").LoopVolumeCurveBehavior;
14
+ loopVolumeCurveBehavior?: import("../index.js").LoopVolumeCurveBehavior;
15
15
  delayRenderRetries?: number;
16
16
  onError?: (err: Error) => void;
17
17
  onAutoPlayError?: null | (() => void);
@@ -3,6 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getOffthreadVideoSource = void 0;
4
4
  const absolute_src_1 = require("../absolute-src");
5
5
  const getOffthreadVideoSource = ({ src, transparent, currentTime, toneMapped, }) => {
6
- return `http://localhost:${window.remotion_proxyPort}/proxy?src=${encodeURIComponent((0, absolute_src_1.getAbsoluteSrc)(src))}&time=${encodeURIComponent(currentTime)}&transparent=${String(transparent)}&toneMapped=${String(toneMapped)}`;
6
+ return `http://localhost:${window.remotion_proxyPort}/proxy?src=${encodeURIComponent((0, absolute_src_1.getAbsoluteSrc)(src))}&time=${encodeURIComponent(Math.max(0, currentTime))}&transparent=${String(transparent)}&toneMapped=${String(toneMapped)}`;
7
7
  };
8
8
  exports.getOffthreadVideoSource = getOffthreadVideoSource;
@@ -104,7 +104,7 @@ function truthy(value) {
104
104
  }
105
105
 
106
106
  // src/version.ts
107
- var VERSION = "4.0.327";
107
+ var VERSION = "4.0.329";
108
108
 
109
109
  // src/multiple-versions-warning.ts
110
110
  var checkMultipleRemotionVersions = () => {
@@ -547,15 +547,15 @@ var validCodecs = [
547
547
  ];
548
548
 
549
549
  // src/validation/validate-default-codec.ts
550
- function validateDefaultCodec(defaultCodec, location) {
550
+ function validateCodec(defaultCodec, location, name) {
551
551
  if (typeof defaultCodec === "undefined") {
552
552
  return;
553
553
  }
554
554
  if (typeof defaultCodec !== "string") {
555
- throw new TypeError(`The "defaultCodec" prop ${location} must be a string, but you passed a value of type ${typeof defaultCodec}.`);
555
+ throw new TypeError(`The "${name}" prop ${location} must be a string, but you passed a value of type ${typeof defaultCodec}.`);
556
556
  }
557
557
  if (!validCodecs.includes(defaultCodec)) {
558
- throw new Error(`The "defaultCodec" prop ${location} must be one of ${validCodecs.join(", ")}, but you passed ${defaultCodec}.`);
558
+ throw new Error(`The "${name}" prop ${location} must be one of ${validCodecs.join(", ")}, but you passed ${defaultCodec}.`);
559
559
  }
560
560
  }
561
561
 
@@ -640,7 +640,7 @@ var validateCalculated = ({
640
640
  component: `of the "<Composition />" component with the id "${compositionId}"`
641
641
  });
642
642
  const defaultCodec = calculated?.defaultCodec;
643
- validateDefaultCodec(defaultCodec, calculateMetadataErrorLocation);
643
+ validateCodec(defaultCodec, calculateMetadataErrorLocation, "defaultCodec");
644
644
  const defaultOutName = calculated?.defaultOutName;
645
645
  const defaultVideoImageFormat = calculated?.defaultVideoImageFormat;
646
646
  const defaultPixelFormat = calculated?.defaultPixelFormat;
@@ -5887,6 +5887,246 @@ var useCurrentScale = (options) => {
5887
5887
  });
5888
5888
  };
5889
5889
 
5890
+ // src/video/VideoForPreview.tsx
5891
+ import {
5892
+ forwardRef as forwardRef9,
5893
+ useContext as useContext28,
5894
+ useEffect as useEffect19,
5895
+ useImperativeHandle as useImperativeHandle9,
5896
+ useMemo as useMemo26,
5897
+ useRef as useRef16,
5898
+ useState as useState17
5899
+ } from "react";
5900
+
5901
+ // src/video/emit-video-frame.ts
5902
+ import { useEffect as useEffect18 } from "react";
5903
+ var useEmitVideoFrame = ({
5904
+ ref,
5905
+ onVideoFrame
5906
+ }) => {
5907
+ useEffect18(() => {
5908
+ const { current } = ref;
5909
+ if (!current) {
5910
+ return;
5911
+ }
5912
+ if (!onVideoFrame) {
5913
+ return;
5914
+ }
5915
+ let handle = 0;
5916
+ const callback = () => {
5917
+ if (!ref.current) {
5918
+ return;
5919
+ }
5920
+ onVideoFrame(ref.current);
5921
+ handle = ref.current.requestVideoFrameCallback(callback);
5922
+ };
5923
+ callback();
5924
+ return () => {
5925
+ current.cancelVideoFrameCallback(handle);
5926
+ };
5927
+ }, [onVideoFrame, ref]);
5928
+ };
5929
+
5930
+ // src/video/VideoForPreview.tsx
5931
+ import { jsx as jsx27 } from "react/jsx-runtime";
5932
+ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
5933
+ const context = useContext28(SharedAudioContext);
5934
+ if (!context) {
5935
+ throw new Error("SharedAudioContext not found");
5936
+ }
5937
+ const videoRef = useRef16(null);
5938
+ const sharedSource = useMemo26(() => {
5939
+ if (!context.audioContext) {
5940
+ return null;
5941
+ }
5942
+ return makeSharedElementSourceNode({
5943
+ audioContext: context.audioContext,
5944
+ ref: videoRef
5945
+ });
5946
+ }, [context.audioContext]);
5947
+ const {
5948
+ volume,
5949
+ muted,
5950
+ playbackRate,
5951
+ onlyWarnForMediaSeekingError,
5952
+ src,
5953
+ onDuration,
5954
+ acceptableTimeShift,
5955
+ acceptableTimeShiftInSeconds,
5956
+ toneFrequency,
5957
+ name,
5958
+ _remotionInternalNativeLoopPassed,
5959
+ _remotionInternalStack,
5960
+ style,
5961
+ pauseWhenBuffering,
5962
+ showInTimeline,
5963
+ loopVolumeCurveBehavior,
5964
+ onError,
5965
+ onAutoPlayError,
5966
+ onVideoFrame,
5967
+ crossOrigin,
5968
+ delayRenderRetries,
5969
+ delayRenderTimeoutInMilliseconds,
5970
+ allowAmplificationDuringRender,
5971
+ useWebAudioApi,
5972
+ ...nativeProps
5973
+ } = props2;
5974
+ const _propsValid = true;
5975
+ if (!_propsValid) {
5976
+ throw new Error("typecheck error");
5977
+ }
5978
+ const volumePropFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
5979
+ const { fps, durationInFrames } = useVideoConfig();
5980
+ const parentSequence = useContext28(SequenceContext);
5981
+ const { hidden } = useContext28(SequenceVisibilityToggleContext);
5982
+ const logLevel = useLogLevel();
5983
+ const mountTime = useMountTime();
5984
+ const [timelineId] = useState17(() => String(Math.random()));
5985
+ const isSequenceHidden = hidden[timelineId] ?? false;
5986
+ if (typeof acceptableTimeShift !== "undefined") {
5987
+ throw new Error("acceptableTimeShift has been removed. Use acceptableTimeShiftInSeconds instead.");
5988
+ }
5989
+ const [mediaVolume] = useMediaVolumeState();
5990
+ const [mediaMuted] = useMediaMutedState();
5991
+ const userPreferredVolume = evaluateVolume({
5992
+ frame: volumePropFrame,
5993
+ volume,
5994
+ mediaVolume
5995
+ });
5996
+ useMediaInTimeline({
5997
+ mediaRef: videoRef,
5998
+ volume,
5999
+ mediaVolume,
6000
+ mediaType: "video",
6001
+ src,
6002
+ playbackRate: props2.playbackRate ?? 1,
6003
+ displayName: name ?? null,
6004
+ id: timelineId,
6005
+ stack: _remotionInternalStack,
6006
+ showInTimeline,
6007
+ premountDisplay: null,
6008
+ onAutoPlayError: onAutoPlayError ?? null,
6009
+ isPremounting: Boolean(parentSequence?.premounting)
6010
+ });
6011
+ useMediaPlayback({
6012
+ mediaRef: videoRef,
6013
+ src,
6014
+ mediaType: "video",
6015
+ playbackRate: props2.playbackRate ?? 1,
6016
+ onlyWarnForMediaSeekingError,
6017
+ acceptableTimeshift: acceptableTimeShiftInSeconds ?? null,
6018
+ isPremounting: Boolean(parentSequence?.premounting),
6019
+ pauseWhenBuffering,
6020
+ onAutoPlayError: onAutoPlayError ?? null
6021
+ });
6022
+ useVolume({
6023
+ logLevel,
6024
+ mediaRef: videoRef,
6025
+ volume: userPreferredVolume,
6026
+ source: sharedSource,
6027
+ shouldUseWebAudioApi: useWebAudioApi ?? false
6028
+ });
6029
+ const actualFrom = parentSequence ? parentSequence.relativeFrom : 0;
6030
+ const duration = parentSequence ? Math.min(parentSequence.durationInFrames, durationInFrames) : durationInFrames;
6031
+ const preloadedSrc = usePreload(src);
6032
+ const actualSrc = useAppendVideoFragment({
6033
+ actualSrc: preloadedSrc,
6034
+ actualFrom,
6035
+ duration,
6036
+ fps
6037
+ });
6038
+ useImperativeHandle9(ref, () => {
6039
+ return videoRef.current;
6040
+ }, []);
6041
+ useState17(() => playbackLogging({
6042
+ logLevel,
6043
+ message: `Mounting video with source = ${actualSrc}, v=${VERSION}, user agent=${typeof navigator === "undefined" ? "server" : navigator.userAgent}`,
6044
+ tag: "video",
6045
+ mountTime
6046
+ }));
6047
+ useEffect19(() => {
6048
+ const { current } = videoRef;
6049
+ if (!current) {
6050
+ return;
6051
+ }
6052
+ const errorHandler = () => {
6053
+ if (current.error) {
6054
+ console.error("Error occurred in video", current?.error);
6055
+ if (onError) {
6056
+ const err = new Error(`Code ${current.error.code}: ${current.error.message}`);
6057
+ onError(err);
6058
+ return;
6059
+ }
6060
+ 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.`);
6061
+ } else {
6062
+ if (onError) {
6063
+ const err = new Error(`The browser threw an error while playing the video ${src}`);
6064
+ onError(err);
6065
+ return;
6066
+ }
6067
+ throw new Error("The browser threw an error while playing the video");
6068
+ }
6069
+ };
6070
+ current.addEventListener("error", errorHandler, { once: true });
6071
+ return () => {
6072
+ current.removeEventListener("error", errorHandler);
6073
+ };
6074
+ }, [onError, src]);
6075
+ const currentOnDurationCallback = useRef16(onDuration);
6076
+ currentOnDurationCallback.current = onDuration;
6077
+ useEmitVideoFrame({ ref: videoRef, onVideoFrame });
6078
+ useEffect19(() => {
6079
+ const { current } = videoRef;
6080
+ if (!current) {
6081
+ return;
6082
+ }
6083
+ if (current.duration) {
6084
+ currentOnDurationCallback.current?.(src, current.duration);
6085
+ return;
6086
+ }
6087
+ const onLoadedMetadata = () => {
6088
+ currentOnDurationCallback.current?.(src, current.duration);
6089
+ };
6090
+ current.addEventListener("loadedmetadata", onLoadedMetadata);
6091
+ return () => {
6092
+ current.removeEventListener("loadedmetadata", onLoadedMetadata);
6093
+ };
6094
+ }, [src]);
6095
+ useEffect19(() => {
6096
+ const { current } = videoRef;
6097
+ if (!current) {
6098
+ return;
6099
+ }
6100
+ if (isIosSafari()) {
6101
+ current.preload = "metadata";
6102
+ } else {
6103
+ current.preload = "auto";
6104
+ }
6105
+ }, []);
6106
+ const actualStyle = useMemo26(() => {
6107
+ return {
6108
+ ...style,
6109
+ opacity: isSequenceHidden ? 0 : style?.opacity ?? 1
6110
+ };
6111
+ }, [isSequenceHidden, style]);
6112
+ const crossOriginValue = getCrossOriginValue({
6113
+ crossOrigin,
6114
+ requestsVideoFrame: Boolean(onVideoFrame)
6115
+ });
6116
+ return /* @__PURE__ */ jsx27("video", {
6117
+ ref: videoRef,
6118
+ muted: muted || mediaMuted || isSequenceHidden || userPreferredVolume <= 0,
6119
+ playsInline: true,
6120
+ src: actualSrc,
6121
+ loop: _remotionInternalNativeLoopPassed,
6122
+ style: actualStyle,
6123
+ disableRemotePlayback: true,
6124
+ crossOrigin: crossOriginValue,
6125
+ ...nativeProps
6126
+ });
6127
+ };
6128
+ var VideoForPreview = forwardRef9(VideoForDevelopmentRefForwardingFunction);
6129
+
5890
6130
  // src/watch-static-file.ts
5891
6131
  var WATCH_REMOTION_STATIC_FILES = "remotion_staticFilesChanged";
5892
6132
  var watchStaticFile = (fileName, callback) => {
@@ -5925,22 +6165,22 @@ var watchStaticFile = (fileName, callback) => {
5925
6165
  };
5926
6166
 
5927
6167
  // src/wrap-remotion-context.tsx
5928
- import React26, { useMemo as useMemo26 } from "react";
5929
- import { jsx as jsx27 } from "react/jsx-runtime";
6168
+ import React27, { useMemo as useMemo27 } from "react";
6169
+ import { jsx as jsx28 } from "react/jsx-runtime";
5930
6170
  function useRemotionContexts() {
5931
- const compositionManagerCtx = React26.useContext(CompositionManager);
5932
- const timelineContext = React26.useContext(TimelineContext);
5933
- const setTimelineContext = React26.useContext(SetTimelineContext);
5934
- const sequenceContext = React26.useContext(SequenceContext);
5935
- const nonceContext = React26.useContext(NonceContext);
5936
- const canUseRemotionHooksContext = React26.useContext(CanUseRemotionHooks);
5937
- const preloadContext = React26.useContext(PreloadContext);
5938
- const resolveCompositionContext = React26.useContext(ResolveCompositionContext);
5939
- const renderAssetManagerContext = React26.useContext(RenderAssetManager);
5940
- const sequenceManagerContext = React26.useContext(SequenceManager);
5941
- const bufferManagerContext = React26.useContext(BufferingContextReact);
5942
- const logLevelContext = React26.useContext(LogLevelContext);
5943
- return useMemo26(() => ({
6171
+ const compositionManagerCtx = React27.useContext(CompositionManager);
6172
+ const timelineContext = React27.useContext(TimelineContext);
6173
+ const setTimelineContext = React27.useContext(SetTimelineContext);
6174
+ const sequenceContext = React27.useContext(SequenceContext);
6175
+ const nonceContext = React27.useContext(NonceContext);
6176
+ const canUseRemotionHooksContext = React27.useContext(CanUseRemotionHooks);
6177
+ const preloadContext = React27.useContext(PreloadContext);
6178
+ const resolveCompositionContext = React27.useContext(ResolveCompositionContext);
6179
+ const renderAssetManagerContext = React27.useContext(RenderAssetManager);
6180
+ const sequenceManagerContext = React27.useContext(SequenceManager);
6181
+ const bufferManagerContext = React27.useContext(BufferingContextReact);
6182
+ const logLevelContext = React27.useContext(LogLevelContext);
6183
+ return useMemo27(() => ({
5944
6184
  compositionManagerCtx,
5945
6185
  timelineContext,
5946
6186
  setTimelineContext,
@@ -5970,29 +6210,29 @@ function useRemotionContexts() {
5970
6210
  }
5971
6211
  var RemotionContextProvider = (props2) => {
5972
6212
  const { children, contexts } = props2;
5973
- return /* @__PURE__ */ jsx27(LogLevelContext.Provider, {
6213
+ return /* @__PURE__ */ jsx28(LogLevelContext.Provider, {
5974
6214
  value: contexts.logLevelContext,
5975
- children: /* @__PURE__ */ jsx27(CanUseRemotionHooks.Provider, {
6215
+ children: /* @__PURE__ */ jsx28(CanUseRemotionHooks.Provider, {
5976
6216
  value: contexts.canUseRemotionHooksContext,
5977
- children: /* @__PURE__ */ jsx27(NonceContext.Provider, {
6217
+ children: /* @__PURE__ */ jsx28(NonceContext.Provider, {
5978
6218
  value: contexts.nonceContext,
5979
- children: /* @__PURE__ */ jsx27(PreloadContext.Provider, {
6219
+ children: /* @__PURE__ */ jsx28(PreloadContext.Provider, {
5980
6220
  value: contexts.preloadContext,
5981
- children: /* @__PURE__ */ jsx27(CompositionManager.Provider, {
6221
+ children: /* @__PURE__ */ jsx28(CompositionManager.Provider, {
5982
6222
  value: contexts.compositionManagerCtx,
5983
- children: /* @__PURE__ */ jsx27(SequenceManager.Provider, {
6223
+ children: /* @__PURE__ */ jsx28(SequenceManager.Provider, {
5984
6224
  value: contexts.sequenceManagerContext,
5985
- children: /* @__PURE__ */ jsx27(RenderAssetManager.Provider, {
6225
+ children: /* @__PURE__ */ jsx28(RenderAssetManager.Provider, {
5986
6226
  value: contexts.renderAssetManagerContext,
5987
- children: /* @__PURE__ */ jsx27(ResolveCompositionContext.Provider, {
6227
+ children: /* @__PURE__ */ jsx28(ResolveCompositionContext.Provider, {
5988
6228
  value: contexts.resolveCompositionContext,
5989
- children: /* @__PURE__ */ jsx27(TimelineContext.Provider, {
6229
+ children: /* @__PURE__ */ jsx28(TimelineContext.Provider, {
5990
6230
  value: contexts.timelineContext,
5991
- children: /* @__PURE__ */ jsx27(SetTimelineContext.Provider, {
6231
+ children: /* @__PURE__ */ jsx28(SetTimelineContext.Provider, {
5992
6232
  value: contexts.setTimelineContext,
5993
- children: /* @__PURE__ */ jsx27(SequenceContext.Provider, {
6233
+ children: /* @__PURE__ */ jsx28(SequenceContext.Provider, {
5994
6234
  value: contexts.sequenceContext,
5995
- children: /* @__PURE__ */ jsx27(BufferingContextReact.Provider, {
6235
+ children: /* @__PURE__ */ jsx28(BufferingContextReact.Provider, {
5996
6236
  value: contexts.bufferManagerContext,
5997
6237
  children
5998
6238
  })
@@ -6013,7 +6253,15 @@ var RemotionContextProvider = (props2) => {
6013
6253
  var compositionSelectorRef = createRef3();
6014
6254
  var Internals = {
6015
6255
  useUnsafeVideoConfig,
6256
+ useFrameForVolumeProp,
6257
+ useTimelinePosition,
6258
+ evaluateVolume,
6259
+ getAbsoluteSrc,
6016
6260
  Timeline: exports_timeline_position_state,
6261
+ validateMediaTrimProps,
6262
+ validateMediaProps,
6263
+ resolveTrimProps,
6264
+ VideoForPreview,
6017
6265
  CompositionManager,
6018
6266
  CompositionSetters,
6019
6267
  SequenceManager,
@@ -6451,17 +6699,17 @@ var getOffthreadVideoSource = ({
6451
6699
  currentTime,
6452
6700
  toneMapped
6453
6701
  }) => {
6454
- return `http://localhost:${window.remotion_proxyPort}/proxy?src=${encodeURIComponent(getAbsoluteSrc(src))}&time=${encodeURIComponent(currentTime)}&transparent=${String(transparent)}&toneMapped=${String(toneMapped)}`;
6702
+ return `http://localhost:${window.remotion_proxyPort}/proxy?src=${encodeURIComponent(getAbsoluteSrc(src))}&time=${encodeURIComponent(Math.max(0, currentTime))}&transparent=${String(transparent)}&toneMapped=${String(toneMapped)}`;
6455
6703
  };
6456
6704
  // src/series/index.tsx
6457
- import { Children, forwardRef as forwardRef9, useMemo as useMemo27 } from "react";
6705
+ import { Children, forwardRef as forwardRef10, useMemo as useMemo28 } from "react";
6458
6706
 
6459
6707
  // src/series/flatten-children.tsx
6460
- import React27 from "react";
6708
+ import React28 from "react";
6461
6709
  var flattenChildren = (children) => {
6462
- const childrenArray = React27.Children.toArray(children);
6710
+ const childrenArray = React28.Children.toArray(children);
6463
6711
  return childrenArray.reduce((flatChildren, child) => {
6464
- if (child.type === React27.Fragment) {
6712
+ if (child.type === React28.Fragment) {
6465
6713
  return flatChildren.concat(flattenChildren(child.props.children));
6466
6714
  }
6467
6715
  flatChildren.push(child);
@@ -6470,39 +6718,39 @@ var flattenChildren = (children) => {
6470
6718
  };
6471
6719
 
6472
6720
  // src/series/is-inside-series.tsx
6473
- import React28, { createContext as createContext19 } from "react";
6474
- import { jsx as jsx28 } from "react/jsx-runtime";
6721
+ import React29, { createContext as createContext19 } from "react";
6722
+ import { jsx as jsx29 } from "react/jsx-runtime";
6475
6723
  var IsInsideSeriesContext = createContext19(false);
6476
6724
  var IsInsideSeriesContainer = ({ children }) => {
6477
- return /* @__PURE__ */ jsx28(IsInsideSeriesContext.Provider, {
6725
+ return /* @__PURE__ */ jsx29(IsInsideSeriesContext.Provider, {
6478
6726
  value: true,
6479
6727
  children
6480
6728
  });
6481
6729
  };
6482
6730
  var IsNotInsideSeriesProvider = ({ children }) => {
6483
- return /* @__PURE__ */ jsx28(IsInsideSeriesContext.Provider, {
6731
+ return /* @__PURE__ */ jsx29(IsInsideSeriesContext.Provider, {
6484
6732
  value: false,
6485
6733
  children
6486
6734
  });
6487
6735
  };
6488
6736
  var useRequireToBeInsideSeries = () => {
6489
- const isInsideSeries = React28.useContext(IsInsideSeriesContext);
6737
+ const isInsideSeries = React29.useContext(IsInsideSeriesContext);
6490
6738
  if (!isInsideSeries) {
6491
6739
  throw new Error("This component must be inside a <Series /> component.");
6492
6740
  }
6493
6741
  };
6494
6742
 
6495
6743
  // src/series/index.tsx
6496
- import { jsx as jsx29 } from "react/jsx-runtime";
6744
+ import { jsx as jsx30 } from "react/jsx-runtime";
6497
6745
  var SeriesSequenceRefForwardingFunction = ({ children }, _ref) => {
6498
6746
  useRequireToBeInsideSeries();
6499
- return /* @__PURE__ */ jsx29(IsNotInsideSeriesProvider, {
6747
+ return /* @__PURE__ */ jsx30(IsNotInsideSeriesProvider, {
6500
6748
  children
6501
6749
  });
6502
6750
  };
6503
- var SeriesSequence = forwardRef9(SeriesSequenceRefForwardingFunction);
6751
+ var SeriesSequence = forwardRef10(SeriesSequenceRefForwardingFunction);
6504
6752
  var Series = (props2) => {
6505
- const childrenValue = useMemo27(() => {
6753
+ const childrenValue = useMemo28(() => {
6506
6754
  let startFrame = 0;
6507
6755
  const flattenedChildren = flattenChildren(props2.children);
6508
6756
  return Children.map(flattenedChildren, (child, i) => {
@@ -6546,7 +6794,7 @@ var Series = (props2) => {
6546
6794
  }
6547
6795
  const currentStartFrame = startFrame + offset;
6548
6796
  startFrame += durationInFramesProp + offset;
6549
- return /* @__PURE__ */ jsx29(Sequence, {
6797
+ return /* @__PURE__ */ jsx30(Sequence, {
6550
6798
  name: name || "<Series.Sequence>",
6551
6799
  from: currentStartFrame,
6552
6800
  durationInFrames: durationInFramesProp,
@@ -6557,14 +6805,14 @@ var Series = (props2) => {
6557
6805
  });
6558
6806
  }, [props2.children]);
6559
6807
  if (ENABLE_V5_BREAKING_CHANGES) {
6560
- return /* @__PURE__ */ jsx29(IsInsideSeriesContainer, {
6561
- children: /* @__PURE__ */ jsx29(Sequence, {
6808
+ return /* @__PURE__ */ jsx30(IsInsideSeriesContainer, {
6809
+ children: /* @__PURE__ */ jsx30(Sequence, {
6562
6810
  ...props2,
6563
6811
  children: childrenValue
6564
6812
  })
6565
6813
  });
6566
6814
  }
6567
- return /* @__PURE__ */ jsx29(IsInsideSeriesContainer, {
6815
+ return /* @__PURE__ */ jsx30(IsInsideSeriesContainer, {
6568
6816
  children: childrenValue
6569
6817
  });
6570
6818
  };
@@ -6901,14 +7149,14 @@ var staticFile = (path) => {
6901
7149
  return preparsed;
6902
7150
  };
6903
7151
  // src/Still.tsx
6904
- import React30 from "react";
7152
+ import React31 from "react";
6905
7153
  var Still = (props2) => {
6906
7154
  const newProps = {
6907
7155
  ...props2,
6908
7156
  durationInFrames: 1,
6909
7157
  fps: 1
6910
7158
  };
6911
- return React30.createElement(Composition, newProps);
7159
+ return React31.createElement(Composition, newProps);
6912
7160
  };
6913
7161
  // src/video/OffthreadVideo.tsx
6914
7162
  import { useCallback as useCallback15 } from "react";
@@ -6916,13 +7164,13 @@ import { useCallback as useCallback15 } from "react";
6916
7164
  // src/video/OffthreadVideoForRendering.tsx
6917
7165
  import {
6918
7166
  useCallback as useCallback14,
6919
- useContext as useContext28,
6920
- useEffect as useEffect18,
7167
+ useContext as useContext29,
7168
+ useEffect as useEffect20,
6921
7169
  useLayoutEffect as useLayoutEffect9,
6922
- useMemo as useMemo28,
6923
- useState as useState17
7170
+ useMemo as useMemo29,
7171
+ useState as useState18
6924
7172
  } from "react";
6925
- import { jsx as jsx30 } from "react/jsx-runtime";
7173
+ import { jsx as jsx31 } from "react/jsx-runtime";
6926
7174
  var OffthreadVideoForRendering = ({
6927
7175
  onError,
6928
7176
  volume: volumeProp,
@@ -6945,13 +7193,13 @@ var OffthreadVideoForRendering = ({
6945
7193
  const frame = useCurrentFrame();
6946
7194
  const volumePropsFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
6947
7195
  const videoConfig = useUnsafeVideoConfig();
6948
- const sequenceContext = useContext28(SequenceContext);
7196
+ const sequenceContext = useContext29(SequenceContext);
6949
7197
  const mediaStartsAt = useMediaStartsAt();
6950
- const { registerRenderAsset, unregisterRenderAsset } = useContext28(RenderAssetManager);
7198
+ const { registerRenderAsset, unregisterRenderAsset } = useContext29(RenderAssetManager);
6951
7199
  if (!src) {
6952
7200
  throw new TypeError("No `src` was passed to <OffthreadVideo>.");
6953
7201
  }
6954
- const id = useMemo28(() => `offthreadvideo-${random(src ?? "")}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
7202
+ const id = useMemo29(() => `offthreadvideo-${random(src ?? "")}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
6955
7203
  src,
6956
7204
  sequenceContext?.cumulatedFrom,
6957
7205
  sequenceContext?.relativeFrom,
@@ -6965,7 +7213,7 @@ var OffthreadVideoForRendering = ({
6965
7213
  frame: volumePropsFrame,
6966
7214
  mediaVolume: 1
6967
7215
  });
6968
- useEffect18(() => {
7216
+ useEffect20(() => {
6969
7217
  if (!src) {
6970
7218
  throw new Error("No src passed");
6971
7219
  }
@@ -7003,14 +7251,14 @@ var OffthreadVideoForRendering = ({
7003
7251
  toneFrequency,
7004
7252
  sequenceContext?.relativeFrom
7005
7253
  ]);
7006
- const currentTime = useMemo28(() => {
7254
+ const currentTime = useMemo29(() => {
7007
7255
  return getExpectedMediaFrameUncorrected({
7008
7256
  frame,
7009
7257
  playbackRate: playbackRate || 1,
7010
7258
  startFrom: -mediaStartsAt
7011
7259
  }) / videoConfig.fps;
7012
7260
  }, [frame, mediaStartsAt, playbackRate, videoConfig.fps]);
7013
- const actualSrc = useMemo28(() => {
7261
+ const actualSrc = useMemo29(() => {
7014
7262
  return getOffthreadVideoSource({
7015
7263
  src,
7016
7264
  currentTime,
@@ -7018,7 +7266,7 @@ var OffthreadVideoForRendering = ({
7018
7266
  toneMapped
7019
7267
  });
7020
7268
  }, [toneMapped, currentTime, src, transparent]);
7021
- const [imageSrc, setImageSrc] = useState17(null);
7269
+ const [imageSrc, setImageSrc] = useState18(null);
7022
7270
  useLayoutEffect9(() => {
7023
7271
  if (!window.remotion_videoEnabled) {
7024
7272
  return;
@@ -7095,7 +7343,7 @@ var OffthreadVideoForRendering = ({
7095
7343
  cancelRender("Failed to load image with src " + imageSrc);
7096
7344
  }
7097
7345
  }, [imageSrc, onError]);
7098
- const className = useMemo28(() => {
7346
+ const className = useMemo29(() => {
7099
7347
  return [OFFTHREAD_VIDEO_CLASS_NAME, props2.className].filter(truthy).join(" ");
7100
7348
  }, [props2.className]);
7101
7349
  const onImageFrame = useCallback14((img) => {
@@ -7107,7 +7355,7 @@ var OffthreadVideoForRendering = ({
7107
7355
  return null;
7108
7356
  }
7109
7357
  continueRender(imageSrc.handle);
7110
- return /* @__PURE__ */ jsx30(Img, {
7358
+ return /* @__PURE__ */ jsx31(Img, {
7111
7359
  src: imageSrc.src,
7112
7360
  className,
7113
7361
  delayRenderRetries,
@@ -7118,246 +7366,6 @@ var OffthreadVideoForRendering = ({
7118
7366
  });
7119
7367
  };
7120
7368
 
7121
- // src/video/VideoForPreview.tsx
7122
- import {
7123
- forwardRef as forwardRef10,
7124
- useContext as useContext29,
7125
- useEffect as useEffect20,
7126
- useImperativeHandle as useImperativeHandle9,
7127
- useMemo as useMemo29,
7128
- useRef as useRef16,
7129
- useState as useState18
7130
- } from "react";
7131
-
7132
- // src/video/emit-video-frame.ts
7133
- import { useEffect as useEffect19 } from "react";
7134
- var useEmitVideoFrame = ({
7135
- ref,
7136
- onVideoFrame
7137
- }) => {
7138
- useEffect19(() => {
7139
- const { current } = ref;
7140
- if (!current) {
7141
- return;
7142
- }
7143
- if (!onVideoFrame) {
7144
- return;
7145
- }
7146
- let handle = 0;
7147
- const callback = () => {
7148
- if (!ref.current) {
7149
- return;
7150
- }
7151
- onVideoFrame(ref.current);
7152
- handle = ref.current.requestVideoFrameCallback(callback);
7153
- };
7154
- callback();
7155
- return () => {
7156
- current.cancelVideoFrameCallback(handle);
7157
- };
7158
- }, [onVideoFrame, ref]);
7159
- };
7160
-
7161
- // src/video/VideoForPreview.tsx
7162
- import { jsx as jsx31 } from "react/jsx-runtime";
7163
- var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
7164
- const context = useContext29(SharedAudioContext);
7165
- if (!context) {
7166
- throw new Error("SharedAudioContext not found");
7167
- }
7168
- const videoRef = useRef16(null);
7169
- const sharedSource = useMemo29(() => {
7170
- if (!context.audioContext) {
7171
- return null;
7172
- }
7173
- return makeSharedElementSourceNode({
7174
- audioContext: context.audioContext,
7175
- ref: videoRef
7176
- });
7177
- }, [context.audioContext]);
7178
- const {
7179
- volume,
7180
- muted,
7181
- playbackRate,
7182
- onlyWarnForMediaSeekingError,
7183
- src,
7184
- onDuration,
7185
- acceptableTimeShift,
7186
- acceptableTimeShiftInSeconds,
7187
- toneFrequency,
7188
- name,
7189
- _remotionInternalNativeLoopPassed,
7190
- _remotionInternalStack,
7191
- style,
7192
- pauseWhenBuffering,
7193
- showInTimeline,
7194
- loopVolumeCurveBehavior,
7195
- onError,
7196
- onAutoPlayError,
7197
- onVideoFrame,
7198
- crossOrigin,
7199
- delayRenderRetries,
7200
- delayRenderTimeoutInMilliseconds,
7201
- allowAmplificationDuringRender,
7202
- useWebAudioApi,
7203
- ...nativeProps
7204
- } = props2;
7205
- const _propsValid = true;
7206
- if (!_propsValid) {
7207
- throw new Error("typecheck error");
7208
- }
7209
- const volumePropFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
7210
- const { fps, durationInFrames } = useVideoConfig();
7211
- const parentSequence = useContext29(SequenceContext);
7212
- const { hidden } = useContext29(SequenceVisibilityToggleContext);
7213
- const logLevel = useLogLevel();
7214
- const mountTime = useMountTime();
7215
- const [timelineId] = useState18(() => String(Math.random()));
7216
- const isSequenceHidden = hidden[timelineId] ?? false;
7217
- if (typeof acceptableTimeShift !== "undefined") {
7218
- throw new Error("acceptableTimeShift has been removed. Use acceptableTimeShiftInSeconds instead.");
7219
- }
7220
- const [mediaVolume] = useMediaVolumeState();
7221
- const [mediaMuted] = useMediaMutedState();
7222
- const userPreferredVolume = evaluateVolume({
7223
- frame: volumePropFrame,
7224
- volume,
7225
- mediaVolume
7226
- });
7227
- useMediaInTimeline({
7228
- mediaRef: videoRef,
7229
- volume,
7230
- mediaVolume,
7231
- mediaType: "video",
7232
- src,
7233
- playbackRate: props2.playbackRate ?? 1,
7234
- displayName: name ?? null,
7235
- id: timelineId,
7236
- stack: _remotionInternalStack,
7237
- showInTimeline,
7238
- premountDisplay: null,
7239
- onAutoPlayError: onAutoPlayError ?? null,
7240
- isPremounting: Boolean(parentSequence?.premounting)
7241
- });
7242
- useMediaPlayback({
7243
- mediaRef: videoRef,
7244
- src,
7245
- mediaType: "video",
7246
- playbackRate: props2.playbackRate ?? 1,
7247
- onlyWarnForMediaSeekingError,
7248
- acceptableTimeshift: acceptableTimeShiftInSeconds ?? null,
7249
- isPremounting: Boolean(parentSequence?.premounting),
7250
- pauseWhenBuffering,
7251
- onAutoPlayError: onAutoPlayError ?? null
7252
- });
7253
- useVolume({
7254
- logLevel,
7255
- mediaRef: videoRef,
7256
- volume: userPreferredVolume,
7257
- source: sharedSource,
7258
- shouldUseWebAudioApi: useWebAudioApi ?? false
7259
- });
7260
- const actualFrom = parentSequence ? parentSequence.relativeFrom : 0;
7261
- const duration = parentSequence ? Math.min(parentSequence.durationInFrames, durationInFrames) : durationInFrames;
7262
- const preloadedSrc = usePreload(src);
7263
- const actualSrc = useAppendVideoFragment({
7264
- actualSrc: preloadedSrc,
7265
- actualFrom,
7266
- duration,
7267
- fps
7268
- });
7269
- useImperativeHandle9(ref, () => {
7270
- return videoRef.current;
7271
- }, []);
7272
- useState18(() => playbackLogging({
7273
- logLevel,
7274
- message: `Mounting video with source = ${actualSrc}, v=${VERSION}, user agent=${typeof navigator === "undefined" ? "server" : navigator.userAgent}`,
7275
- tag: "video",
7276
- mountTime
7277
- }));
7278
- useEffect20(() => {
7279
- const { current } = videoRef;
7280
- if (!current) {
7281
- return;
7282
- }
7283
- const errorHandler = () => {
7284
- if (current.error) {
7285
- console.error("Error occurred in video", current?.error);
7286
- if (onError) {
7287
- const err = new Error(`Code ${current.error.code}: ${current.error.message}`);
7288
- onError(err);
7289
- return;
7290
- }
7291
- 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.`);
7292
- } else {
7293
- if (onError) {
7294
- const err = new Error(`The browser threw an error while playing the video ${src}`);
7295
- onError(err);
7296
- return;
7297
- }
7298
- throw new Error("The browser threw an error while playing the video");
7299
- }
7300
- };
7301
- current.addEventListener("error", errorHandler, { once: true });
7302
- return () => {
7303
- current.removeEventListener("error", errorHandler);
7304
- };
7305
- }, [onError, src]);
7306
- const currentOnDurationCallback = useRef16(onDuration);
7307
- currentOnDurationCallback.current = onDuration;
7308
- useEmitVideoFrame({ ref: videoRef, onVideoFrame });
7309
- useEffect20(() => {
7310
- const { current } = videoRef;
7311
- if (!current) {
7312
- return;
7313
- }
7314
- if (current.duration) {
7315
- currentOnDurationCallback.current?.(src, current.duration);
7316
- return;
7317
- }
7318
- const onLoadedMetadata = () => {
7319
- currentOnDurationCallback.current?.(src, current.duration);
7320
- };
7321
- current.addEventListener("loadedmetadata", onLoadedMetadata);
7322
- return () => {
7323
- current.removeEventListener("loadedmetadata", onLoadedMetadata);
7324
- };
7325
- }, [src]);
7326
- useEffect20(() => {
7327
- const { current } = videoRef;
7328
- if (!current) {
7329
- return;
7330
- }
7331
- if (isIosSafari()) {
7332
- current.preload = "metadata";
7333
- } else {
7334
- current.preload = "auto";
7335
- }
7336
- }, []);
7337
- const actualStyle = useMemo29(() => {
7338
- return {
7339
- ...style,
7340
- opacity: isSequenceHidden ? 0 : style?.opacity ?? 1
7341
- };
7342
- }, [isSequenceHidden, style]);
7343
- const crossOriginValue = getCrossOriginValue({
7344
- crossOrigin,
7345
- requestsVideoFrame: Boolean(onVideoFrame)
7346
- });
7347
- return /* @__PURE__ */ jsx31("video", {
7348
- ref: videoRef,
7349
- muted: muted || mediaMuted || isSequenceHidden || userPreferredVolume <= 0,
7350
- playsInline: true,
7351
- src: actualSrc,
7352
- loop: _remotionInternalNativeLoopPassed,
7353
- style: actualStyle,
7354
- disableRemotePlayback: true,
7355
- crossOrigin: crossOriginValue,
7356
- ...nativeProps
7357
- });
7358
- };
7359
- var VideoForPreview = forwardRef10(VideoForDevelopmentRefForwardingFunction);
7360
-
7361
7369
  // src/video/OffthreadVideo.tsx
7362
7370
  import { jsx as jsx32 } from "react/jsx-runtime";
7363
7371
  var OffthreadVideo = (props2) => {
@@ -522,6 +522,34 @@ var validateFrame = ({
522
522
  }
523
523
  };
524
524
 
525
+ // src/codec.ts
526
+ var validCodecs = [
527
+ "h264",
528
+ "h265",
529
+ "vp8",
530
+ "vp9",
531
+ "mp3",
532
+ "aac",
533
+ "wav",
534
+ "prores",
535
+ "h264-mkv",
536
+ "h264-ts",
537
+ "gif"
538
+ ];
539
+
540
+ // src/validation/validate-default-codec.ts
541
+ function validateCodec(defaultCodec, location, name) {
542
+ if (typeof defaultCodec === "undefined") {
543
+ return;
544
+ }
545
+ if (typeof defaultCodec !== "string") {
546
+ throw new TypeError(`The "${name}" prop ${location} must be a string, but you passed a value of type ${typeof defaultCodec}.`);
547
+ }
548
+ if (!validCodecs.includes(defaultCodec)) {
549
+ throw new Error(`The "${name}" prop ${location} must be one of ${validCodecs.join(", ")}, but you passed ${defaultCodec}.`);
550
+ }
551
+ }
552
+
525
553
  // src/validation/validate-default-props.ts
526
554
  var validateDefaultAndInputProps = (defaultProps, name, compositionId) => {
527
555
  if (!defaultProps) {
@@ -620,7 +648,7 @@ var getOffthreadVideoSource = ({
620
648
  currentTime,
621
649
  toneMapped
622
650
  }) => {
623
- return `http://localhost:${window.remotion_proxyPort}/proxy?src=${encodeURIComponent(getAbsoluteSrc(src))}&time=${encodeURIComponent(currentTime)}&transparent=${String(transparent)}&toneMapped=${String(toneMapped)}`;
651
+ return `http://localhost:${window.remotion_proxyPort}/proxy?src=${encodeURIComponent(getAbsoluteSrc(src))}&time=${encodeURIComponent(Math.max(0, currentTime))}&transparent=${String(transparent)}&toneMapped=${String(toneMapped)}`;
624
652
  };
625
653
 
626
654
  // src/no-react.ts
@@ -647,7 +675,8 @@ var NoReactInternals = {
647
675
  MIN_BUN_VERSION: ENABLE_V5_BREAKING_CHANGES ? "1.1.3" : "1.0.3",
648
676
  colorNames,
649
677
  DATE_TOKEN,
650
- FILE_TOKEN
678
+ FILE_TOKEN,
679
+ validateCodec
651
680
  };
652
681
  export {
653
682
  random,
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "4.0.327";
2
+ var VERSION = "4.0.329";
3
3
  export {
4
4
  VERSION
5
5
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/core"
4
4
  },
5
5
  "name": "remotion",
6
- "version": "4.0.327",
6
+ "version": "4.0.329",
7
7
  "description": "Make videos programmatically",
8
8
  "main": "dist/cjs/index.js",
9
9
  "types": "dist/cjs/index.d.ts",
@@ -28,7 +28,7 @@
28
28
  "webpack": "5.96.1",
29
29
  "zod": "3.22.3",
30
30
  "eslint": "9.19.0",
31
- "@remotion/eslint-config-internal": "4.0.327"
31
+ "@remotion/eslint-config-internal": "4.0.329"
32
32
  },
33
33
  "keywords": [
34
34
  "remotion",