@remotion/media 4.0.462 → 4.0.464

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.
@@ -20,4 +20,4 @@ export declare const Audio: React.ComponentType<{
20
20
  delayRenderTimeoutInMilliseconds?: number | undefined;
21
21
  onError?: import("../on-error").MediaOnError | undefined;
22
22
  credentials?: RequestCredentials | undefined;
23
- } & Pick<import("remotion").SequenceProps, "durationInFrames" | "from" | "name" | "showInTimeline">>;
23
+ } & Pick<import("remotion").SequenceProps, "durationInFrames" | "from" | "hidden" | "name" | "showInTimeline">>;
@@ -6,6 +6,7 @@ export type FallbackHtml5AudioProps = {
6
6
  useWebAudioApi?: boolean;
7
7
  acceptableTimeShiftInSeconds?: number;
8
8
  pauseWhenBuffering?: boolean;
9
+ preservePitch?: boolean;
9
10
  };
10
11
  export type AudioProps = {
11
12
  src: string;
@@ -31,4 +32,4 @@ export type AudioProps = {
31
32
  delayRenderTimeoutInMilliseconds?: number;
32
33
  onError?: MediaOnError;
33
34
  credentials?: RequestCredentials;
34
- } & Pick<SequenceProps, 'from' | 'durationInFrames' | 'name' | 'showInTimeline'>;
35
+ } & Pick<SequenceProps, 'from' | 'durationInFrames' | 'name' | 'showInTimeline' | 'hidden'>;
@@ -87,6 +87,7 @@ export declare const drawPreviewOverlay: ({ context, audioTime, audioContextStat
87
87
  };
88
88
  } | null;
89
89
  drawFrame: (frame: import("mediabunny").WrappedCanvas) => Promise<void>;
90
+ redrawCurrentFrame: () => Promise<void>;
90
91
  getFramesRendered: () => number;
91
92
  } | null;
92
93
  playbackRate: number;
@@ -1120,13 +1120,16 @@ var videoIteratorManager = async ({
1120
1120
  getStartTime,
1121
1121
  getIsLooping,
1122
1122
  getEffects,
1123
- getEffectChainState,
1124
- getCurrentFrame
1123
+ getEffectChainState
1125
1124
  }) => {
1126
1125
  let videoIteratorsCreated = 0;
1127
1126
  let videoFrameIterator = null;
1128
1127
  let framesRendered = 0;
1129
1128
  let currentDelayHandle = null;
1129
+ let lastDrawnFrame = null;
1130
+ const clearLastDrawnFrame = () => {
1131
+ lastDrawnFrame = null;
1132
+ };
1130
1133
  if (canvas) {
1131
1134
  const displayWidth = await videoTrack.getDisplayWidth();
1132
1135
  const displayHeight = await videoTrack.getDisplayHeight();
@@ -1141,7 +1144,7 @@ var videoIteratorManager = async ({
1141
1144
  alpha: true
1142
1145
  });
1143
1146
  const prewarmedVideoIteratorCache = makePrewarmedVideoIteratorCache(canvasSink);
1144
- const drawFrame = async (frame) => {
1147
+ const paintFrame = async (frame) => {
1145
1148
  if (context && canvas) {
1146
1149
  const effects = getEffects();
1147
1150
  const chainState = getEffectChainState(canvas.width, canvas.height);
@@ -1151,7 +1154,6 @@ var videoIteratorManager = async ({
1151
1154
  source: frame.canvas,
1152
1155
  effects,
1153
1156
  output: canvas,
1154
- frame: getCurrentFrame(),
1155
1157
  width: canvas.width,
1156
1158
  height: canvas.height
1157
1159
  });
@@ -1160,6 +1162,10 @@ var videoIteratorManager = async ({
1160
1162
  context.drawImage(frame.canvas, 0, 0);
1161
1163
  }
1162
1164
  }
1165
+ };
1166
+ const drawFrame = async (frame) => {
1167
+ await paintFrame(frame);
1168
+ lastDrawnFrame = frame;
1163
1169
  framesRendered++;
1164
1170
  drawDebugOverlay();
1165
1171
  const callback = getOnVideoFrameCallback();
@@ -1168,9 +1174,22 @@ var videoIteratorManager = async ({
1168
1174
  }
1169
1175
  Internals4.Log.trace({ logLevel, tag: "@remotion/media" }, `[MediaPlayer] Drew frame ${frame.timestamp.toFixed(3)}s`);
1170
1176
  };
1177
+ const redrawCurrentFrame = async () => {
1178
+ if (!lastDrawnFrame) {
1179
+ return;
1180
+ }
1181
+ await paintFrame(lastDrawnFrame);
1182
+ drawDebugOverlay();
1183
+ const callback = getOnVideoFrameCallback();
1184
+ if (callback) {
1185
+ callback(lastDrawnFrame.canvas);
1186
+ }
1187
+ Internals4.Log.trace({ logLevel, tag: "@remotion/media" }, `[MediaPlayer] Redrew frame ${lastDrawnFrame.timestamp.toFixed(3)}s with updated effects`);
1188
+ };
1171
1189
  const startVideoIterator = async (timeToSeek, nonce) => {
1172
1190
  let __stack = [];
1173
1191
  try {
1192
+ clearLastDrawnFrame();
1174
1193
  videoFrameIterator?.destroy();
1175
1194
  const delayHandle = __using(__stack, delayPlaybackHandleIfNotPremounting(), 0);
1176
1195
  currentDelayHandle = delayHandle;
@@ -1222,6 +1241,7 @@ var videoIteratorManager = async ({
1222
1241
  getVideoIteratorsCreated: () => videoIteratorsCreated,
1223
1242
  seek,
1224
1243
  destroy: () => {
1244
+ clearLastDrawnFrame();
1225
1245
  prewarmedVideoIteratorCache.destroy();
1226
1246
  videoFrameIterator?.destroy();
1227
1247
  if (context && canvas) {
@@ -1235,6 +1255,7 @@ var videoIteratorManager = async ({
1235
1255
  },
1236
1256
  getVideoFrameIterator: () => videoFrameIterator,
1237
1257
  drawFrame,
1258
+ redrawCurrentFrame,
1238
1259
  getFramesRendered: () => framesRendered
1239
1260
  };
1240
1261
  };
@@ -1265,7 +1286,6 @@ class MediaPlayer {
1265
1286
  onVideoFrameCallback = null;
1266
1287
  getEffects;
1267
1288
  getEffectChainState;
1268
- getCurrentFrame;
1269
1289
  initializationPromise = null;
1270
1290
  bufferState;
1271
1291
  isPremounting;
@@ -1294,8 +1314,7 @@ class MediaPlayer {
1294
1314
  credentials,
1295
1315
  tagType,
1296
1316
  getEffects,
1297
- getEffectChainState,
1298
- getCurrentFrame
1317
+ getEffectChainState
1299
1318
  }) {
1300
1319
  this.canvas = canvas ?? null;
1301
1320
  this.src = src;
@@ -1326,7 +1345,6 @@ class MediaPlayer {
1326
1345
  this.tagType = tagType;
1327
1346
  this.getEffects = getEffects;
1328
1347
  this.getEffectChainState = getEffectChainState;
1329
- this.getCurrentFrame = getCurrentFrame;
1330
1348
  if (canvas) {
1331
1349
  const context = canvas.getContext("2d", {
1332
1350
  alpha: true,
@@ -1436,8 +1454,7 @@ class MediaPlayer {
1436
1454
  getStartTime: () => this.getStartTime(),
1437
1455
  getIsLooping: () => this.loop,
1438
1456
  getEffects: this.getEffects,
1439
- getEffectChainState: this.getEffectChainState,
1440
- getCurrentFrame: this.getCurrentFrame
1457
+ getEffectChainState: this.getEffectChainState
1441
1458
  });
1442
1459
  }
1443
1460
  const startTime = this.getTrimmedTime(startTimeUnresolved);
@@ -1749,6 +1766,9 @@ class MediaPlayer {
1749
1766
  setVideoFrameCallback(callback) {
1750
1767
  this.onVideoFrameCallback = callback;
1751
1768
  }
1769
+ async redrawVideoEffects() {
1770
+ await this.videoIteratorManager?.redrawCurrentFrame();
1771
+ }
1752
1772
  drawDebugOverlay = () => {
1753
1773
  if (!this.debugOverlay)
1754
1774
  return;
@@ -2093,8 +2113,7 @@ var AudioForPreviewAssertedShowing = ({
2093
2113
  credentials,
2094
2114
  tagType: "audio",
2095
2115
  getEffects: () => [],
2096
- getEffectChainState: () => null,
2097
- getCurrentFrame: () => 0
2116
+ getEffectChainState: () => null
2098
2117
  });
2099
2118
  mediaPlayerRef.current = player;
2100
2119
  player.initialize(currentTimeRef.current, initialMuted.current).then((result) => {
@@ -4363,6 +4382,7 @@ var AudioForRendering = ({
4363
4382
  onError: fallbackHtml5AudioProps?.onError,
4364
4383
  toneFrequency,
4365
4384
  acceptableTimeShiftInSeconds: fallbackHtml5AudioProps?.acceptableTimeShiftInSeconds,
4385
+ preservePitch: fallbackHtml5AudioProps?.preservePitch ?? true,
4366
4386
  name,
4367
4387
  showInTimeline
4368
4388
  });
@@ -4389,7 +4409,8 @@ var audioSchema = {
4389
4409
  default: 1,
4390
4410
  description: "Playback Rate"
4391
4411
  },
4392
- loop: { type: "boolean", default: false, description: "Loop" }
4412
+ loop: { type: "boolean", default: false, description: "Loop" },
4413
+ hidden: Internals16.hiddenField
4393
4414
  };
4394
4415
  var AudioInner = (props) => {
4395
4416
  const {
@@ -4399,6 +4420,7 @@ var AudioInner = (props) => {
4399
4420
  _experimentalControls: controls,
4400
4421
  from,
4401
4422
  durationInFrames,
4423
+ hidden,
4402
4424
  ...otherProps
4403
4425
  } = props;
4404
4426
  const environment = useRemotionEnvironment2();
@@ -4458,6 +4480,7 @@ var AudioInner = (props) => {
4458
4480
  _experimentalControls: controls,
4459
4481
  _remotionInternalLoopDisplay: loopDisplay,
4460
4482
  showInTimeline: showInTimeline ?? true,
4483
+ hidden,
4461
4484
  children: environment.isRendering ? /* @__PURE__ */ jsx3(AudioForRendering, {
4462
4485
  ...otherProps
4463
4486
  }) : /* @__PURE__ */ jsx3(AudioForPreview, {
@@ -4611,8 +4634,6 @@ var VideoForPreviewAssertedShowing = ({
4611
4634
  experimentalEffectsRef.current = _experimentalEffects;
4612
4635
  const effectChainStateRef = useRef2(effectChainState);
4613
4636
  effectChainStateRef.current = effectChainState;
4614
- const frameRef = useRef2(frame);
4615
- frameRef.current = frame;
4616
4637
  const parentSequence = useContext4(SequenceContext2);
4617
4638
  const isPremounting = Boolean(parentSequence?.premounting);
4618
4639
  const isPostmounting = Boolean(parentSequence?.postmounting);
@@ -4718,8 +4739,7 @@ var VideoForPreviewAssertedShowing = ({
4718
4739
  credentials,
4719
4740
  tagType: "video",
4720
4741
  getEffects: () => experimentalEffectsRef.current,
4721
- getEffectChainState: (width, height) => effectChainStateRef.current?.get(width, height),
4722
- getCurrentFrame: () => frameRef.current
4742
+ getEffectChainState: (width, height) => effectChainStateRef.current?.get(width, height)
4723
4743
  });
4724
4744
  mediaPlayerRef.current = player;
4725
4745
  player.initialize(currentTimeRef.current, initialMuted.current).then((result) => {
@@ -4854,6 +4874,13 @@ var VideoForPreviewAssertedShowing = ({
4854
4874
  }
4855
4875
  mediaPlayer.setVideoFrameCallback(onVideoFrame ?? null);
4856
4876
  }, [onVideoFrame, mediaPlayerReady]);
4877
+ useLayoutEffect3(() => {
4878
+ const mediaPlayer = mediaPlayerRef.current;
4879
+ if (!mediaPlayer || !mediaPlayerReady) {
4880
+ return;
4881
+ }
4882
+ mediaPlayer.redrawVideoEffects().catch(() => {});
4883
+ }, [_experimentalEffects, mediaPlayerReady, mediaPlayerRef]);
4857
4884
  const actualStyle = useMemo4(() => {
4858
4885
  return {
4859
4886
  ...style,
@@ -5202,6 +5229,7 @@ var VideoForRendering = ({
5202
5229
  trimAfter: trimAfterValue,
5203
5230
  trimBefore: trimBeforeValue,
5204
5231
  useWebAudioApi: fallbackOffthreadVideoProps?.useWebAudioApi ?? false,
5232
+ preservePitch: fallbackOffthreadVideoProps?.preservePitch ?? true,
5205
5233
  startFrom: undefined,
5206
5234
  endAt: undefined,
5207
5235
  stack,
@@ -5255,8 +5283,13 @@ var videoSchema = {
5255
5283
  default: 1,
5256
5284
  description: "Playback Rate"
5257
5285
  },
5286
+ hidden: {
5287
+ type: "boolean",
5288
+ default: false,
5289
+ description: "Hidden"
5290
+ },
5258
5291
  loop: { type: "boolean", default: false, description: "Loop" },
5259
- ...Internals20.sequenceStyleSchema
5292
+ ...Internals20.sequenceVisualStyleSchema
5260
5293
  };
5261
5294
  var InnerVideo = ({
5262
5295
  src,
@@ -5393,7 +5426,8 @@ var VideoInner = ({
5393
5426
  _experimentalInitiallyDrawCachedFrame,
5394
5427
  _experimentalEffects,
5395
5428
  durationInFrames,
5396
- from
5429
+ from,
5430
+ hidden
5397
5431
  }) => {
5398
5432
  const fallbackLogLevel = Internals20.useLogLevel();
5399
5433
  const [mediaVolume] = Internals20.useMediaVolumeState();
@@ -5454,6 +5488,7 @@ var VideoInner = ({
5454
5488
  _remotionInternalLoopDisplay: loopDisplay,
5455
5489
  _experimentalEffects: memoizedEffectDefinitions,
5456
5490
  showInTimeline: showInTimeline ?? true,
5491
+ hidden,
5457
5492
  children: /* @__PURE__ */ jsx6(InnerVideo, {
5458
5493
  audioStreamIndex: audioStreamIndex ?? 0,
5459
5494
  className,
package/dist/index.d.ts CHANGED
@@ -24,7 +24,7 @@ export declare const experimental_Audio: import("react").ComponentType<{
24
24
  delayRenderTimeoutInMilliseconds?: number | undefined;
25
25
  onError?: import("./on-error").MediaOnError | undefined;
26
26
  credentials?: RequestCredentials | undefined;
27
- } & Pick<import("remotion").SequenceProps, "durationInFrames" | "from" | "name" | "showInTimeline">>;
27
+ } & Pick<import("remotion").SequenceProps, "durationInFrames" | "from" | "hidden" | "name" | "showInTimeline">>;
28
28
  /**
29
29
  * @deprecated Now just `Video`
30
30
  */
@@ -60,7 +60,7 @@ export declare const experimental_Video: import("react").ComponentType<{
60
60
  objectFit: import(".").VideoObjectFit;
61
61
  _experimentalInitiallyDrawCachedFrame: boolean;
62
62
  _experimentalEffects: import("remotion").EffectsProp;
63
- }> & Pick<import("remotion").SequenceProps, "durationInFrames" | "from" | "name">>;
63
+ }> & Pick<import("remotion").SequenceProps, "durationInFrames" | "from" | "hidden" | "name">>;
64
64
  export { AudioForPreview } from './audio/audio-for-preview';
65
65
  export { AudioProps, FallbackHtml5AudioProps } from './audio/props';
66
66
  export { MediaErrorAction } from './on-error';
@@ -42,13 +42,12 @@ export declare class MediaPlayer {
42
42
  private onVideoFrameCallback;
43
43
  private getEffects;
44
44
  private getEffectChainState;
45
- private getCurrentFrame;
46
45
  private initializationPromise;
47
46
  private bufferState;
48
47
  private isPremounting;
49
48
  private isPostmounting;
50
49
  private seekPromiseChain;
51
- constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, durationInFrames, onVideoFrameCallback, playing, sequenceOffset, credentials, tagType, getEffects, getEffectChainState, getCurrentFrame }: {
50
+ constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, durationInFrames, onVideoFrameCallback, playing, sequenceOffset, credentials, tagType, getEffects, getEffectChainState }: {
52
51
  canvas: HTMLCanvasElement | OffscreenCanvas | null;
53
52
  src: string;
54
53
  logLevel: LogLevel;
@@ -72,7 +71,6 @@ export declare class MediaPlayer {
72
71
  tagType: 'audio' | 'video';
73
72
  getEffects: () => EffectDefinitionAndStack<unknown>[];
74
73
  getEffectChainState: (width: number, height: number) => EffectChainState | null;
75
- getCurrentFrame: () => number;
76
74
  });
77
75
  private input;
78
76
  private isDisposalError;
@@ -107,6 +105,7 @@ export declare class MediaPlayer {
107
105
  private getTargetTime;
108
106
  private scheduleAudioNode;
109
107
  setVideoFrameCallback(callback: null | ((frame: CanvasImageSource) => void)): void;
108
+ redrawVideoEffects(): Promise<void>;
110
109
  private drawDebugOverlay;
111
110
  audioSyncAnchorChanged: () => void;
112
111
  }
@@ -13,6 +13,7 @@ export type FallbackOffthreadVideoProps = {
13
13
  useWebAudioApi?: boolean;
14
14
  pauseWhenBuffering?: boolean;
15
15
  onAutoPlayError?: null | (() => void);
16
+ preservePitch?: boolean;
16
17
  };
17
18
  type MandatoryVideoProps = {
18
19
  src: string;
@@ -55,5 +56,5 @@ type OptionalVideoProps = {
55
56
  export type InnerVideoProps = MandatoryVideoProps & OuterVideoProps & Omit<OptionalVideoProps, '_experimentalEffects'> & {
56
57
  _experimentalEffects: EffectDefinitionAndStack<unknown>[];
57
58
  };
58
- export type VideoProps = MandatoryVideoProps & Partial<OuterVideoProps> & Partial<OptionalVideoProps> & Pick<SequenceProps, 'durationInFrames' | 'from' | 'name'>;
59
+ export type VideoProps = MandatoryVideoProps & Partial<OuterVideoProps> & Partial<OptionalVideoProps> & Pick<SequenceProps, 'durationInFrames' | 'from' | 'name' | 'hidden'>;
59
60
  export {};
@@ -31,4 +31,4 @@ export declare const Video: React.ComponentType<{
31
31
  objectFit: import("./props").VideoObjectFit;
32
32
  _experimentalInitiallyDrawCachedFrame: boolean;
33
33
  _experimentalEffects: import("remotion").EffectsProp;
34
- }> & Pick<import("remotion").SequenceProps, "durationInFrames" | "from" | "name">>;
34
+ }> & Pick<import("remotion").SequenceProps, "durationInFrames" | "from" | "hidden" | "name">>;
@@ -2,7 +2,7 @@ import type { InputVideoTrack, WrappedCanvas } from 'mediabunny';
2
2
  import type { EffectChainState, EffectDefinitionAndStack } from 'remotion';
3
3
  import type { DelayPlaybackIfNotPremounting } from './delay-playback-if-not-premounting';
4
4
  import type { Nonce } from './nonce-manager';
5
- export declare const videoIteratorManager: ({ delayPlaybackHandleIfNotPremounting, canvas, context, drawDebugOverlay, logLevel, getOnVideoFrameCallback, videoTrack, getLoopSegmentMediaEndTimestamp, getStartTime, getIsLooping, getEffects, getEffectChainState, getCurrentFrame, }: {
5
+ export declare const videoIteratorManager: ({ delayPlaybackHandleIfNotPremounting, canvas, context, drawDebugOverlay, logLevel, getOnVideoFrameCallback, videoTrack, getLoopSegmentMediaEndTimestamp, getStartTime, getIsLooping, getEffects, getEffectChainState, }: {
6
6
  videoTrack: InputVideoTrack;
7
7
  delayPlaybackHandleIfNotPremounting: () => DelayPlaybackIfNotPremounting;
8
8
  context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;
@@ -15,7 +15,6 @@ export declare const videoIteratorManager: ({ delayPlaybackHandleIfNotPremountin
15
15
  getIsLooping: () => boolean;
16
16
  getEffects: () => EffectDefinitionAndStack<unknown>[];
17
17
  getEffectChainState: (width: number, height: number) => EffectChainState | null;
18
- getCurrentFrame: () => number;
19
18
  }) => Promise<{
20
19
  startVideoIterator: (timeToSeek: number, nonce: Nonce) => Promise<void>;
21
20
  getVideoIteratorsCreated: () => number;
@@ -37,6 +36,7 @@ export declare const videoIteratorManager: ({ delayPlaybackHandleIfNotPremountin
37
36
  };
38
37
  } | null;
39
38
  drawFrame: (frame: WrappedCanvas) => Promise<void>;
39
+ redrawCurrentFrame: () => Promise<void>;
40
40
  getFramesRendered: () => number;
41
41
  }>;
42
42
  export type VideoIteratorManager = Awaited<ReturnType<typeof videoIteratorManager>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/media",
3
- "version": "4.0.462",
3
+ "version": "4.0.464",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/esm/index.mjs",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "mediabunny": "1.45.0",
26
- "remotion": "4.0.462",
26
+ "remotion": "4.0.464",
27
27
  "zod": "4.3.6"
28
28
  },
29
29
  "peerDependencies": {
@@ -31,7 +31,7 @@
31
31
  "react-dom": ">=16.8.0"
32
32
  },
33
33
  "devDependencies": {
34
- "@remotion/eslint-config-internal": "4.0.462",
34
+ "@remotion/eslint-config-internal": "4.0.464",
35
35
  "@vitest/browser-webdriverio": "4.0.9",
36
36
  "eslint": "9.19.0",
37
37
  "react": "19.2.3",