remotion 4.0.511 → 4.0.513

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.
@@ -13,6 +13,23 @@ const use_crop_style_js_1 = require("./use-crop-style.js");
13
13
  const use_delay_render_js_1 = require("./use-delay-render.js");
14
14
  const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
15
15
  const with_interactivity_schema_js_1 = require("./with-interactivity-schema.js");
16
+ // `transferControlToOffscreen()` may only be called once per canvas — a second
17
+ // call throws an `InvalidStateError`. The layout effect that needs the
18
+ // `OffscreenCanvas` can run more than once for the same canvas element: its
19
+ // dependencies (e.g. the paint callback) can change identity without the
20
+ // canvas remounting, and React StrictMode intentionally double-invokes
21
+ // effects. Cache the transferred `OffscreenCanvas` per canvas element so
22
+ // re-runs reuse it instead of throwing.
23
+ const transferredOffscreenCanvases = new WeakMap();
24
+ const getTransferredOffscreenCanvas = (canvas) => {
25
+ const existing = transferredOffscreenCanvases.get(canvas);
26
+ if (existing) {
27
+ return existing;
28
+ }
29
+ const offscreen = canvas.transferControlToOffscreen();
30
+ transferredOffscreenCanvases.set(canvas, offscreen);
31
+ return offscreen;
32
+ };
16
33
  // Memoize the support check across the session — neither the platform
17
34
  // capability nor the chrome://flags toggle can change between calls.
18
35
  // SSR results are not cached so the check runs again once `document` exists.
@@ -297,7 +314,7 @@ const HtmlInCanvasContent = (0, react_1.forwardRef)(({ width, height, effects, c
297
314
  placeholder.layoutSubtree = true;
298
315
  const paintTarget = usesDirectLayoutCanvas
299
316
  ? placeholder
300
- : placeholder.transferControlToOffscreen();
317
+ : getTransferredOffscreenCanvas(placeholder);
301
318
  paintTargetRef.current = paintTarget;
302
319
  resizePaintTarget({
303
320
  target: paintTarget,
@@ -5,6 +5,10 @@ export type ResolvedDragOverrideValue = {
5
5
  readonly type: 'resolved';
6
6
  readonly value: unknown;
7
7
  };
8
+ export declare const getFrameInKeyframedStatusClock: ({ frame, status, }: {
9
+ readonly frame: number;
10
+ readonly status: CanUpdateSequencePropStatusKeyframed;
11
+ }) => number;
8
12
  export declare const resolveDragOverrideValue: ({ dragOverrideValue, frame, }: {
9
13
  dragOverrideValue: DragOverrideValue | undefined;
10
14
  frame: number | null;
@@ -1,7 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getEffectiveVisualModeValue = exports.resolveDragOverrideValue = void 0;
3
+ exports.getEffectiveVisualModeValue = exports.resolveDragOverrideValue = exports.getFrameInKeyframedStatusClock = void 0;
4
4
  const interpolate_keyframed_status_1 = require("./interpolate-keyframed-status");
5
+ const getFrameInKeyframedStatusClock = ({ frame, status, }) => {
6
+ var _a;
7
+ return frame - ((_a = status.keyframeDisplayOffsetAdjustment) !== null && _a !== void 0 ? _a : 0);
8
+ };
9
+ exports.getFrameInKeyframedStatusClock = getFrameInKeyframedStatusClock;
5
10
  const resolveDragOverrideValue = ({ dragOverrideValue, frame, }) => {
6
11
  if (dragOverrideValue === undefined) {
7
12
  return { type: 'none' };
@@ -14,7 +19,10 @@ const resolveDragOverrideValue = ({ dragOverrideValue, frame, }) => {
14
19
  }
15
20
  const interpolated = (0, interpolate_keyframed_status_1.interpolateKeyframedStatus)({
16
21
  forceSpringAllowTail: null,
17
- frame,
22
+ frame: (0, exports.getFrameInKeyframedStatusClock)({
23
+ frame,
24
+ status: dragOverrideValue.status,
25
+ }),
18
26
  status: dragOverrideValue.status,
19
27
  });
20
28
  if (interpolated === null) {
@@ -35,7 +43,7 @@ const getEffectiveVisualModeValue = ({ propStatus, dragOverrideValue, defaultVal
35
43
  if (frame !== null) {
36
44
  return (0, interpolate_keyframed_status_1.interpolateKeyframedStatus)({
37
45
  forceSpringAllowTail: null,
38
- frame,
46
+ frame: (0, exports.getFrameInKeyframedStatusClock)({ frame, status: propStatus }),
39
47
  status: propStatus,
40
48
  });
41
49
  }
@@ -490,8 +490,12 @@ const interpolateString = ({ input, inputRange, outputRange, options, }) => {
490
490
  var _a;
491
491
  const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
492
492
  const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
493
+ const posterizedInput = (options === null || options === void 0 ? void 0 : options.posterize) === undefined
494
+ ? input
495
+ : Math.floor(input / options.posterize) * options.posterize;
496
+ const segmentIndex = inputRange.length === 1 ? 0 : findRange(posterizedInput, inputRange);
493
497
  const parsedOutputRange = hasAxisRotation
494
- ? initiallyParsedOutputRange.map((parsed) => {
498
+ ? initiallyParsedOutputRange.map((parsed, index) => {
495
499
  if (parsed.kind !== 'rotate') {
496
500
  return parsed;
497
501
  }
@@ -501,9 +505,22 @@ const interpolateString = ({ input, inputRange, outputRange, options, }) => {
501
505
  if (parsed.dimensions !== 1) {
502
506
  throw new TypeError('Cannot interpolate a multi-angle rotate value with an axis rotation');
503
507
  }
508
+ // A zero-degree rotation is the identity regardless of its axis. Reusing
509
+ // the active neighbor's axis prevents the axis from drifting while the
510
+ // angle interpolates away from zero.
511
+ const adjacentAxisRotation = parsed.values[0] === 0
512
+ ? index === segmentIndex
513
+ ? initiallyParsedOutputRange[index + 1]
514
+ : index === segmentIndex + 1
515
+ ? initiallyParsedOutputRange[index - 1]
516
+ : undefined
517
+ : undefined;
518
+ const axis = (adjacentAxisRotation === null || adjacentAxisRotation === void 0 ? void 0 : adjacentAxisRotation.axisRotation)
519
+ ? adjacentAxisRotation.values
520
+ : [0, 0, 1];
504
521
  return {
505
522
  kind: 'rotate',
506
- values: [0, 0, 1, parsed.values[0]],
523
+ values: [axis[0], axis[1], axis[2], parsed.values[0]],
507
524
  units: [null, null, null, parsed.units[0]],
508
525
  dimensions: 4,
509
526
  axisRotation: true,
@@ -127,7 +127,7 @@ const SeriesInner = (props) => {
127
127
  const currentStartFrame = startFrame + offset;
128
128
  const nextStartFrame = startFrame + durationInFramesProp + offset;
129
129
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
130
- jsx_runtime_1.jsx(SequenceWithoutSchemaWithRef, { ref: ref, name: name || '<Series.Sequence>', _remotionInternalDocumentationLink: name ? undefined : 'https://www.remotion.dev/docs/series', controls: controls !== null && controls !== void 0 ? controls : undefined, from: currentStartFrame, durationInFrames: durationInFramesProp, ...passedProps, children: jsx_runtime_1.jsx(is_inside_series_js_1.IsNotInsideSeriesProvider, { children: sequenceChildren }) }), renderChildren(i + 1, nextStartFrame)] }));
130
+ jsx_runtime_1.jsx(SequenceWithoutSchemaWithRef, { ref: ref, name: name || '<Series.Sequence>', _remotionInternalDocumentationLink: name ? undefined : 'https://www.remotion.dev/docs/series', controls: controls !== null && controls !== void 0 ? controls : undefined, from: currentStartFrame, durationInFrames: durationInFramesProp, ...passedProps, _remotionInternalSingleChildComponent: (0, enable_sequence_stack_traces_js_1.getSingleChildComponent)(sequenceChildren), children: jsx_runtime_1.jsx(is_inside_series_js_1.IsNotInsideSeriesProvider, { children: sequenceChildren }) }), renderChildren(i + 1, nextStartFrame)] }));
131
131
  },
132
132
  });
133
133
  };
@@ -4,6 +4,7 @@ import type { CanUpdateSequencePropsResponse, SequencePropsSubscriptionKey } fro
4
4
  export type CanUpdateSequencePropStatusStatic = {
5
5
  status: 'static';
6
6
  codeValue: unknown;
7
+ keyframeDisplayOffsetAdjustment: number | null;
7
8
  numericExpression?: VideoConfigNumericExpression;
8
9
  };
9
10
  export type CanUpdateSequencePropStatusKeyframe = {
@@ -67,6 +68,13 @@ export type CanUpdateSequencePropStatusComputed = {
67
68
  export type CanUpdateSequencePropStatusKeyframed = {
68
69
  status: 'keyframed';
69
70
  interpolationFunction: CanUpdateSequencePropStatusInterpolationFunction;
71
+ /**
72
+ * Added to the timeline track's keyframe display offset and subtracted from
73
+ * the controlled element's local frame when evaluating the interpolation.
74
+ * This is non-zero when the useCurrentFrame() call is outside a timing
75
+ * element that wraps the controlled element.
76
+ */
77
+ keyframeDisplayOffsetAdjustment: number | null;
70
78
  keyframes: CanUpdateSequencePropStatusKeyframe[];
71
79
  easing: CanUpdateSequencePropStatusEasing[];
72
80
  clamping: CanUpdateSequencePropStatusClamping;
@@ -111,7 +111,7 @@ const computeEffectiveSchemaValuesDotNotation = ({ schema, currentValue, overrid
111
111
  else if (frame !== null) {
112
112
  const interpolated = (0, interpolate_keyframed_status_js_1.interpolateKeyframedStatus)({
113
113
  forceSpringAllowTail: null,
114
- frame,
114
+ frame: (0, get_effective_visual_mode_value_js_1.getFrameInKeyframedStatusClock)({ frame, status }),
115
115
  status,
116
116
  });
117
117
  value = interpolated !== null && interpolated !== void 0 ? interpolated : currentValue[key];
@@ -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.511";
6
+ export declare const VERSION = "4.0.513";
@@ -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.511';
10
+ exports.VERSION = '4.0.513';
@@ -1340,7 +1340,7 @@ var getSingleChildComponent = (children) => {
1340
1340
  };
1341
1341
 
1342
1342
  // src/version.ts
1343
- var VERSION = "4.0.511";
1343
+ var VERSION = "4.0.513";
1344
1344
 
1345
1345
  // src/multiple-versions-warning.ts
1346
1346
  var checkMultipleRemotionVersions = () => {
@@ -3114,7 +3114,9 @@ var interpolateString = ({
3114
3114
  }) => {
3115
3115
  const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
3116
3116
  const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
3117
- const parsedOutputRange = hasAxisRotation ? initiallyParsedOutputRange.map((parsed) => {
3117
+ const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
3118
+ const segmentIndex = inputRange.length === 1 ? 0 : findRange(posterizedInput, inputRange);
3119
+ const parsedOutputRange = hasAxisRotation ? initiallyParsedOutputRange.map((parsed, index) => {
3118
3120
  if (parsed.kind !== "rotate") {
3119
3121
  return parsed;
3120
3122
  }
@@ -3124,9 +3126,11 @@ var interpolateString = ({
3124
3126
  if (parsed.dimensions !== 1) {
3125
3127
  throw new TypeError("Cannot interpolate a multi-angle rotate value with an axis rotation");
3126
3128
  }
3129
+ const adjacentAxisRotation = parsed.values[0] === 0 ? index === segmentIndex ? initiallyParsedOutputRange[index + 1] : index === segmentIndex + 1 ? initiallyParsedOutputRange[index - 1] : undefined : undefined;
3130
+ const axis = adjacentAxisRotation?.axisRotation ? adjacentAxisRotation.values : [0, 0, 1];
3127
3131
  return {
3128
3132
  kind: "rotate",
3129
- values: [0, 0, 1, parsed.values[0]],
3133
+ values: [axis[0], axis[1], axis[2], parsed.values[0]],
3130
3134
  units: [null, null, null, parsed.units[0]],
3131
3135
  dimensions: 4,
3132
3136
  axisRotation: true
@@ -4331,6 +4335,10 @@ var interpolateKeyframedStatus = ({
4331
4335
  };
4332
4336
 
4333
4337
  // src/get-effective-visual-mode-value.ts
4338
+ var getFrameInKeyframedStatusClock = ({
4339
+ frame,
4340
+ status
4341
+ }) => frame - (status.keyframeDisplayOffsetAdjustment ?? 0);
4334
4342
  var resolveDragOverrideValue = ({
4335
4343
  dragOverrideValue,
4336
4344
  frame
@@ -4346,7 +4354,10 @@ var resolveDragOverrideValue = ({
4346
4354
  }
4347
4355
  const interpolated = interpolateKeyframedStatus({
4348
4356
  forceSpringAllowTail: null,
4349
- frame,
4357
+ frame: getFrameInKeyframedStatusClock({
4358
+ frame,
4359
+ status: dragOverrideValue.status
4360
+ }),
4350
4361
  status: dragOverrideValue.status
4351
4362
  });
4352
4363
  if (interpolated === null) {
@@ -4372,7 +4383,7 @@ var getEffectiveVisualModeValue = ({
4372
4383
  if (frame !== null) {
4373
4384
  return interpolateKeyframedStatus({
4374
4385
  forceSpringAllowTail: null,
4375
- frame,
4386
+ frame: getFrameInKeyframedStatusClock({ frame, status: propStatus }),
4376
4387
  status: propStatus
4377
4388
  });
4378
4389
  }
@@ -4759,7 +4770,7 @@ var computeEffectiveSchemaValuesDotNotation = ({
4759
4770
  } else if (frame !== null) {
4760
4771
  const interpolated = interpolateKeyframedStatus({
4761
4772
  forceSpringAllowTail: null,
4762
- frame,
4773
+ frame: getFrameInKeyframedStatusClock({ frame, status }),
4763
4774
  status
4764
4775
  });
4765
4776
  value = interpolated ?? currentValue[key];
@@ -10027,6 +10038,16 @@ import {
10027
10038
  useRef as useRef23
10028
10039
  } from "react";
10029
10040
  import { jsx as jsx26 } from "react/jsx-runtime";
10041
+ var transferredOffscreenCanvases = new WeakMap;
10042
+ var getTransferredOffscreenCanvas = (canvas) => {
10043
+ const existing = transferredOffscreenCanvases.get(canvas);
10044
+ if (existing) {
10045
+ return existing;
10046
+ }
10047
+ const offscreen = canvas.transferControlToOffscreen();
10048
+ transferredOffscreenCanvases.set(canvas, offscreen);
10049
+ return offscreen;
10050
+ };
10030
10051
  var cachedSupport = null;
10031
10052
  var isHtmlInCanvasSupported = () => {
10032
10053
  if (cachedSupport !== null) {
@@ -10287,7 +10308,7 @@ var HtmlInCanvasContent = forwardRef9(({
10287
10308
  throw new Error("Canvas not found");
10288
10309
  }
10289
10310
  placeholder.layoutSubtree = true;
10290
- const paintTarget = usesDirectLayoutCanvas ? placeholder : placeholder.transferControlToOffscreen();
10311
+ const paintTarget = usesDirectLayoutCanvas ? placeholder : getTransferredOffscreenCanvas(placeholder);
10291
10312
  paintTargetRef.current = paintTarget;
10292
10313
  resizePaintTarget({
10293
10314
  target: paintTarget,
@@ -13419,6 +13440,7 @@ var SeriesInner = (props2) => {
13419
13440
  from: currentStartFrame,
13420
13441
  durationInFrames: durationInFramesProp,
13421
13442
  ...passedProps,
13443
+ _remotionInternalSingleChildComponent: getSingleChildComponent(sequenceChildren),
13422
13444
  children: /* @__PURE__ */ jsx38(IsNotInsideSeriesProvider, {
13423
13445
  children: sequenceChildren
13424
13446
  })
@@ -978,7 +978,9 @@ var interpolateString = ({
978
978
  }) => {
979
979
  const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
980
980
  const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
981
- const parsedOutputRange = hasAxisRotation ? initiallyParsedOutputRange.map((parsed) => {
981
+ const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
982
+ const segmentIndex = inputRange.length === 1 ? 0 : findRange(posterizedInput, inputRange);
983
+ const parsedOutputRange = hasAxisRotation ? initiallyParsedOutputRange.map((parsed, index) => {
982
984
  if (parsed.kind !== "rotate") {
983
985
  return parsed;
984
986
  }
@@ -988,9 +990,11 @@ var interpolateString = ({
988
990
  if (parsed.dimensions !== 1) {
989
991
  throw new TypeError("Cannot interpolate a multi-angle rotate value with an axis rotation");
990
992
  }
993
+ const adjacentAxisRotation = parsed.values[0] === 0 ? index === segmentIndex ? initiallyParsedOutputRange[index + 1] : index === segmentIndex + 1 ? initiallyParsedOutputRange[index - 1] : undefined : undefined;
994
+ const axis = adjacentAxisRotation?.axisRotation ? adjacentAxisRotation.values : [0, 0, 1];
991
995
  return {
992
996
  kind: "rotate",
993
- values: [0, 0, 1, parsed.values[0]],
997
+ values: [axis[0], axis[1], axis[2], parsed.values[0]],
994
998
  units: [null, null, null, parsed.units[0]],
995
999
  dimensions: 4,
996
1000
  axisRotation: true
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "4.0.511";
2
+ var VERSION = "4.0.513";
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.511",
6
+ "version": "4.0.513",
7
7
  "description": "Make videos programmatically",
8
8
  "main": "dist/cjs/index.js",
9
9
  "types": "dist/cjs/index.d.ts",
@@ -35,7 +35,7 @@
35
35
  "react-dom": "19.2.3",
36
36
  "webpack": "5.105.0",
37
37
  "zod": "4.4.3",
38
- "@remotion/eslint-config-internal": "4.0.511",
38
+ "@remotion/eslint-config-internal": "4.0.513",
39
39
  "eslint": "9.19.0",
40
40
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
41
41
  },