@remotion/player 4.0.508 → 4.0.510

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.
@@ -63,6 +63,7 @@ export type PlayerProps<Schema extends AnyZodObject, Props extends Record<string
63
63
  readonly sampleRate?: number;
64
64
  readonly volumePersistenceKey?: string;
65
65
  readonly initialVolume?: number;
66
+ readonly _experimentalKeepAudioContextAlive?: boolean;
66
67
  } & CompProps<Props> & PropsIfHasProps<Schema, Props>;
67
68
  export type PlayerPropsWithoutZod<Props extends Record<string, unknown>> = PlayerProps<AnyZodObject, Props>;
68
69
  export declare const componentOrNullIfLazy: <Props>(props: CompProps<Props>) => ComponentType<Props> | null;
@@ -23,7 +23,7 @@ const componentOrNullIfLazy = (props) => {
23
23
  return null;
24
24
  };
25
25
  exports.componentOrNullIfLazy = componentOrNullIfLazy;
26
- const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps, inputProps, style, controls = false, loop = false, autoPlay = false, showVolumeControls = true, allowFullscreen = true, clickToPlay, doubleClickToFullscreen = false, spaceKeyToPlayOrPause = true, moveToBeginningWhenEnded = true, numberOfSharedAudioTags = 5, errorFallback = () => '⚠️', playbackRate = 1, renderLoading, className, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, showPosterWhenBuffering, showPosterWhenBufferingAndPaused, initialFrame, renderPoster, inFrame, outFrame, initiallyShowControls, renderFullscreenButton, renderPlayPauseButton, renderVolumeSlider, renderCustomControls, alwaysShowControls = false, initiallyMuted = false, showPlaybackRateControl = false, posterFillMode = 'player-size', bufferStateDelayInMilliseconds, hideControlsWhenPointerDoesntMove = true, overflowVisible = false, renderMuteButton, browserMediaControlsBehavior: passedBrowserMediaControlsBehavior, overrideInternalClassName, logLevel = 'info', noSuspense, acknowledgeRemotionLicense, audioLatencyHint = 'playback', sampleRate = 48000, volumePersistenceKey, initialVolume, ...componentProps }, ref) => {
26
+ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps, inputProps, style, controls = false, loop = false, autoPlay = false, showVolumeControls = true, allowFullscreen = true, clickToPlay, doubleClickToFullscreen = false, spaceKeyToPlayOrPause = true, moveToBeginningWhenEnded = true, numberOfSharedAudioTags = 5, errorFallback = () => '⚠️', playbackRate = 1, renderLoading, className, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, showPosterWhenBuffering, showPosterWhenBufferingAndPaused, initialFrame, renderPoster, inFrame, outFrame, initiallyShowControls, renderFullscreenButton, renderPlayPauseButton, renderVolumeSlider, renderCustomControls, alwaysShowControls = false, initiallyMuted = false, showPlaybackRateControl = false, posterFillMode = 'player-size', bufferStateDelayInMilliseconds, hideControlsWhenPointerDoesntMove = true, overflowVisible = false, renderMuteButton, browserMediaControlsBehavior: passedBrowserMediaControlsBehavior, overrideInternalClassName, logLevel = 'info', noSuspense, acknowledgeRemotionLicense, audioLatencyHint = 'playback', sampleRate = 48000, volumePersistenceKey, initialVolume, _experimentalKeepAudioContextAlive = false, ...componentProps }, ref) => {
27
27
  if (typeof window !== 'undefined') {
28
28
  window.remotion_isPlayer = true;
29
29
  }
@@ -172,7 +172,7 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
172
172
  mode: 'prevent-media-session',
173
173
  });
174
174
  }, [passedBrowserMediaControlsBehavior]);
175
- return (jsx_runtime_1.jsx(remotion_1.Internals.IsPlayerContextProvider, { children: jsx_runtime_1.jsx(SharedPlayerContext_js_1.SharedPlayerContexts, { timelineContext: timelineContextValue, playbackRateContext: playbackRateContextValue, component: component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, numberOfSharedAudioTags: numberOfSharedAudioTags, initiallyMuted: initiallyMuted, logLevel: logLevel, audioLatencyHint: audioLatencyHint, sampleRate: sampleRate, volumePersistenceKey: volumePersistenceKey, initialVolume: initialVolume, inputProps: actualInputProps, audioEnabled: true, children: jsx_runtime_1.jsx(remotion_1.Internals.SetTimelineContext.Provider, { value: setTimelineContextValue, children: jsx_runtime_1.jsx(EmitterProvider_js_1.PlayerEmitterProvider, { currentPlaybackRate: currentPlaybackRate, children: jsx_runtime_1.jsx(PlayerUI_js_1.default, { ref: rootRef, posterFillMode: posterFillMode, renderLoading: renderLoading, autoPlay: Boolean(autoPlay), loop: Boolean(loop), controls: Boolean(controls), errorFallback: errorFallback, style: style, inputProps: actualInputProps, allowFullscreen: Boolean(allowFullscreen), moveToBeginningWhenEnded: Boolean(moveToBeginningWhenEnded), clickToPlay: typeof clickToPlay === 'boolean'
175
+ return (jsx_runtime_1.jsx(remotion_1.Internals.IsPlayerContextProvider, { children: jsx_runtime_1.jsx(SharedPlayerContext_js_1.SharedPlayerContexts, { timelineContext: timelineContextValue, playbackRateContext: playbackRateContextValue, component: component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, numberOfSharedAudioTags: numberOfSharedAudioTags, initiallyMuted: initiallyMuted, logLevel: logLevel, audioLatencyHint: audioLatencyHint, sampleRate: sampleRate, _experimentalKeepAudioContextAlive: _experimentalKeepAudioContextAlive, volumePersistenceKey: volumePersistenceKey, initialVolume: initialVolume, inputProps: actualInputProps, audioEnabled: true, children: jsx_runtime_1.jsx(remotion_1.Internals.SetTimelineContext.Provider, { value: setTimelineContextValue, children: jsx_runtime_1.jsx(EmitterProvider_js_1.PlayerEmitterProvider, { currentPlaybackRate: currentPlaybackRate, children: jsx_runtime_1.jsx(PlayerUI_js_1.default, { ref: rootRef, posterFillMode: posterFillMode, renderLoading: renderLoading, autoPlay: Boolean(autoPlay), loop: Boolean(loop), controls: Boolean(controls), errorFallback: errorFallback, style: style, inputProps: actualInputProps, allowFullscreen: Boolean(allowFullscreen), moveToBeginningWhenEnded: Boolean(moveToBeginningWhenEnded), clickToPlay: typeof clickToPlay === 'boolean'
176
176
  ? clickToPlay
177
177
  : Boolean(controls), showVolumeControls: Boolean(showVolumeControls), doubleClickToFullscreen: Boolean(doubleClickToFullscreen), spaceKeyToPlayOrPause: Boolean(spaceKeyToPlayOrPause), playbackRate: currentPlaybackRate, className: className !== null && className !== void 0 ? className : undefined, showPosterWhenUnplayed: Boolean(showPosterWhenUnplayed), showPosterWhenEnded: Boolean(showPosterWhenEnded), showPosterWhenPaused: Boolean(showPosterWhenPaused), showPosterWhenBuffering: Boolean(showPosterWhenBuffering), showPosterWhenBufferingAndPaused: Boolean(showPosterWhenBufferingAndPaused), renderPoster: renderPoster, inFrame: inFrame !== null && inFrame !== void 0 ? inFrame : null, outFrame: outFrame !== null && outFrame !== void 0 ? outFrame : null, initiallyShowControls: initiallyShowControls !== null && initiallyShowControls !== void 0 ? initiallyShowControls : true, renderFullscreen: renderFullscreenButton !== null && renderFullscreenButton !== void 0 ? renderFullscreenButton : null, renderPlayPauseButton: renderPlayPauseButton !== null && renderPlayPauseButton !== void 0 ? renderPlayPauseButton : null, renderMuteButton: renderMuteButton !== null && renderMuteButton !== void 0 ? renderMuteButton : null, renderVolumeSlider: renderVolumeSlider !== null && renderVolumeSlider !== void 0 ? renderVolumeSlider : null, renderCustomControls: renderCustomControls !== null && renderCustomControls !== void 0 ? renderCustomControls : null, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl, bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds !== null && bufferStateDelayInMilliseconds !== void 0 ? bufferStateDelayInMilliseconds : 300, hideControlsWhenPointerDoesntMove: hideControlsWhenPointerDoesntMove, overflowVisible: overflowVisible, browserMediaControlsBehavior: browserMediaControlsBehavior, overrideInternalClassName: overrideInternalClassName !== null && overrideInternalClassName !== void 0 ? overrideInternalClassName : undefined, noSuspense: Boolean(noSuspense) }) }) }) }) }));
178
178
  };
@@ -20,4 +20,5 @@ export declare const SharedPlayerContexts: React.FC<{
20
20
  readonly initialVolume?: number;
21
21
  readonly inputProps: Record<string, unknown>;
22
22
  readonly audioEnabled: boolean;
23
+ readonly _experimentalKeepAudioContextAlive: boolean;
23
24
  }>;
@@ -7,7 +7,7 @@ const remotion_1 = require("remotion");
7
7
  const timeline_imperative_context_js_1 = require("./timeline-imperative-context.js");
8
8
  const volume_persistence_js_1 = require("./volume-persistence.js");
9
9
  exports.PLAYER_COMP_ID = 'player-comp';
10
- const SharedPlayerContexts = ({ children, timelineContext, playbackRateContext, fps, compositionHeight, compositionWidth, durationInFrames, component, numberOfSharedAudioTags, initiallyMuted, logLevel, audioLatencyHint, sampleRate, volumePersistenceKey, initialVolume, inputProps, audioEnabled, }) => {
10
+ const SharedPlayerContexts = ({ children, timelineContext, playbackRateContext, fps, compositionHeight, compositionWidth, durationInFrames, component, numberOfSharedAudioTags, initiallyMuted, logLevel, audioLatencyHint, sampleRate, volumePersistenceKey, initialVolume, inputProps, audioEnabled, _experimentalKeepAudioContextAlive, }) => {
11
11
  const persistVolumeToStorage = initialVolume === undefined;
12
12
  const compositionManagerContext = (0, react_1.useMemo)(() => {
13
13
  const context = {
@@ -102,6 +102,6 @@ const SharedPlayerContexts = ({ children, timelineContext, playbackRateContext,
102
102
  audioAndVideoTags: timelineContext.audioAndVideoTags,
103
103
  };
104
104
  }, [timelineContext.audioAndVideoTags, timelineContext.imperativePlaying]);
105
- return (jsx_runtime_1.jsx(remotion_1.Internals.RemotionEnvironmentContext.Provider, { value: env, children: jsx_runtime_1.jsx(remotion_1.Internals.LogLevelContext.Provider, { value: logLevelContext, children: jsx_runtime_1.jsx(remotion_1.Internals.CanUseRemotionHooksProvider, { children: jsx_runtime_1.jsx(remotion_1.Internals.AbsoluteTimeContext.Provider, { value: timelineContext, children: jsx_runtime_1.jsx(remotion_1.Internals.PlaybackRateContext.Provider, { value: playbackRateContext, children: jsx_runtime_1.jsx(timeline_imperative_context_js_1.CoreTimelineImperativeContextProvider, { value: timelineImperativeContextValue, children: jsx_runtime_1.jsx(remotion_1.Internals.TimelineContext.Provider, { value: timelineContext, children: jsx_runtime_1.jsx(remotion_1.Internals.CompositionManager.Provider, { value: compositionManagerContext, children: jsx_runtime_1.jsx(remotion_1.Internals.PrefetchProvider, { children: jsx_runtime_1.jsx(remotion_1.Internals.DurationsContextProvider, { children: jsx_runtime_1.jsx(remotion_1.Internals.MediaVolumeContext.Provider, { value: mediaVolumeContextValue, children: jsx_runtime_1.jsx(remotion_1.Internals.SetMediaVolumeContext.Provider, { value: setMediaVolumeContextValue, children: jsx_runtime_1.jsx(remotion_1.Internals.BufferingProvider, { children: jsx_runtime_1.jsx(remotion_1.Internals.SharedAudioContextProvider, { audioLatencyHint: audioLatencyHint, audioEnabled: shouldCreateAudioContext, previewSampleRate: sampleRate, children: jsx_runtime_1.jsx(remotion_1.Internals.SharedAudioTagsContextProvider, { numberOfAudioTags: numberOfSharedAudioTags, children: children }) }) }) }) }) }) }) }) }) }) }) }) }) }) }));
105
+ return (jsx_runtime_1.jsx(remotion_1.Internals.RemotionEnvironmentContext.Provider, { value: env, children: jsx_runtime_1.jsx(remotion_1.Internals.LogLevelContext.Provider, { value: logLevelContext, children: jsx_runtime_1.jsx(remotion_1.Internals.CanUseRemotionHooksProvider, { children: jsx_runtime_1.jsx(remotion_1.Internals.AbsoluteTimeContext.Provider, { value: timelineContext, children: jsx_runtime_1.jsx(remotion_1.Internals.PlaybackRateContext.Provider, { value: playbackRateContext, children: jsx_runtime_1.jsx(timeline_imperative_context_js_1.CoreTimelineImperativeContextProvider, { value: timelineImperativeContextValue, children: jsx_runtime_1.jsx(remotion_1.Internals.TimelineContext.Provider, { value: timelineContext, children: jsx_runtime_1.jsx(remotion_1.Internals.CompositionManager.Provider, { value: compositionManagerContext, children: jsx_runtime_1.jsx(remotion_1.Internals.PrefetchProvider, { children: jsx_runtime_1.jsx(remotion_1.Internals.DurationsContextProvider, { children: jsx_runtime_1.jsx(remotion_1.Internals.MediaVolumeContext.Provider, { value: mediaVolumeContextValue, children: jsx_runtime_1.jsx(remotion_1.Internals.SetMediaVolumeContext.Provider, { value: setMediaVolumeContextValue, children: jsx_runtime_1.jsx(remotion_1.Internals.BufferingProvider, { children: jsx_runtime_1.jsx(remotion_1.Internals.SharedAudioContextProvider, { audioLatencyHint: audioLatencyHint, audioEnabled: shouldCreateAudioContext, previewSampleRate: sampleRate, _experimentalKeepAudioContextAlive: _experimentalKeepAudioContextAlive, children: jsx_runtime_1.jsx(remotion_1.Internals.SharedAudioTagsContextProvider, { numberOfAudioTags: numberOfSharedAudioTags, children: children }) }) }) }) }) }) }) }) }) }) }) }) }) }) }));
106
106
  };
107
107
  exports.SharedPlayerContexts = SharedPlayerContexts;
@@ -50,7 +50,7 @@ const ThumbnailFn = ({ frameToDisplay, style, inputProps, compositionHeight, com
50
50
  const passedInputProps = (0, react_1.useMemo)(() => {
51
51
  return inputProps !== null && inputProps !== void 0 ? inputProps : {};
52
52
  }, [inputProps]);
53
- return (jsx_runtime_1.jsx(remotion_1.Internals.IsPlayerContextProvider, { children: jsx_runtime_1.jsx(SharedPlayerContext_js_1.SharedPlayerContexts, { timelineContext: timelineState, playbackRateContext: playbackRateContext, component: Component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, numberOfSharedAudioTags: 0, initiallyMuted: true, logLevel: logLevel, audioLatencyHint: "playback", sampleRate: 48000, inputProps: passedInputProps, audioEnabled: false, children: jsx_runtime_1.jsx(emitter_context_js_1.ThumbnailEmitterContext.Provider, { value: emitter, children: jsx_runtime_1.jsx(ThumbnailUI_js_1.default, { ref: rootRef, className: className, errorFallback: errorFallback, inputProps: passedInputProps, renderLoading: renderLoading, style: style, overflowVisible: overflowVisible, overrideInternalClassName: overrideInternalClassName, noSuspense: Boolean(noSuspense) }) }) }) }));
53
+ return (jsx_runtime_1.jsx(remotion_1.Internals.IsPlayerContextProvider, { children: jsx_runtime_1.jsx(SharedPlayerContext_js_1.SharedPlayerContexts, { timelineContext: timelineState, playbackRateContext: playbackRateContext, component: Component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, numberOfSharedAudioTags: 0, initiallyMuted: true, logLevel: logLevel, audioLatencyHint: "playback", sampleRate: 48000, inputProps: passedInputProps, audioEnabled: false, _experimentalKeepAudioContextAlive: false, children: jsx_runtime_1.jsx(emitter_context_js_1.ThumbnailEmitterContext.Provider, { value: emitter, children: jsx_runtime_1.jsx(ThumbnailUI_js_1.default, { ref: rootRef, className: className, errorFallback: errorFallback, inputProps: passedInputProps, renderLoading: renderLoading, style: style, overflowVisible: overflowVisible, overrideInternalClassName: overrideInternalClassName, noSuspense: Boolean(noSuspense) }) }) }) }));
54
54
  };
55
55
  const forward = react_1.forwardRef;
56
56
  /*
@@ -119,6 +119,29 @@ const usePlayback = ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, ou
119
119
  (_a = sharedAudioContext === null || sharedAudioContext === void 0 ? void 0 : sharedAudioContext.suspend) === null || _a === void 0 ? void 0 : _a.call(sharedAudioContext);
120
120
  return;
121
121
  }
122
+ if ((sharedAudioContext === null || sharedAudioContext === void 0 ? void 0 : sharedAudioContext._experimentalKeepAudioContextAlive) &&
123
+ sharedAudioContext.audioContext &&
124
+ !muted) {
125
+ // With _experimentalKeepAudioContextAlive, the context clock keeps
126
+ // running while frames are not advancing (pauses, buffering, muted playback), so
127
+ // the anchor is stale by the length of the stall. Without this mode,
128
+ // the 'statechange' listener above re-anchors on the
129
+ // suspended-to-running transition, but that transition never happens
130
+ // here. Re-anchor from the current frame instead, and tell the audio
131
+ // iterators so they drop the nodes they queued against the old
132
+ // anchor and reschedule.
133
+ const changed = (0, set_global_time_anchor_js_1.setGlobalTimeAnchor)({
134
+ audioContext: sharedAudioContext.audioContext,
135
+ audioSyncAnchor: sharedAudioContext.audioSyncAnchor,
136
+ absoluteTimeInSeconds: getCurrentFrame() / config.fps,
137
+ globalPlaybackRate: playbackRate,
138
+ logLevel,
139
+ force: true,
140
+ });
141
+ if (changed) {
142
+ sharedAudioContext.audioSyncAnchorEmitter.dispatch('changed');
143
+ }
144
+ }
122
145
  let hasBeenStopped = false;
123
146
  let audioContextFailed = false;
124
147
  let reqAnimFrameCall = null;
@@ -1108,6 +1108,19 @@ var usePlayback = ({
1108
1108
  sharedAudioContext?.suspend?.();
1109
1109
  return;
1110
1110
  }
1111
+ if (sharedAudioContext?._experimentalKeepAudioContextAlive && sharedAudioContext.audioContext && !muted) {
1112
+ const changed = setGlobalTimeAnchor({
1113
+ audioContext: sharedAudioContext.audioContext,
1114
+ audioSyncAnchor: sharedAudioContext.audioSyncAnchor,
1115
+ absoluteTimeInSeconds: getCurrentFrame() / config.fps,
1116
+ globalPlaybackRate: playbackRate,
1117
+ logLevel,
1118
+ force: true
1119
+ });
1120
+ if (changed) {
1121
+ sharedAudioContext.audioSyncAnchorEmitter.dispatch("changed");
1122
+ }
1123
+ }
1111
1124
  let hasBeenStopped = false;
1112
1125
  let audioContextFailed = false;
1113
1126
  let reqAnimFrameCall = null;
@@ -3158,7 +3171,8 @@ var SharedPlayerContexts = ({
3158
3171
  volumePersistenceKey,
3159
3172
  initialVolume,
3160
3173
  inputProps,
3161
- audioEnabled
3174
+ audioEnabled,
3175
+ _experimentalKeepAudioContextAlive
3162
3176
  }) => {
3163
3177
  const persistVolumeToStorage = initialVolume === undefined;
3164
3178
  const compositionManagerContext = useMemo14(() => {
@@ -3277,6 +3291,7 @@ var SharedPlayerContexts = ({
3277
3291
  audioLatencyHint,
3278
3292
  audioEnabled: shouldCreateAudioContext,
3279
3293
  previewSampleRate: sampleRate,
3294
+ _experimentalKeepAudioContextAlive,
3280
3295
  children: /* @__PURE__ */ jsx14(Internals15.SharedAudioTagsContextProvider, {
3281
3296
  numberOfAudioTags: numberOfSharedAudioTags,
3282
3297
  children
@@ -3468,6 +3483,7 @@ var PlayerFn = ({
3468
3483
  sampleRate = 48000,
3469
3484
  volumePersistenceKey,
3470
3485
  initialVolume,
3486
+ _experimentalKeepAudioContextAlive = false,
3471
3487
  ...componentProps
3472
3488
  }, ref) => {
3473
3489
  if (typeof window !== "undefined") {
@@ -3611,6 +3627,7 @@ var PlayerFn = ({
3611
3627
  logLevel,
3612
3628
  audioLatencyHint,
3613
3629
  sampleRate,
3630
+ _experimentalKeepAudioContextAlive,
3614
3631
  volumePersistenceKey,
3615
3632
  initialVolume,
3616
3633
  inputProps: actualInputProps,
@@ -3899,6 +3916,7 @@ var ThumbnailFn = ({
3899
3916
  sampleRate: 48000,
3900
3917
  inputProps: passedInputProps,
3901
3918
  audioEnabled: false,
3919
+ _experimentalKeepAudioContextAlive: false,
3902
3920
  children: /* @__PURE__ */ jsx17(ThumbnailEmitterContext.Provider, {
3903
3921
  value: emitter,
3904
3922
  children: /* @__PURE__ */ jsx17(ThumbnailUI_default, {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/player"
4
4
  },
5
5
  "name": "@remotion/player",
6
- "version": "4.0.508",
6
+ "version": "4.0.510",
7
7
  "description": "React component for embedding a Remotion preview into your app",
8
8
  "main": "dist/cjs/index.js",
9
9
  "types": "dist/cjs/index.d.ts",
@@ -35,7 +35,7 @@
35
35
  ],
36
36
  "license": "SEE LICENSE IN LICENSE.md",
37
37
  "dependencies": {
38
- "remotion": "4.0.508"
38
+ "remotion": "4.0.510"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "react": ">=16.8.0",
@@ -49,7 +49,7 @@
49
49
  "react-dom": "19.2.3",
50
50
  "webpack": "5.105.0",
51
51
  "zod": "4.4.3",
52
- "@remotion/eslint-config-internal": "4.0.508",
52
+ "@remotion/eslint-config-internal": "4.0.510",
53
53
  "eslint": "9.19.0",
54
54
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
55
55
  },