@remotion/studio-server 4.0.489 → 4.0.490

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.
@@ -111,6 +111,9 @@ const makeKeyframedOptions = ({ param, remotionLocalNames, }) => {
111
111
  if (param.clamping.right !== 'extend') {
112
112
  properties.push(b.objectProperty(b.identifier('extrapolateRight'), b.stringLiteral(param.clamping.right)));
113
113
  }
114
+ if (param.output === 'perceptual-scale') {
115
+ properties.push(b.objectProperty(b.identifier('output'), b.stringLiteral(param.output)));
116
+ }
114
117
  }
115
118
  if (keyframedParamNeedsEasingImport(param)) {
116
119
  const easingLocalName = (_a = remotionLocalNames.Easing) !== null && _a !== void 0 ? _a : 'Easing';
@@ -1,5 +1,5 @@
1
1
  import { type KeyframeInterpolationFunction } from '@remotion/studio-shared';
2
- import type { CanUpdateSequencePropStatus, ExtrapolateType, SequenceNodePath, InteractivitySchema } from 'remotion';
2
+ import type { CanUpdateSequencePropStatus, ExtrapolateType, InteractivitySchema, InterpolateOutputOption, SequenceNodePath } from 'remotion';
3
3
  type KeyframeEasing = Extract<CanUpdateSequencePropStatus, {
4
4
  status: 'keyframed';
5
5
  }>['easing'][number];
@@ -17,6 +17,7 @@ export type KeyframeOperation = {
17
17
  right: ExtrapolateType;
18
18
  } | undefined;
19
19
  posterize: number | undefined;
20
+ output: InterpolateOutputOption | undefined;
20
21
  } | {
21
22
  type: 'easing';
22
23
  segmentIndex: number;
@@ -192,11 +192,15 @@ const getInterpolationCalleeForValues = ({ schema, key, staticValue, newValue, }
192
192
  const createFrameExpression = (frame) => {
193
193
  return (0, update_nested_prop_1.parseValueExpression)(frame);
194
194
  };
195
- const createClampOptionsExpression = () => {
196
- return b.objectExpression([
195
+ const createClampOptionsExpression = ({ defaultOutput, }) => {
196
+ const properties = [
197
197
  b.objectProperty(b.identifier('extrapolateLeft'), b.stringLiteral('clamp')),
198
198
  b.objectProperty(b.identifier('extrapolateRight'), b.stringLiteral('clamp')),
199
- ]);
199
+ ];
200
+ if (defaultOutput !== null && defaultOutput !== 'linear') {
201
+ properties.push(b.objectProperty(b.identifier('output'), b.stringLiteral(defaultOutput)));
202
+ }
203
+ return b.objectExpression(properties);
200
204
  };
201
205
  const createEmptyOptionsExpression = () => b.objectExpression([]);
202
206
  const findObjectOptionProperty = (options, propertyName) => {
@@ -451,8 +455,17 @@ const validatePosterize = (posterize) => {
451
455
  throw new Error('Cannot update keyframe settings: posterize must be > 0');
452
456
  }
453
457
  };
454
- const updateKeyframeSettings = ({ expression, clamping, posterize, }) => {
458
+ const validateOutput = (output) => {
459
+ if (output === undefined ||
460
+ output === 'linear' ||
461
+ output === 'perceptual-scale') {
462
+ return;
463
+ }
464
+ throw new Error('Cannot update keyframe settings: output must be "linear" or "perceptual-scale"');
465
+ };
466
+ const updateKeyframeSettings = ({ expression, clamping, posterize, output, }) => {
455
467
  validatePosterize(posterize);
468
+ validateOutput(output);
456
469
  const existing = getInterpolationExpression(expression);
457
470
  if (!existing) {
458
471
  throw new Error('Cannot update keyframe settings on non-keyframed value');
@@ -474,6 +487,7 @@ const updateKeyframeSettings = ({ expression, clamping, posterize, }) => {
474
487
  propertyName: 'extrapolateRight',
475
488
  value: null,
476
489
  });
490
+ setOptionsProperty({ options, propertyName: 'output', value: null });
477
491
  }
478
492
  else if (clamping) {
479
493
  setOptionsProperty({
@@ -487,6 +501,13 @@ const updateKeyframeSettings = ({ expression, clamping, posterize, }) => {
487
501
  value: b.stringLiteral(clamping.right),
488
502
  });
489
503
  }
504
+ if (!isColorInterpolation && output !== undefined) {
505
+ setOptionsProperty({
506
+ options,
507
+ propertyName: 'output',
508
+ value: output === 'linear' ? null : b.stringLiteral(output),
509
+ });
510
+ }
490
511
  setOptionsProperty({
491
512
  options,
492
513
  propertyName: 'posterize',
@@ -617,7 +638,11 @@ const addKeyframe = ({ expression, key, frame, value, schema, }) => {
617
638
  });
618
639
  const extraArgs = callee.type === 'Identifier' && callee.name === 'interpolateColors'
619
640
  ? []
620
- : [createClampOptionsExpression()];
641
+ : [
642
+ createClampOptionsExpression({
643
+ defaultOutput: getDefaultKeyframeOutput({ schema, key }),
644
+ }),
645
+ ];
621
646
  return {
622
647
  expression: createInterpolateExpression({
623
648
  callee,
@@ -744,6 +769,7 @@ const applyKeyframeOperation = ({ expression, key, operation, schema, }) => {
744
769
  expression,
745
770
  clamping: operation.clamping,
746
771
  posterize: operation.posterize,
772
+ output: operation.output,
747
773
  }),
748
774
  introduced: noIntroducedIdentifiers,
749
775
  };
@@ -832,6 +858,14 @@ const findFieldInSchema = (schema, key) => {
832
858
  }
833
859
  return undefined;
834
860
  };
861
+ const getDefaultKeyframeOutput = ({ schema, key, }) => {
862
+ const field = schema ? findFieldInSchema(schema, key) : undefined;
863
+ if (((field === null || field === void 0 ? void 0 : field.type) === 'number' || (field === null || field === void 0 ? void 0 : field.type) === 'scale') &&
864
+ field.defaultKeyframeOutput !== undefined) {
865
+ return field.defaultKeyframeOutput;
866
+ }
867
+ return key === 'style.scale' ? 'perceptual-scale' : null;
868
+ };
835
869
  const getInitialValueForMissingProp = ({ schema, key, newValue, }) => {
836
870
  const field = schema ? findFieldInSchema(schema, key) : undefined;
837
871
  if (field && field.type !== 'hidden' && field.default !== undefined) {
@@ -1,22 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getInstalledInstallablePackages = void 0;
4
- const studio_shared_1 = require("@remotion/studio-shared");
5
4
  const get_installed_dependencies_1 = require("./get-installed-dependencies");
6
5
  const getInstalledInstallablePackages = (remotionRoot) => {
7
- const { dependencies, devDependencies, optionalDependencies } = (0, get_installed_dependencies_1.getInstalledDependencies)(remotionRoot);
8
- const installablePackages = [
6
+ const { dependencies, devDependencies, optionalDependencies, peerDependencies, } = (0, get_installed_dependencies_1.getInstalledDependencies)(remotionRoot);
7
+ return Array.from(new Set([
9
8
  ...dependencies,
10
9
  ...devDependencies,
11
10
  ...optionalDependencies,
12
- ];
13
- const remotionPackages = Object.entries(studio_shared_1.installableMap)
14
- .filter(([, _installable]) => _installable)
15
- .map(([pkg]) => (pkg === 'core' ? 'remotion' : `@remotion/${pkg}`))
16
- .filter((pkg) => installablePackages.includes(pkg));
17
- const installedExtraPackages = studio_shared_1.extraPackages
18
- .map((pkg) => pkg.name)
19
- .filter((pkg) => installablePackages.includes(pkg));
20
- return [...remotionPackages, ...installedExtraPackages];
11
+ ...peerDependencies,
12
+ ]));
21
13
  };
22
14
  exports.getInstalledInstallablePackages = getInstalledInstallablePackages;
@@ -569,6 +569,7 @@ const createSolidElement = ({ localName, width, height, position, }) => {
569
569
  return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
570
570
  createNumberAttribute('width', width),
571
571
  createNumberAttribute('height', height),
572
+ createStringAttribute('color', 'gray'),
572
573
  createPositionAbsoluteStyleAttribute(position),
573
574
  ], true), null, []);
574
575
  };
@@ -201,6 +201,18 @@ const getExtrapolateType = (node) => {
201
201
  }
202
202
  return null;
203
203
  };
204
+ const getInterpolateOutputOption = (node) => {
205
+ if (node.type === 'StringLiteral') {
206
+ if (node.value === 'linear' || node.value === 'perceptual-scale') {
207
+ return node.value;
208
+ }
209
+ return null;
210
+ }
211
+ if (node.type === 'TSAsExpression') {
212
+ return getInterpolateOutputOption(node.expression);
213
+ }
214
+ return null;
215
+ };
204
216
  const getKeyframeEasing = (node) => (0, parse_keyframe_easing_expression_1.parseKeyframeEasingExpression)(node);
205
217
  const getKeyframeEasingArray = ({ easingNode, segments, }) => {
206
218
  if (segments === 0) {
@@ -248,6 +260,7 @@ const getInterpolationMetadata = (interpolationFunction, callExpression, keyfram
248
260
  easing: Array.from({ length: segments }, () => studio_shared_1.LINEAR_KEYFRAME_EASING),
249
261
  clamping: defaultClamping,
250
262
  posterize: undefined,
263
+ output: undefined,
251
264
  };
252
265
  const optionsArg = callExpression.arguments[3];
253
266
  if (!optionsArg) {
@@ -259,6 +272,7 @@ const getInterpolationMetadata = (interpolationFunction, callExpression, keyfram
259
272
  let { easing } = defaults;
260
273
  let { clamping } = defaults;
261
274
  let posterize;
275
+ let { output } = defaults;
262
276
  for (const property of optionsArg.properties) {
263
277
  if (property.type !== 'ObjectProperty' || property.computed) {
264
278
  return null;
@@ -307,12 +321,24 @@ const getInterpolationMetadata = (interpolationFunction, callExpression, keyfram
307
321
  posterize = parsedPosterize;
308
322
  continue;
309
323
  }
324
+ if (key === 'output') {
325
+ if (interpolationFunction === 'interpolateColors') {
326
+ return null;
327
+ }
328
+ const parsedOutput = getInterpolateOutputOption(value);
329
+ if (!parsedOutput) {
330
+ return null;
331
+ }
332
+ output = parsedOutput;
333
+ continue;
334
+ }
310
335
  return null;
311
336
  }
312
337
  return {
313
338
  easing,
314
339
  clamping,
315
340
  posterize,
341
+ output,
316
342
  };
317
343
  };
318
344
  const getInterpolationKeyframes = (node, ast) => {
@@ -394,6 +420,7 @@ const getInterpolationKeyframes = (node, ast) => {
394
420
  easing: metadata.easing,
395
421
  clamping: metadata.clamping,
396
422
  posterize: metadata.posterize,
423
+ output: metadata.output,
397
424
  };
398
425
  };
399
426
  const isUseCurrentFrameCall = (node) => {
@@ -440,6 +467,7 @@ const getComputedStatus = (node, ast) => {
440
467
  easing: interpolation.easing,
441
468
  clamping: interpolation.clamping,
442
469
  posterize: interpolation.posterize,
470
+ output: interpolation.output,
443
471
  };
444
472
  };
445
473
  exports.getComputedStatus = getComputedStatus;
@@ -1,3 +1,4 @@
1
1
  import { type InstallPackageRequest, type InstallPackageResponse } from '@remotion/studio-shared';
2
2
  import type { ApiHandler } from '../api-types';
3
+ export declare const getPackageInstallSpec: (packageName: string) => string;
3
4
  export declare const handleInstallPackage: ApiHandler<InstallPackageRequest, InstallPackageResponse>;
@@ -1,24 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleInstallPackage = void 0;
3
+ exports.handleInstallPackage = exports.getPackageInstallSpec = void 0;
4
4
  const node_child_process_1 = require("node:child_process");
5
5
  const renderer_1 = require("@remotion/renderer");
6
6
  const studio_shared_1 = require("@remotion/studio-shared");
7
7
  const version_1 = require("remotion/version");
8
8
  const install_command_1 = require("../../helpers/install-command");
9
9
  const get_package_manager_1 = require("../get-package-manager");
10
- const extraPackageNames = studio_shared_1.extraPackages.map((pkg) => pkg.name);
11
- const isExtraPackage = (packageName) => {
12
- return extraPackageNames.includes(packageName);
13
- };
14
10
  const getExtraPackageVersion = (packageName) => {
15
11
  const pkg = studio_shared_1.extraPackages.find((p) => p.name === packageName);
16
12
  return pkg ? pkg.version : null;
17
13
  };
14
+ const getPackageInstallSpec = (packageName) => {
15
+ const extraVersion = getExtraPackageVersion(packageName);
16
+ if (extraVersion) {
17
+ return `${packageName}@${extraVersion}`;
18
+ }
19
+ if (packageName === 'remotion' || packageName.startsWith('@remotion/')) {
20
+ return `${packageName}@${version_1.VERSION}`;
21
+ }
22
+ return packageName;
23
+ };
24
+ exports.getPackageInstallSpec = getPackageInstallSpec;
18
25
  const handleInstallPackage = async ({ logLevel, remotionRoot, input: { packageNames } }) => {
19
26
  for (const packageName of packageNames) {
20
- if (!packageName.startsWith('@remotion/') && !isExtraPackage(packageName)) {
21
- return Promise.reject(new Error(`Package ${packageName} is not allowed to be installed.`));
27
+ if (!(0, studio_shared_1.isValidPackageName)(packageName)) {
28
+ return Promise.reject(new Error(`Package name ${JSON.stringify(packageName)} is invalid.`));
22
29
  }
23
30
  }
24
31
  const manager = (0, get_package_manager_1.getPackageManager)({
@@ -32,14 +39,9 @@ const handleInstallPackage = async ({ logLevel, remotionRoot, input: { packageNa
32
39
  .map((p) => p.path)
33
40
  .join(', ')}). Install dependencies using your favorite manager!`);
34
41
  }
35
- // Build packages with appropriate versions
36
- const packagesWithVersions = packageNames.map((pkg) => {
37
- const extraVersion = getExtraPackageVersion(pkg);
38
- if (extraVersion) {
39
- return `${pkg}@${extraVersion}`;
40
- }
41
- return `${pkg}@${version_1.VERSION}`;
42
- });
42
+ // Remotion packages must match the Studio version and catalogued extra
43
+ // packages use their supported version. Other packages resolve normally.
44
+ const packagesWithVersions = packageNames.map(exports.getPackageInstallSpec);
43
45
  const command = (0, install_command_1.getInstallCommand)({
44
46
  manager: manager.manager,
45
47
  packages: packagesWithVersions,
@@ -35,6 +35,7 @@ const updateEffectKeyframeSettingsHandler = ({ input: { fileName, sequenceNodePa
35
35
  type: 'settings',
36
36
  clamping: settings.clamping,
37
37
  posterize: settings.posterize,
38
+ output: settings.output,
38
39
  }
39
40
  : {
40
41
  type: 'easing',
@@ -32,6 +32,7 @@ const updateSequenceKeyframeSettingsHandler = ({ input: { fileName, nodePath, ke
32
32
  type: 'settings',
33
33
  clamping: settings.clamping,
34
34
  posterize: settings.posterize,
35
+ output: settings.output,
35
36
  }
36
37
  : {
37
38
  type: 'easing',
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-server"
4
4
  },
5
5
  "name": "@remotion/studio-server",
6
- "version": "4.0.489",
6
+ "version": "4.0.490",
7
7
  "description": "Run a Remotion Studio with a server backend",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -27,11 +27,11 @@
27
27
  "@babel/parser": "7.24.1",
28
28
  "semver": "7.5.3",
29
29
  "prettier": "3.8.1",
30
- "remotion": "4.0.489",
30
+ "remotion": "4.0.490",
31
31
  "recast": "0.23.11",
32
- "@remotion/bundler": "4.0.489",
33
- "@remotion/renderer": "4.0.489",
34
- "@remotion/studio-shared": "4.0.489",
32
+ "@remotion/bundler": "4.0.490",
33
+ "@remotion/renderer": "4.0.490",
34
+ "@remotion/studio-shared": "4.0.490",
35
35
  "memfs": "3.4.3",
36
36
  "open": "8.4.2"
37
37
  },
@@ -39,7 +39,7 @@
39
39
  "ast-types": "0.16.1",
40
40
  "react": "19.2.3",
41
41
  "@types/semver": "7.5.3",
42
- "@remotion/eslint-config-internal": "4.0.489",
42
+ "@remotion/eslint-config-internal": "4.0.490",
43
43
  "eslint": "9.19.0",
44
44
  "@types/node": "20.12.14",
45
45
  "@typescript/native-preview": "7.0.0-dev.20260217.1"