UNPKG

remotion

Version:

Make videos programmatically

2,356 lines • 68.6 kB
// src/bezier.ts
var NEWTON_ITERATIONS = 4;
var NEWTON_MIN_SLOPE = 0.001;
var SUBDIVISION_PRECISION = 0.0000001;
var SUBDIVISION_MAX_ITERATIONS = 10;
var kSplineTableSize = 11;
var kSampleStepSize = 1 / (kSplineTableSize - 1);
var float32ArraySupported = typeof Float32Array === "function";
function a(aA1, aA2) {
  return 1 - 3 * aA2 + 3 * aA1;
}
function b(aA1, aA2) {
  return 3 * aA2 - 6 * aA1;
}
function c(aA1) {
  return 3 * aA1;
}
function calcBezier(aT, aA1, aA2) {
  return ((a(aA1, aA2) * aT + b(aA1, aA2)) * aT + c(aA1)) * aT;
}
function getSlope(aT, aA1, aA2) {
  return 3 * a(aA1, aA2) * aT * aT + 2 * b(aA1, aA2) * aT + c(aA1);
}
function binarySubdivide({
  aX,
  _aA,
  _aB,
  mX1,
  mX2
}) {
  let currentX;
  let currentT;
  let i = 0;
  let aA = _aA;
  let aB = _aB;
  do {
    currentT = aA + (aB - aA) / 2;
    currentX = calcBezier(currentT, mX1, mX2) - aX;
    if (currentX > 0) {
      aB = currentT;
    } else {
      aA = currentT;
    }
  } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
  return currentT;
}
function newtonRaphsonIterate(aX, _aGuessT, mX1, mX2) {
  let aGuessT = _aGuessT;
  for (let i = 0;i < NEWTON_ITERATIONS; ++i) {
    const currentSlope = getSlope(aGuessT, mX1, mX2);
    if (currentSlope === 0) {
      return aGuessT;
    }
    const currentX = calcBezier(aGuessT, mX1, mX2) - aX;
    aGuessT -= currentX / currentSlope;
  }
  return aGuessT;
}
function bezier(mX1, mY1, mX2, mY2) {
  if (!(mX1 >= 0 && mX1 <= 1 && mX2 >= 0 && mX2 <= 1)) {
    throw new Error("bezier x values must be in [0, 1] range");
  }
  const sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
  if (mX1 !== mY1 || mX2 !== mY2) {
    for (let i = 0;i < kSplineTableSize; ++i) {
      sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
    }
  }
  function getTForX(aX) {
    let intervalStart = 0;
    let currentSample = 1;
    const lastSample = kSplineTableSize - 1;
    for (;currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
      intervalStart += kSampleStepSize;
    }
    --currentSample;
    const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
    const guessForT = intervalStart + dist * kSampleStepSize;
    const initialSlope = getSlope(guessForT, mX1, mX2);
    if (initialSlope >= NEWTON_MIN_SLOPE) {
      return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
    }
    if (initialSlope === 0) {
      return guessForT;
    }
    return binarySubdivide({
      aX,
      _aA: intervalStart,
      _aB: intervalStart + kSampleStepSize,
      mX1,
      mX2
    });
  }
  return function(x) {
    const clampedX = Math.min(1, Math.max(0, x));
    if (mX1 === mY1 && mX2 === mY2) {
      return clampedX;
    }
    if (clampedX === 0) {
      return 0;
    }
    if (clampedX === 1) {
      return 1;
    }
    return calcBezier(getTForX(clampedX), mY1, mY2);
  };
}

// src/validate-frame.ts
var validateFrame = ({
  allowFloats,
  durationInFrames,
  frame
}) => {
  if (typeof frame === "undefined") {
    throw new TypeError(`Argument missing for parameter "frame"`);
  }
  if (typeof frame !== "number") {
    throw new TypeError(`Argument passed for "frame" is not a number: ${frame}`);
  }
  if (!Number.isFinite(frame)) {
    throw new RangeError(`Frame ${frame} is not finite`);
  }
  if (frame % 1 !== 0 && !allowFloats) {
    throw new RangeError(`Argument for frame must be an integer, but got ${frame}`);
  }
  if (frame < 0 && frame < -durationInFrames) {
    throw new RangeError(`Cannot use frame ${frame}: Duration of composition is ${durationInFrames}, therefore the lowest frame that can be rendered is ${-durationInFrames}`);
  }
  if (frame > durationInFrames - 1) {
    throw new RangeError(`Cannot use frame ${frame}: Duration of composition is ${durationInFrames}, therefore the highest frame that can be rendered is ${durationInFrames - 1}`);
  }
};

// src/validation/validate-fps.ts
function validateFps(fps, location, isGif) {
  if (typeof fps !== "number") {
    throw new Error(`"fps" must be a number, but you passed a value of type ${typeof fps} ${location}`);
  }
  if (!Number.isFinite(fps)) {
    throw new Error(`"fps" must be a finite, but you passed ${fps} ${location}`);
  }
  if (isNaN(fps)) {
    throw new Error(`"fps" must not be NaN, but got ${fps} ${location}`);
  }
  if (fps <= 0) {
    throw new TypeError(`"fps" must be positive, but got ${fps} ${location}`);
  }
  if (isGif && fps > 50) {
    throw new TypeError(`The FPS for a GIF cannot be higher than 50. Use the --every-nth-frame option to lower the FPS: https://remotion.dev/docs/render-as-gif`);
  }
}

// src/validation/validation-spring-duration.ts
var validateSpringDuration = (dur) => {
  if (typeof dur === "undefined") {
    return;
  }
  if (typeof dur !== "number") {
    throw new TypeError(`A "duration" of a spring must be a "number" but is "${typeof dur}"`);
  }
  if (Number.isNaN(dur)) {
    throw new TypeError('A "duration" of a spring is NaN, which it must not be');
  }
  if (!Number.isFinite(dur)) {
    throw new TypeError('A "duration" of a spring must be finite, but is ' + dur);
  }
  if (dur <= 0) {
    throw new TypeError('A "duration" of a spring must be positive, but is ' + dur);
  }
};

// src/spring/spring-utils.ts
var defaultSpringConfig = {
  damping: 10,
  mass: 1,
  stiffness: 100,
  overshootClamping: false
};
var advanceCache = {};
function advance({
  animation,
  now,
  config
}) {
  const { toValue, lastTimestamp, current, velocity } = animation;
  const deltaTime = Math.min(now - lastTimestamp, 64);
  if (config.damping <= 0) {
    throw new Error("Spring damping must be greater than 0, otherwise the spring() animation will never end, causing an infinite loop.");
  }
  const c2 = config.damping;
  const m = config.mass;
  const k = config.stiffness;
  const cacheKey = [
    toValue,
    lastTimestamp,
    current,
    velocity,
    c2,
    m,
    k,
    now
  ].join("-");
  if (advanceCache[cacheKey]) {
    return advanceCache[cacheKey];
  }
  const v0 = -velocity;
  const x0 = toValue - current;
  const zeta = c2 / (2 * Math.sqrt(k * m));
  const omega0 = Math.sqrt(k / m);
  const omega1 = omega0 * Math.sqrt(1 - zeta ** 2);
  const t = deltaTime / 1000;
  const sin1 = Math.sin(omega1 * t);
  const cos1 = Math.cos(omega1 * t);
  const underDampedEnvelope = Math.exp(-zeta * omega0 * t);
  const underDampedFrag1 = underDampedEnvelope * (sin1 * ((v0 + zeta * omega0 * x0) / omega1) + x0 * cos1);
  const underDampedPosition = toValue - underDampedFrag1;
  const underDampedVelocity = zeta * omega0 * underDampedFrag1 - underDampedEnvelope * (cos1 * (v0 + zeta * omega0 * x0) - omega1 * x0 * sin1);
  const criticallyDampedEnvelope = Math.exp(-omega0 * t);
  const criticallyDampedPosition = toValue - criticallyDampedEnvelope * (x0 + (v0 + omega0 * x0) * t);
  const criticallyDampedVelocity = criticallyDampedEnvelope * (v0 * (t * omega0 - 1) + t * x0 * omega0 * omega0);
  const animationNode = {
    toValue,
    prevPosition: current,
    lastTimestamp: now,
    current: zeta < 1 ? underDampedPosition : criticallyDampedPosition,
    velocity: zeta < 1 ? underDampedVelocity : criticallyDampedVelocity
  };
  advanceCache[cacheKey] = animationNode;
  return animationNode;
}
var calculationCache = {};
function springCalculation({
  frame,
  fps,
  config = {}
}) {
  const from = 0;
  const to = 1;
  const cacheKey = [
    frame,
    fps,
    config.damping,
    config.mass,
    config.overshootClamping,
    config.stiffness
  ].join("-");
  if (calculationCache[cacheKey]) {
    return calculationCache[cacheKey];
  }
  let animation = {
    lastTimestamp: 0,
    current: from,
    toValue: to,
    velocity: 0,
    prevPosition: 0
  };
  const frameClamped = Math.max(0, frame);
  const unevenRest = frameClamped % 1;
  for (let f = 0;f <= Math.floor(frameClamped); f++) {
    const time = f / fps * 1000;
    animation = advance({
      animation,
      now: time,
      config: {
        ...defaultSpringConfig,
        ...config
      }
    });
  }
  if (unevenRest > 0) {
    animation = advance({
      animation,
      now: frameClamped / fps * 1000,
      config: {
        ...defaultSpringConfig,
        ...config
      }
    });
  }
  calculationCache[cacheKey] = animation;
  return animation;
}

// src/spring/measure-spring.ts
var cache = new Map;
function measureSpring({
  fps,
  config = {},
  threshold = 0.005
}) {
  if (typeof threshold !== "number") {
    throw new TypeError(`threshold must be a number, got ${threshold} of type ${typeof threshold}`);
  }
  if (threshold === 0) {
    return Infinity;
  }
  if (threshold === 1) {
    return 0;
  }
  if (isNaN(threshold)) {
    throw new TypeError("Threshold is NaN");
  }
  if (!Number.isFinite(threshold)) {
    throw new TypeError("Threshold is not finite");
  }
  if (threshold < 0) {
    throw new TypeError("Threshold is below 0");
  }
  const cacheKey = [
    fps,
    config.damping,
    config.mass,
    config.overshootClamping,
    config.stiffness,
    threshold
  ].join("-");
  if (cache.has(cacheKey)) {
    return cache.get(cacheKey);
  }
  validateFps(fps, "to the measureSpring() function", false);
  let frame = 0;
  let finishedFrame = 0;
  const calc = () => {
    return springCalculation({
      fps,
      frame,
      config
    });
  };
  let animation = calc();
  const calcDifference = () => {
    return Math.abs(animation.current - animation.toValue);
  };
  let difference = calcDifference();
  while (difference >= threshold) {
    frame++;
    animation = calc();
    difference = calcDifference();
  }
  finishedFrame = frame;
  for (let i = 0;i < 20; i++) {
    frame++;
    animation = calc();
    difference = calcDifference();
    if (difference >= threshold) {
      i = 0;
      finishedFrame = frame + 1;
    }
  }
  cache.set(cacheKey, finishedFrame);
  return finishedFrame;
}

// src/spring/index.ts
function spring({
  frame: passedFrame,
  fps,
  config = {},
  from = 0,
  to = 1,
  durationInFrames: passedDurationInFrames,
  durationRestThreshold,
  delay = 0,
  reverse = false
}) {
  validateSpringDuration(passedDurationInFrames);
  validateFrame({
    frame: passedFrame,
    durationInFrames: Infinity,
    allowFloats: true
  });
  validateFps(fps, "to spring()", false);
  const needsToCalculateNaturalDuration = reverse || typeof passedDurationInFrames !== "undefined";
  const naturalDuration = needsToCalculateNaturalDuration ? measureSpring({
    fps,
    config,
    threshold: durationRestThreshold
  }) : undefined;
  const naturalDurationGetter = needsToCalculateNaturalDuration ? {
    get: () => naturalDuration
  } : {
    get: () => {
      throw new Error("did not calculate natural duration, this is an error with Remotion. Please report");
    }
  };
  const reverseProcessed = reverse ? (passedDurationInFrames ?? naturalDurationGetter.get()) - passedFrame : passedFrame;
  const delayProcessed = reverseProcessed + (reverse ? delay : -delay);
  const durationProcessed = passedDurationInFrames === undefined ? delayProcessed : delayProcessed / (passedDurationInFrames / naturalDurationGetter.get());
  if (passedDurationInFrames && delayProcessed > passedDurationInFrames) {
    return to;
  }
  const spr = springCalculation({
    fps,
    frame: durationProcessed,
    config
  });
  const inner = config.overshootClamping ? to >= from ? Math.min(spr.current, to) : Math.max(spr.current, to) : spr.current;
  const interpolated = from === 0 && to === 1 ? inner : interpolate(inner, [0, 1], [from, to]);
  return interpolated;
}

// src/easing.ts
var clampUnit = (t) => Math.min(1, Math.max(0, t));
var springEasingDurationInFrames = 30;

class Easing {
  static step0(n) {
    return n > 0 ? 1 : 0;
  }
  static step1(n) {
    return n >= 1 ? 1 : 0;
  }
  static linear(t) {
    return t;
  }
  static ease(t) {
    return Easing.bezier(0.42, 0, 1, 1)(t);
  }
  static quad(t) {
    return t * t;
  }
  static cubic(t) {
    return t * t * t;
  }
  static poly(n) {
    return (t) => t ** n;
  }
  static sin(t) {
    return 1 - Math.cos(t * Math.PI / 2);
  }
  static circle(t) {
    const u = clampUnit(t);
    return 1 - Math.sqrt(1 - u * u);
  }
  static exp(t) {
    return 2 ** (10 * (t - 1));
  }
  static elastic(bounciness = 1) {
    const p = bounciness * Math.PI;
    return (t) => 1 - Math.cos(t * Math.PI / 2) ** 3 * Math.cos(t * p);
  }
  static back(s = 1.70158) {
    return (t) => t * t * ((s + 1) * t - s);
  }
  static spring({
    allowTail = false,
    durationRestThreshold,
    ...config
  } = {}) {
    const easing = (t) => {
      if (t <= 0) {
        return 0;
      }
      if (!allowTail && t >= 1) {
        return 1;
      }
      if (allowTail) {
        return spring({
          fps: springEasingDurationInFrames,
          frame: t * measureSpring({
            fps: springEasingDurationInFrames,
            config,
            threshold: durationRestThreshold
          }),
          config
        });
      }
      return spring({
        fps: springEasingDurationInFrames,
        frame: t * springEasingDurationInFrames,
        config,
        durationInFrames: springEasingDurationInFrames,
        durationRestThreshold
      });
    };
    return Object.assign(easing, {
      remotionShouldExtendRight: allowTail
    });
  }
  static bounce(t) {
    const u = clampUnit(t);
    if (u < 1 / 2.75) {
      return 7.5625 * u * u;
    }
    if (u < 2 / 2.75) {
      const t2_ = u - 1.5 / 2.75;
      return 7.5625 * t2_ * t2_ + 0.75;
    }
    if (u < 2.5 / 2.75) {
      const t2_ = u - 2.25 / 2.75;
      return 7.5625 * t2_ * t2_ + 0.9375;
    }
    const t2 = u - 2.625 / 2.75;
    return 7.5625 * t2 * t2 + 0.984375;
  }
  static bezier(x1, y1, x2, y2) {
    return bezier(x1, y1, x2, y2);
  }
  static in(easing) {
    return easing;
  }
  static out(easing) {
    return (t) => 1 - easing(1 - t);
  }
  static inOut(easing) {
    return (t) => {
      if (t < 0.5) {
        return easing(t * 2) / 2;
      }
      return 1 - easing((1 - t) * 2) / 2;
    };
  }
}

// src/normalize-number.ts
var normalizeNumber = (value) => {
  return Math.round(value * 1e6) / 1e6;
};

// src/interpolate.ts
var angleUnits = new Set(["deg", "rad", "grad", "turn"]);
var lengthUnits = new Set([
  "%",
  "cap",
  "ch",
  "cm",
  "cqb",
  "cqh",
  "cqi",
  "cqmax",
  "cqmin",
  "cqw",
  "dvh",
  "dvw",
  "em",
  "ex",
  "ic",
  "in",
  "lh",
  "lvh",
  "lvw",
  "mm",
  "pc",
  "pt",
  "px",
  "q",
  "rem",
  "rlh",
  "svh",
  "svw",
  "vb",
  "vh",
  "vi",
  "vmax",
  "vmin",
  "vw"
]);
var cssNumberRegex = /^([+-]?(?:\d+\.?\d*|\.\d+))([a-zA-Z%]+)?$/;
var transformOriginKeywords = new Set([
  "left",
  "center",
  "right",
  "top",
  "bottom"
]);
var transformOriginKeywordOptions = (keyword) => {
  if (keyword === "left") {
    return [{ axis: "x", value: { value: 0, unit: "%" } }];
  }
  if (keyword === "right") {
    return [{ axis: "x", value: { value: 100, unit: "%" } }];
  }
  if (keyword === "top") {
    return [{ axis: "y", value: { value: 0, unit: "%" } }];
  }
  if (keyword === "bottom") {
    return [{ axis: "y", value: { value: 100, unit: "%" } }];
  }
  return [
    { axis: "x", value: { value: 50, unit: "%" } },
    { axis: "y", value: { value: 50, unit: "%" } }
  ];
};
var transformOriginCenter = { value: 50, unit: "%" };
var stringifyNumber = (value) => {
  return String(normalizeNumber(value));
};

class UnsupportedStringInterpolationValueError extends TypeError {
}
var parseStringInterpolationComponent = (component, value) => {
  const match = cssNumberRegex.exec(component);
  if (match === null) {
    throw new UnsupportedStringInterpolationValueError(`Cannot interpolate "${value}" because "${component}" is not a supported scale, translate, or rotate value`);
  }
  const unit = match[2] ?? null;
  const numberValue = Number(match[1]);
  if (!Number.isFinite(numberValue)) {
    throw new TypeError(`Cannot interpolate "${value}" because "${component}" is not finite`);
  }
  if (unit === null) {
    return { kind: "scale", value: numberValue, unit: null };
  }
  if (angleUnits.has(unit)) {
    return { kind: "rotate", value: numberValue, unit };
  }
  if (lengthUnits.has(unit)) {
    return { kind: "translate", value: numberValue, unit };
  }
  throw new TypeError(`Cannot interpolate "${value}" because "${unit}" is not a supported translate or rotate unit`);
};
var parseTransformOriginLengthPercentage = ({
  component,
  value,
  allowPercentage
}) => {
  const match = cssNumberRegex.exec(component);
  if (match === null) {
    throw new TypeError(`Cannot interpolate "${value}" because "${component}" is not a supported transform-origin ${allowPercentage ? "length-percentage" : "z length"}`);
  }
  const unit = match[2] ?? null;
  const numberValue = Number(match[1]);
  if (!Number.isFinite(numberValue)) {
    throw new TypeError(`Cannot interpolate "${value}" because "${component}" is not finite`);
  }
  if (unit === null || !lengthUnits.has(unit) || !allowPercentage && unit === "%") {
    throw new TypeError(`Cannot interpolate "${value}" because "${component}" is not a supported transform-origin ${allowPercentage ? "length-percentage" : "z length"}`);
  }
  return { value: numberValue, unit };
};
var parseTransformOriginToken = (component, value) => {
  const lower = component.toLowerCase();
  if (transformOriginKeywords.has(lower)) {
    return { type: "keyword", keyword: lower };
  }
  return {
    type: "length-percentage",
    parsed: parseTransformOriginLengthPercentage({
      component,
      value,
      allowPercentage: true
    })
  };
};
var parseTwoTransformOriginKeywords = (first, second, value) => {
  const candidates = [];
  for (const firstOption of transformOriginKeywordOptions(first)) {
    for (const secondOption of transformOriginKeywordOptions(second)) {
      if (firstOption.axis === secondOption.axis) {
        continue;
      }
      candidates.push(firstOption.axis === "x" ? [firstOption.value, secondOption.value] : [secondOption.value, firstOption.value]);
    }
  }
  if (candidates.length === 0) {
    throw new TypeError(`Cannot interpolate "${value}" because "${first} ${second}" is not a valid transform-origin keyword pair`);
  }
  return candidates[0];
};
var parseTransformOriginXY = (parts, value) => {
  if (parts.length === 1) {
    const token = parseTransformOriginToken(parts[0], value);
    if (token.type === "length-percentage") {
      return [token.parsed, transformOriginCenter];
    }
    if (token.keyword === "top" || token.keyword === "bottom") {
      return [
        transformOriginCenter,
        transformOriginKeywordOptions(token.keyword)[0].value
      ];
    }
    return [
      transformOriginKeywordOptions(token.keyword)[0].value,
      transformOriginCenter
    ];
  }
  const first = parseTransformOriginToken(parts[0], value);
  const second = parseTransformOriginToken(parts[1], value);
  if (first.type === "length-percentage" && second.type === "length-percentage") {
    return [first.parsed, second.parsed];
  }
  if (first.type === "keyword" && second.type === "keyword") {
    return parseTwoTransformOriginKeywords(first.keyword, second.keyword, value);
  }
  const keyword = first.type === "keyword" ? first : second.type === "keyword" ? second : null;
  const length = first.type === "length-percentage" ? first.parsed : second.type === "length-percentage" ? second.parsed : null;
  if (keyword === null || length === null) {
    throw new Error("Expected a keyword and a length-percentage value");
  }
  const keywordIsFirst = first.type === "keyword";
  if (keyword.keyword === "left" || keyword.keyword === "right") {
    if (!keywordIsFirst) {
      throw new TypeError(`Cannot interpolate "${value}" because horizontal transform-origin keywords must come before a length-percentage value`);
    }
    return [transformOriginKeywordOptions(keyword.keyword)[0].value, length];
  }
  if (keyword.keyword === "top" || keyword.keyword === "bottom") {
    return [length, transformOriginKeywordOptions(keyword.keyword)[0].value];
  }
  return keywordIsFirst ? [transformOriginCenter, length] : [length, transformOriginCenter];
};
var parseTransformOriginValue = (output, parts) => {
  const [x, y] = parseTransformOriginXY(parts.slice(0, 2), output);
  const z = parts[2] === undefined ? { value: 0, unit: null } : parseTransformOriginLengthPercentage({
    component: parts[2],
    value: output,
    allowPercentage: false
  });
  return {
    kind: "translate",
    values: [x.value, y.value, z.value, 0],
    units: [x.unit, y.unit, z.unit, null],
    dimensions: parts[2] === undefined ? 2 : 3,
    axisRotation: false
  };
};
var parseAxisRotationValue = (output) => {
  const parts = output.trim().split(/\s+/);
  const keywordAxis = parts.length === 2 ? parts[0].toLowerCase() : null;
  if (keywordAxis === "x" || keywordAxis === "y" || keywordAxis === "z") {
    const keywordAngle = parseStringInterpolationComponent(parts[1], output);
    if (keywordAngle.kind !== "rotate") {
      return null;
    }
    return {
      kind: "rotate",
      values: keywordAxis === "x" ? [1, 0, 0, keywordAngle.value] : keywordAxis === "y" ? [0, 1, 0, keywordAngle.value] : [0, 0, 1, keywordAngle.value],
      units: [null, null, null, keywordAngle.unit],
      dimensions: 4,
      axisRotation: true
    };
  }
  if (parts.length !== 4) {
    return null;
  }
  const axis = parts.slice(0, 3).map(Number);
  if (!axis.every(Number.isFinite)) {
    return null;
  }
  const vectorAngle = parseStringInterpolationComponent(parts[3], output);
  if (vectorAngle.kind !== "rotate") {
    return null;
  }
  return {
    kind: "rotate",
    values: [axis[0], axis[1], axis[2], vectorAngle.value],
    units: [null, null, null, vectorAngle.unit],
    dimensions: 4,
    axisRotation: true
  };
};
var parseStringInterpolationValue = (output) => {
  if (typeof output === "number") {
    if (!Number.isFinite(output)) {
      throw new Error(`outputRange must contain only finite numbers, but got [${output}]`);
    }
    return {
      kind: "scale",
      values: [output, output, 1, 0],
      units: [null, null, null, null],
      dimensions: 1,
      axisRotation: false
    };
  }
  const axisRotation = parseAxisRotationValue(output);
  if (axisRotation !== null) {
    return axisRotation;
  }
  const parts = output.trim().split(/\s+/);
  if (parts.length < 1 || parts.length > 3 || parts[0] === "") {
    throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
  }
  if (parts.some((part) => transformOriginKeywords.has(part.toLowerCase()))) {
    return parseTransformOriginValue(output, parts);
  }
  const parsed = parts.map((part) => parseStringInterpolationComponent(part, output));
  const [{ kind }] = parsed;
  for (const part of parsed) {
    if (part.kind !== kind) {
      throw new TypeError(`Cannot interpolate "${output}" because it mixes ${kind} and ${part.kind} values`);
    }
  }
  if (kind === "scale") {
    const x = parsed[0].value;
    const y = parsed[1]?.value ?? x;
    const z = parsed[2]?.value ?? 1;
    return {
      kind,
      values: [x, y, z, 0],
      units: [null, null, null, null],
      dimensions: parsed.length,
      axisRotation: false
    };
  }
  return {
    kind,
    values: [parsed[0].value, parsed[1]?.value ?? 0, parsed[2]?.value ?? 0, 0],
    units: [
      parsed[0].unit,
      parsed[1]?.unit ?? null,
      parsed[2]?.unit ?? null,
      null
    ],
    dimensions: parsed.length,
    axisRotation: false
  };
};
var serializeStringInterpolationValue = ({
  kind,
  values,
  units,
  dimensions,
  axisRotation
}) => {
  if (axisRotation) {
    return `${stringifyNumber(values[0])} ${stringifyNumber(values[1])} ${stringifyNumber(values[2])} ${stringifyNumber(values[3])}${units[3]}`;
  }
  if (kind === "scale") {
    return values.slice(0, dimensions).map((value) => stringifyNumber(value)).join(" ");
  }
  return values.slice(0, dimensions).map((value, index) => `${stringifyNumber(value)}${units[index]}`).join(" ");
};
var toSignedArea = (scale) => {
  if (scale === 0) {
    return 0;
  }
  return Math.sign(scale) * scale * scale;
};
var fromSignedArea = (area) => {
  if (area === 0) {
    return 0;
  }
  return Math.sign(area) * Math.sqrt(Math.abs(area));
};
function interpolateFunction(input, inputRange, outputRange, options) {
  const { extrapolateLeft, extrapolateRight, easing, output } = options;
  let result = input;
  const [inputMin, inputMax] = inputRange;
  const [outputMin, outputMax] = outputRange;
  if (result < inputMin) {
    if (extrapolateLeft === "identity") {
      return result;
    }
    if (extrapolateLeft === "clamp") {
      result = inputMin;
    } else if (extrapolateLeft === "wrap") {
      const range = inputMax - inputMin;
      result = ((result - inputMin) % range + range) % range + inputMin;
    } else if (extrapolateLeft === "extend") {}
  }
  if (result > inputMax) {
    if (extrapolateRight === "identity") {
      return result;
    }
    if (extrapolateRight === "clamp") {
      result = inputMax;
    } else if (extrapolateRight === "wrap") {
      const range = inputMax - inputMin;
      result = ((result - inputMin) % range + range) % range + inputMin;
    } else if (extrapolateRight === "extend") {}
  }
  if (outputMin === outputMax) {
    return outputMin;
  }
  result = (result - inputMin) / (inputMax - inputMin);
  result = easing(result);
  if (output === "perceptual-scale") {
    const signedAreaMin = toSignedArea(outputMin);
    const signedAreaMax = toSignedArea(outputMax);
    result = fromSignedArea(result * (signedAreaMax - signedAreaMin) + signedAreaMin);
  } else {
    result = result * (outputMax - outputMin) + outputMin;
  }
  return result;
}
function findRange(input, inputRange) {
  let i;
  for (i = 1;i < inputRange.length - 1; ++i) {
    if (inputRange[i] >= input) {
      break;
    }
  }
  return i - 1;
}
var defaultEasing = (num) => num;
var resolveOutputOption = (output) => {
  return output ?? "linear";
};
var shouldExtendRightForEasing = (easing) => {
  return easing.remotionShouldExtendRight === true;
};
var resolveEasingForSegment = ({
  easing,
  segmentIndex
}) => {
  if (easing === undefined) {
    return defaultEasing;
  }
  if (typeof easing === "function") {
    return easing;
  }
  return easing[segmentIndex];
};
var interpolateSegment = ({
  input,
  inputRange,
  outputRange,
  easing,
  extrapolateLeft,
  extrapolateRight,
  output
}) => {
  return interpolateFunction(input, inputRange, outputRange, {
    easing,
    extrapolateLeft,
    extrapolateRight: input > inputRange[1] && extrapolateRight === "clamp" && shouldExtendRightForEasing(easing) ? "extend" : extrapolateRight,
    output
  });
};
var interpolateNumber = ({
  input,
  inputRange,
  outputRange,
  options
}) => {
  const output = resolveOutputOption(options?.output);
  if (inputRange.length === 1) {
    return outputRange[0];
  }
  const easingOption = options?.easing;
  let extrapolateLeft = "extend";
  if (options?.extrapolateLeft !== undefined) {
    extrapolateLeft = options.extrapolateLeft;
  }
  let extrapolateRight = "extend";
  if (options?.extrapolateRight !== undefined) {
    extrapolateRight = options.extrapolateRight;
  }
  const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
  const range = findRange(posterizedInput, inputRange);
  const easing = resolveEasingForSegment({
    easing: easingOption,
    segmentIndex: range
  });
  let result = interpolateSegment({
    input: posterizedInput,
    inputRange: [inputRange[range], inputRange[range + 1]],
    outputRange: [outputRange[range], outputRange[range + 1]],
    easing,
    extrapolateLeft,
    extrapolateRight,
    output
  });
  for (let segmentIndex = 0;segmentIndex < range; segmentIndex++) {
    const previousEasing = resolveEasingForSegment({
      easing: easingOption,
      segmentIndex
    });
    if (!shouldExtendRightForEasing(previousEasing)) {
      continue;
    }
    const previousSegmentEnd = inputRange[segmentIndex + 1];
    if (posterizedInput <= previousSegmentEnd) {
      continue;
    }
    const continuedSegmentValue = interpolateSegment({
      input: posterizedInput,
      inputRange: [inputRange[segmentIndex], previousSegmentEnd],
      outputRange: [outputRange[segmentIndex], outputRange[segmentIndex + 1]],
      easing: previousEasing,
      extrapolateLeft,
      extrapolateRight: "extend",
      output
    });
    result += continuedSegmentValue - outputRange[segmentIndex + 1];
  }
  return result;
};
var interpolateString = ({
  input,
  inputRange,
  outputRange,
  options
}) => {
  const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
  const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
  const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
  const segmentIndex = inputRange.length === 1 ? 0 : findRange(posterizedInput, inputRange);
  const parsedOutputRange = hasAxisRotation ? initiallyParsedOutputRange.map((parsed, index) => {
    if (parsed.kind !== "rotate") {
      return parsed;
    }
    if (parsed.axisRotation) {
      return parsed;
    }
    if (parsed.dimensions !== 1) {
      throw new TypeError("Cannot interpolate a multi-angle rotate value with an axis rotation");
    }
    const adjacentAxisRotation = parsed.values[0] === 0 ? index === 0 ? initiallyParsedOutputRange.find((candidate) => candidate.axisRotation) : index === initiallyParsedOutputRange.length - 1 ? [...initiallyParsedOutputRange].reverse().find((candidate) => candidate.axisRotation) : index === segmentIndex ? initiallyParsedOutputRange[index + 1] : index === segmentIndex + 1 ? initiallyParsedOutputRange[index - 1] : undefined : undefined;
    const axis = adjacentAxisRotation?.axisRotation ? adjacentAxisRotation.values : [0, 0, 1];
    return {
      kind: "rotate",
      values: [axis[0], axis[1], axis[2], parsed.values[0]],
      units: [null, null, null, parsed.units[0]],
      dimensions: 4,
      axisRotation: true
    };
  }) : initiallyParsedOutputRange;
  const kind = parsedOutputRange[0]?.kind;
  if (kind === undefined) {
    throw new Error("outputRange must have at least 1 element");
  }
  for (const parsed of parsedOutputRange) {
    if (parsed.kind !== kind) {
      throw new TypeError(`Cannot interpolate ${kind} values with ${parsed.kind} values`);
    }
  }
  const dimensions = Math.max(...parsedOutputRange.map((parsed) => parsed.dimensions));
  const units = [
    null,
    null,
    null,
    null
  ];
  if (kind !== "scale") {
    for (let axis = 0;axis < dimensions; axis++) {
      if (hasAxisRotation && axis < 3) {
        continue;
      }
      for (const parsed of parsedOutputRange) {
        const unit = parsed.units[axis];
        if (unit === null) {
          continue;
        }
        if (units[axis] === null) {
          units[axis] = unit;
          continue;
        }
        if (units[axis] !== unit) {
          throw new TypeError(`Cannot interpolate ${kind} values with different units on axis ${axis + 1}: ${units[axis]} and ${unit}`);
        }
      }
      if (units[axis] === null) {
        throw new TypeError(`Cannot interpolate ${kind} values because axis ${axis + 1} has no unit`);
      }
    }
  }
  const values = [0, 0, 0, 0];
  for (let axis = 0;axis < dimensions; axis++) {
    values[axis] = interpolateNumber({
      input,
      inputRange,
      outputRange: parsedOutputRange.map((parsed) => parsed.values[axis]),
      options
    });
  }
  return serializeStringInterpolationValue({
    kind,
    values,
    units,
    dimensions,
    axisRotation: hasAxisRotation
  });
};
var interpolateDiscreteString = ({
  input,
  inputRange,
  outputRange,
  options
}) => {
  if (inputRange.length === 1) {
    return outputRange[0];
  }
  for (let segmentIndex = 0;segmentIndex < inputRange.length - 1; segmentIndex++) {
    if (resolveEasingForSegment({
      easing: options?.easing,
      segmentIndex
    }) !== Easing.step1) {
      throw new TypeError("Non-numeric strings can only be interpolated using Easing.step1");
    }
  }
  const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
  const inputMin = inputRange[0];
  const inputMax = inputRange[inputRange.length - 1];
  let resolvedInput = posterizedInput;
  if (resolvedInput < inputMin) {
    if (options?.extrapolateLeft === "identity") {
      throw new TypeError('extrapolateLeft: "identity" is not supported for non-numeric strings');
    }
    if (options?.extrapolateLeft === "wrap") {
      const wrapRange = inputMax - inputMin;
      resolvedInput = ((resolvedInput - inputMin) % wrapRange + wrapRange) % wrapRange + inputMin;
    } else {
      return outputRange[0];
    }
  }
  if (resolvedInput > inputMax) {
    if (options?.extrapolateRight === "identity") {
      throw new TypeError('extrapolateRight: "identity" is not supported for non-numeric strings');
    }
    if (options?.extrapolateRight === "wrap") {
      const wrapRange = inputMax - inputMin;
      resolvedInput = ((resolvedInput - inputMin) % wrapRange + wrapRange) % wrapRange + inputMin;
    } else {
      return outputRange[outputRange.length - 1];
    }
  }
  const range = findRange(resolvedInput, inputRange);
  return resolvedInput >= inputRange[range + 1] ? outputRange[range + 1] : outputRange[range];
};
var validateTupleOutputRange = (outputRange) => {
  const dimensions = outputRange[0]?.length;
  if (dimensions === undefined) {
    throw new Error("outputRange must have at least 1 element");
  }
  if (dimensions === 0) {
    throw new TypeError("outputRange tuples must contain at least 1 number");
  }
  for (const output of outputRange) {
    if (output.length !== dimensions) {
      throw new TypeError(`outputRange tuples must all have the same length, but got ${dimensions} and ${output.length}`);
    }
    for (const value of output) {
      if (typeof value !== "number" || !Number.isFinite(value)) {
        throw new TypeError(`outputRange tuples must contain only finite numbers, but got [${output.join(",")}]`);
      }
    }
  }
  return dimensions;
};
var interpolateTuple = ({
  input,
  inputRange,
  outputRange,
  options
}) => {
  const dimensions = validateTupleOutputRange(outputRange);
  return new Array(dimensions).fill(true).map((_, axis) => interpolateNumber({
    input,
    inputRange,
    outputRange: outputRange.map((output) => output[axis]),
    options
  }));
};
function checkValidInputRange(arr) {
  for (let i = 1;i < arr.length; ++i) {
    if (!(arr[i] > arr[i - 1])) {
      throw new Error(`inputRange must be strictly monotonically increasing but got [${arr.join(",")}]`);
    }
  }
}
function checkInfiniteRange(name, arr) {
  if (arr.length < 1) {
    throw new Error(name + " must have at least 1 element");
  }
  for (const element of arr) {
    if (typeof element !== "number") {
      throw new Error(`${name} must contain only numbers`);
    }
    if (!Number.isFinite(element)) {
      throw new Error(`${name} must contain only finite numbers, but got [${arr.join(",")}]`);
    }
  }
}
function assertValidInterpolateEasingOption(easing, inputRangeLength) {
  if (easing === undefined) {
    return;
  }
  if (typeof easing === "function") {
    return;
  }
  const expectedLength = inputRangeLength - 1;
  if (easing.length !== expectedLength) {
    throw new Error(`When easing is an array, it must have one entry per segment between keyframes (length inputRange.length - 1 = ${expectedLength}), but got length ${easing.length}`);
  }
  for (let i = 0;i < easing.length; i++) {
    if (typeof easing[i] !== "function") {
      throw new Error(`easing[${i}] must be a function`);
    }
  }
}
function assertValidInterpolatePosterizeOption(posterize) {
  if (posterize === undefined) {
    return;
  }
  if (typeof posterize !== "number" || !Number.isFinite(posterize) || posterize <= 0) {
    throw new Error(`posterize must be a positive finite number, but got ${posterize}`);
  }
}
function assertValidInterpolateOutputOption(output) {
  if (output === undefined || output === "linear" || output === "perceptual-scale") {
    return;
  }
  throw new Error(`output must be "linear" or "perceptual-scale", but got ${String(output)}`);
}
function interpolate(input, inputRange, outputRange, options) {
  if (typeof input === "undefined") {
    throw new Error("input can not be undefined");
  }
  if (typeof inputRange === "undefined") {
    throw new Error("inputRange can not be undefined");
  }
  if (typeof outputRange === "undefined") {
    throw new Error("outputRange can not be undefined");
  }
  if (inputRange.length !== outputRange.length) {
    throw new Error("inputRange (" + inputRange.length + ") and outputRange (" + outputRange.length + ") must have the same length");
  }
  checkInfiniteRange("inputRange", inputRange);
  checkValidInputRange(inputRange);
  assertValidInterpolateEasingOption(options?.easing, inputRange.length);
  assertValidInterpolatePosterizeOption(options?.posterize);
  assertValidInterpolateOutputOption(options?.output);
  if (typeof input !== "number") {
    throw new TypeError("Cannot interpolate an input which is not a number");
  }
  if (!Array.isArray(outputRange)) {
    throw new Error("outputRange must contain only numbers");
  }
  const hasStringOutput = outputRange.some((output) => typeof output === "string");
  if (hasStringOutput) {
    if (!outputRange.every((output) => typeof output === "string" || typeof output === "number")) {
      throw new TypeError("outputRange must contain only numbers, or supported scale, translate, and rotate strings");
    }
    try {
      return interpolateString({ input, inputRange, outputRange, options });
    } catch (error) {
      if (!outputRange.every((output) => typeof output === "string")) {
        throw error;
      }
      const hasNonNumericString = outputRange.some((output) => {
        try {
          parseStringInterpolationValue(output);
          return false;
        } catch (parseError) {
          return parseError instanceof UnsupportedStringInterpolationValueError;
        }
      });
      if (!hasNonNumericString) {
        throw error;
      }
      return interpolateDiscreteString({
        input,
        inputRange,
        outputRange,
        options
      });
    }
  }
  if (outputRange.every((output) => Array.isArray(output))) {
    return interpolateTuple({ input, inputRange, outputRange, options });
  }
  if (!outputRange.every((output) => typeof output === "number")) {
    throw new TypeError("outputRange must contain only numbers, numeric tuples, or supported scale, translate, and rotate strings");
  }
  checkInfiniteRange("outputRange", outputRange);
  return interpolateNumber({ input, inputRange, outputRange, options });
}
// src/random.ts
function mulberry32(a2) {
  let t = a2 + 1831565813;
  t = Math.imul(t ^ t >>> 15, t | 1);
  t ^= t + Math.imul(t ^ t >>> 7, t | 61);
  return ((t ^ t >>> 14) >>> 0) / 4294967296;
}
function hashCode(str) {
  let i = 0;
  let chr = 0;
  let hash = 0;
  for (i = 0;i < str.length; i++) {
    chr = str.charCodeAt(i);
    hash = (hash << 5) - hash + chr;
    hash |= 0;
  }
  return hash;
}
var random = (seed, dummy) => {
  if (dummy !== undefined) {
    throw new TypeError("random() takes only one argument");
  }
  if (seed === null) {
    return Math.random();
  }
  if (typeof seed === "string") {
    return mulberry32(hashCode(seed));
  }
  if (typeof seed === "number") {
    return mulberry32(seed * 10000000000);
  }
  throw new Error("random() argument must be a number or a string");
};
// src/delay-render-constants.ts
var DELAY_RENDER_CALLSTACK_TOKEN = "The delayRender was called:";
var DELAY_RENDER_RETRIES_LEFT = "Retries left: ";
var DELAY_RENDER_RETRY_TOKEN = "- Rendering the frame will be retried.";
var DELAY_RENDER_CLEAR_TOKEN = "handle was cleared after";

// src/find-props-to-delete.ts
var findPropsToDelete = ({
  schema,
  key,
  value
}) => {
  const fieldSchema = schema[key];
  if (!fieldSchema) {
    throw new Error("Key " + JSON.stringify(key) + " not found in schema");
  }
  if (typeof value !== "string") {
    throw new Error("Value must be a string, but is " + JSON.stringify(value));
  }
  if (fieldSchema.type !== "enum") {
    throw new Error("Key " + JSON.stringify(key) + " is not an enum");
  }
  const currentVariant = fieldSchema.variants[value];
  if (!currentVariant) {
    throw new Error("Value for " + JSON.stringify(key) + " must be one of " + Object.keys(fieldSchema.variants).map((v) => JSON.stringify(v)).join(", ") + ", got " + JSON.stringify(value));
  }
  const otherVariants = Object.keys(fieldSchema.variants).filter((v) => v !== value);
  const otherKeys = new Set;
  for (const variant of otherVariants) {
    const otherVariant = fieldSchema.variants[variant];
    const keys = Object.keys(otherVariant);
    for (const k of keys) {
      otherKeys.add(k);
    }
  }
  return [...otherKeys];
};

// src/input-props-serialization.ts
var DATE_TOKEN = "remotion-date:";
var FILE_TOKEN = "remotion-file:";
var serializeJSONWithSpecialTypes = ({
  data,
  indent,
  staticBase
}) => {
  let customDateUsed = false;
  let customFileUsed = false;
  let mapUsed = false;
  let setUsed = false;
  try {
    const serializedString = JSON.stringify(data, function(key, value) {
      const item = this[key];
      if (item instanceof Date) {
        customDateUsed = true;
        return `${DATE_TOKEN}${item.toISOString()}`;
      }
      if (item instanceof Map) {
        mapUsed = true;
        return value;
      }
      if (item instanceof Set) {
        setUsed = true;
        return value;
      }
      if (typeof item === "string" && staticBase !== null && staticBase !== "" && item.startsWith(staticBase)) {
        customFileUsed = true;
        return `${FILE_TOKEN}${item.replace(staticBase + "/", "")}`;
      }
      return value;
    }, indent);
    return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
  } catch (err) {
    throw new Error("Could not serialize the passed input props to JSON: " + err.message);
  }
};
var resolveFileTokenToUrl = (value) => {
  const encodedName = value.replace(FILE_TOKEN, "");
  let name = encodedName;
  try {
    name = encodedName.split("/").map(decodeURIComponent).join("/");
  } catch {}
  const matchingStaticFile = window.remotion_staticFiles?.find((file) => file.name === name);
  if (matchingStaticFile) {
    return matchingStaticFile.src;
  }
  return `${window.remotion_staticBase}/${encodedName}`;
};
var deserializeJSONWithSpecialTypes = (data) => {
  return JSON.parse(data, (_, value) => {
    if (typeof value === "string" && value.startsWith(DATE_TOKEN)) {
      return new Date(value.replace(DATE_TOKEN, ""));
    }
    if (typeof value === "string" && value.startsWith(FILE_TOKEN)) {
      return resolveFileTokenToUrl(value);
    }
    return value;
  });
};

// src/interactivity-schema.ts
var transformSchema = {
  "style.transformOrigin": {
    type: "transform-origin",
    step: 1,
    default: "50% 50%",
    description: "Transform origin"
  },
  "style.translate": {
    type: "translate",
    step: 1,
    default: "0px 0px",
    description: "Offset"
  },
  "style.scale": {
    type: "scale",
    max: 100,
    step: 0.01,
    default: 1,
    description: "Scale",
    defaultKeyframeOutput: "perceptual-scale"
  },
  "style.rotate": {
    type: "rotation-css",
    step: 1,
    default: "0deg",
    description: "Rotation"
  },
  "style.opacity": {
    type: "number",
    min: 0,
    max: 1,
    step: 0.01,
    default: 1,
    description: "Opacity",
    hiddenFromList: false
  }
};
var borderSchema = {
  "style.borderWidth": {
    type: "number",
    default: undefined,
    min: 0,
    step: 1,
    description: "Border width",
    hiddenFromList: false
  },
  "style.borderStyle": {
    type: "enum",
    default: "none",
    description: "Border style",
    variants: {
      none: {},
      hidden: {},
      solid: {},
      dashed: {},
      dotted: {},
      double: {},
      groove: {},
      ridge: {},
      inset: {},
      outset: {}
    }
  },
  "style.borderColor": {
    type: "color",
    default: undefined,
    description: "Border color"
  }
};
var borderRadiusSchema = {
  "style.borderRadius": {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    description: "Border radius",
    hiddenFromList: false,
    keyframable: true
  },
  "style.borderTopLeftRadius": {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    description: "Top left radius",
    hiddenFromList: false
  },
  "style.borderTopRightRadius": {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    description: "Top right radius",
    hiddenFromList: false
  },
  "style.borderBottomRightRadius": {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    description: "Bottom right radius",
    hiddenFromList: false
  },
  "style.borderBottomLeftRadius": {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    description: "Bottom left radius",
    hiddenFromList: false
  }
};
var backgroundSchema = {
  "style.backgroundColor": {
    type: "color",
    default: "transparent",
    description: "Color"
  }
};
var svgColorSchema = {
  color: {
    type: "color",
    default: undefined,
    description: "Current color"
  }
};
var svgStrokeSchema = {
  ...svgColorSchema,
  stroke: {
    type: "color",
    default: "none",
    description: "Stroke"
  },
  strokeWidth: {
    type: "number",
    default: 1,
    description: "Stroke width",
    min: 0,
    step: 1,
    hiddenFromList: false
  }
};
var svgPaintSchema = {
  fill: {
    type: "color",
    default: undefined,
    description: "Fill"
  },
  ...svgStrokeSchema
};
var premountSchema = {
  premountFor: {
    type: "number",
    default: 0,
    description: "Premount For",
    min: 0,
    step: 1,
    hiddenFromList: false,
    keyframable: false
  },
  postmountFor: {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    hiddenFromList: true,
    keyframable: false
  }
};
var sequencePremountSchema = {
  ...premountSchema
};
var cropSchema = {
  cropLeft: {
    type: "number",
    default: 0,
    description: "Crop left",
    min: 0,
    max: 1,
    step: 0.01,
    hiddenFromList: false,
    keyframable: true
  },
  cropRight: {
    type: "number",
    default: 0,
    description: "Crop right",
    min: 0,
    max: 1,
    step: 0.01,
    hiddenFromList: false,
    keyframable: true
  },
  cropTop: {
    type: "number",
    default: 0,
    description: "Crop top",
    min: 0,
    max: 1,
    step: 0.01,
    hiddenFromList: false,
    keyframable: true
  },
  cropBottom: {
    type: "number",
    default: 0,
    description: "Crop bottom",
    min: 0,
    max: 1,
    step: 0.01,
    hiddenFromList: false,
    keyframable: true
  }
};
var sequenceCropSchema = cropSchema;
var sequenceStyleSchema = {
  ...sequenceCropSchema,
  ...transformSchema,
  ...backgroundSchema,
  ...borderSchema,
  ...borderRadiusSchema,
  ...sequencePremountSchema
};
var hiddenField = {
  type: "boolean",
  default: false,
  description: "Hidden"
};
var showInTimelineField = {
  type: "hidden"
};
var sequenceNameField = {
  type: "hidden"
};
var durationInFramesField = {
  type: "number",
  default: undefined,
  min: 1,
  step: 1,
  hiddenFromList: true
};
var fromField = {
  type: "number",
  default: 0,
  step: 1,
  hiddenFromList: true
};
var trimBeforeField = {
  type: "number",
  default: 0,
  min: 0,
  step: 1,
  hiddenFromList: true
};
var freezeField = {
  type: "number",
  default: null,
  step: 1,
  hiddenFromList: true
};
var baseSchema = {
  durationInFrames: durationInFramesField,
  from: fromField,
  trimBefore: trimBeforeField,
  freeze: freezeField,
  hidden: hiddenField,
  name: sequenceNameField,
  showInTimeline: showInTimelineField
};
var sequenceSchema = {
  ...baseSchema,
  layout: {
    type: "enum",
    default: "absolute-fill",
    description: "Layout",
    variants: {
      "absolute-fill": sequenceStyleSchema,
      none: {}
    }
  }
};
var baseSchemaWithoutFrom = {
  durationInFrames: durationInFramesField,
  trimBefore: trimBeforeField,
  freeze: freezeField,
  hidden: hiddenField,
  name: sequenceNameField,
  showInTimeline: showInTimelineField
};
var sequenceSchemaWithoutFrom = {
  ...baseSchemaWithoutFrom,
  layout: sequenceSchema.layout
};
var sequenceSchemaDefaultLayoutNone = {
  ...sequenceSchema,
  layout: {
    ...sequenceSchema.layout,
    default: "none"
  }
};

// src/interpolate-colors.ts
var NUMBER = "[-+]?\\d*\\.?\\d+";
var PERCENTAGE = NUMBER + "%";
function call(...args) {
  return "\\(\\s*(" + args.join(")\\s*,\\s*(") + ")\\s*\\)";
}
var MODERN_VALUE = "(?:none|[-+]?\\d*\\.?\\d+(?:%|deg|rad|grad|turn)?)";
function modernColorCall(name) {
  return new RegExp(name + "\\(\\s*(" + MODERN_VALUE + ")\\s+(" + MODERN_VALUE + ")\\s+(" + MODERN_VALUE + ")(?:\\s*\\/\\s*(" + MODERN_VALUE + "))?\\s*\\)");
}
function getMatchers() {
  const cachedMatchers = {
    rgb: undefined,
    rgba: undefined,
    hsl: undefined,
    hsla: undefined,
    hex3: undefined,
    hex4: undefined,
    hex5: undefined,
    hex6: undefined,
    hex8: undefined,
    oklch: undefined,
    oklab: undefined,
    lab: undefined,
    lch: undefined,
    hwb: undefined
  };
  if (cachedMatchers.rgb === undefined) {
    cachedMatchers.rgb = new RegExp("rgb" + call(NUMBER, NUMBER, NUMBER));
    cachedMatchers.rgba = new RegExp("rgba" + call(NUMBER, NUMBER, NUMBER, NUMBER));
    cachedMatchers.hsl = new RegExp("hsl" + call(NUMBER, PERCENTAGE, PERCENTAGE));
    cachedMatchers.hsla = new RegExp("hsla" + call(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER));
    cachedMatchers.hex3 = /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/;
    cachedMatchers.hex4 = /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/;
    cachedMatchers.hex6 = /^#([0-9a-fA-F]{6})$/;
    cachedMatchers.hex8 = /^#([0-9a-fA-F]{8})$/;
    cachedMatchers.oklch = modernColorCall("oklch");
    cachedMatchers.oklab = modernColorCall("oklab");
    cachedMatchers.lab = modernColorCall("lab");
    cachedMatchers.lch = modernColorCall("lch");
    cachedMatchers.hwb = modernColorCall("hwb");
  }
  return cachedMatchers;
}
function hue2rgb(p, q, t) {
  if (t < 0) {
    t += 1;
  }
  if (t > 1) {
    t -= 1;
  }
  if (t < 1 / 6) {
    return p + (q - p) * 6 * t;
  }
  if (t < 1 / 2) {
    return q;
  }
  if (t < 2 / 3) {
    return p + (q - p) * (2 / 3 - t) * 6;
  }
  return p;
}
function hslToRgb(h, s, l) {
  const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  const p = 2 * l - q;
  const r = hue2rgb(p, q, h + 1 / 3);
  const g = hue2rgb(p, q, h);
  const b2 = hue2rgb(p, q, h - 1 / 3);
  return Math.round(r * 255) << 24 | Math.round(g * 255) << 16 | Math.round(b2 * 255) << 8;
}
function parse255(str) {
  const int = Number.parseInt(str, 10);
  if (int < 0) {
    return 0;
  }
  if (int > 255) {
    return 255;
  }
  return int;
}
function parse360(str) {
  const int = Number.parseFloat(str);
  return (int % 360 + 360) % 360 / 360;
}
function parse1(str) {
  const num = Number.parseFloat(str);
  if (num < 0) {
    return 0;
  }
  if (num > 1) {
    return 255;
  }
  return Math.round(num * 255);
}
function parsePercentage(str) {
  const int = Number.parseFloat(str);
  if (int < 0) {
    return 0;
  }
  if (int > 100) {
    return 1;
  }
  return int / 100;
}
function parseModernComponent(str, percentScale) {
  if (str === "none")
    return 0;
  if (str.endsWith("%")) {
    return Number.parseFloat(str) / 100 * percentScale;
  }
  return Number.parseFloat(str);
}
function parseHueAngle(str) {
  if (str === "none")
    return 0;
  if (str.endsWith("rad")) {
    return Number.parseFloat(str) * 180 / Math.PI;
  }
  if (str.endsWith("grad"))
    return Number.parseFloat(str) * 0.9;
  if (str.endsWith("turn"))
    return Number.parseFloat(str) * 360;
  return Number.parseFloat(str);
}
function parseModernAlpha(str) {
  if (str === undefined || str === "none")
    return 1;
  if (str.endsWith("%")) {
    return Math.max(0, Math.min(1, Number.parseFloat(str) / 100));
  }
  return Math.max(0, Math.min(1, Number.parseFloat(str)));
}
function linearToSrgb(c2) {
  if (c2 <= 0.0031308)
    return 12.92 * c2;
  return 1.055 * c2 ** (1 / 2.4) - 0.055;
}
function clamp01(v) {
  return Math.max(0, Math.min(1, v));
}
function rgbFloatToInt(r, g, b2, alpha) {
  const ri = Math.round(clamp01(r) * 255);
  const gi = Math.round(clamp01(g) * 255);
  const bi = Math.round(clamp01(b2) * 255);
  const ai = Math.round(clamp01(alpha) * 255);
  return (ri << 24 | gi << 16 | bi << 8 | ai) >>> 0;
}
function oklabToSrgb(L, a2, b2) {
  const l_ = L + 0.3963377774 * a2 + 0.2158037573 * b2;
  const m_ = L - 0.1055613458 * a2 - 0.0638541728 * b2;
  const s_ = L - 0.0894841775 * a2 - 1.291485548 * b2;
  const l = l_ * l_ * l_;
  const m = m_ * m_ * m_;
  const s = s_ * s_ * s_;
  const rLin = 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;
  const gLin = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
  const bLin = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;
  return [linearToSrgb(rLin), linearToSrgb(gLin), linearToSrgb(bLin)];
}
function labToSrgb(L, a2, b2) {
  const epsilon = 216 / 24389;
  const kappa = 24389 / 27;
  const Xn = 0.95047;
  const Yn = 1;
  const Zn = 1.08883;
  const fy = (L + 16) / 116;
  const fx = a2 / 500 + fy;
  const fz = fy - b2 / 200;
  const fx3 = fx * fx * fx;
  const fz3 = fz * fz * fz;
  const xr = fx3 > epsilon ? fx3 : (116 * fx - 16) / kappa;
  const yr = L > kappa * epsilon ? ((L + 16) / 116) ** 3 : L / kappa;
  const zr = fz3 > epsilon ? fz3 : (116 * fz - 16) / kappa;
  const X = xr * Xn;
  const Y = yr * Yn;
  const Z = zr * Zn;
  const rLin = 3.2404542 * X - 1.5371385 * Y - 0.4985314 * Z;
  const gLin = -0.969266 * X + 1.8760108 * Y + 0.041556 * Z;
  const bLin = 0.0556434 * X - 0.2040259 * Y + 1.0572252 * Z;
  return [linearToSrgb(rLin), linearToSrgb(gLin), linearToSrgb(bLin)];
}
function hwbToSrgb(h, w, bk) {
  if (w + bk >= 1) {
    const gray = w / (w + bk);
    return [gray, gray, gray];
  }
  const q = 1;
  const p = 0;
  const r = hue2rgb(p, q, h + 1 / 3);
  const g = hue2rgb(p, q, h);
  const bl = hue2rgb(p, q, h - 1 / 3);
  const factor = 1 - w - bk;
  return [r * factor + w, g * factor + w, bl * factor + w];
}
var colorNames = {
  transparent: 0,
  aliceblue: 4042850303,
  antiquewhite: 4209760255,
  aqua: 16777215,
  aquamarine: 2147472639,
  azure: 4043309055,
  beige: 4126530815,
  bisque: 4293182719,
  black: 255,
  blanchedalmond: 4293643775,
  blue: 65535,
  blueviolet: 2318131967,
  brown: 2771004159,
  burlywood: 3736635391,
  burntsienna: 3934150143,
  cadetblue: 1604231423,
  chartreuse: 2147418367,
  chocolate: 3530104575,
  coral: 4286533887,
  cornflowerblue: 1687547391,
  cornsilk: 4294499583,
  crimson: 3692313855,
  cyan: 16777215,
  darkblue: 35839,
  darkcyan: 9145343,
  darkgoldenrod: 3095792639,
  darkgray: 2846468607,
  darkgreen: 6553855,
  darkgrey: 2846468607,
  darkkhaki: 3182914559,
  darkmagenta: 2332068863,
  darkolivegreen: 1433087999,
  darkorange: 4287365375,
  darkorchid: 2570243327,
  darkred: 2332033279,
  darksalmon: 3918953215,
  darkseagreen: 2411499519,
  darkslateblue: 1211993087,
  darkslategray: 793726975,
  darkslategrey: 793726975,
  darkturquoise: 13554175,
  darkviolet: 2483082239,
  deeppink: 4279538687,
  deepskyblue: 12582911,
  dimgray: 1768516095,
  dimgrey: 1768516095,
  dodgerblue: 512819199,
  firebrick: 2988581631,
  floralwhite: 4294635775,
  forestgreen: 579543807,
  fuchsia: 4278255615,
  gainsboro: 3705462015,
  ghostwhite: 4177068031,
  gold: 4292280575,
  goldenrod: 3668254975,
  gray: 2155905279,
  green: 8388863,
  greenyellow: 2919182335,
  grey: 2155905279,
  honeydew: 4043305215,
  hotpink: 4285117695,
  indianred: 3445382399,
  indigo: 1258324735,
  ivory: 4294963455,
  khaki: 4041641215,
  lavender: 3873897215,
  lavenderblush: 4293981695,
  lawngreen: 2096890111,
  lemonchiffon: 4294626815,
  lightblue: 2916673279,
  lightcoral: 4034953471,
  lightcyan: 3774873599,
  lightgoldenrodyellow: 4210742015,
  lightgray: 3553874943,
  lightgreen: 2431553791,
  lightgrey: 3553874943,
  lightpink: 4290167295,
  lightsalmon: 4288707327,
  lightseagreen: 548580095,
  lightskyblue: 2278488831,
  lightslategray: 2005441023,
  lightslategrey: 2005441023,
  lightsteelblue: 2965692159,
  lightyellow: 4294959359,
  lime: 16711935,
  limegreen: 852308735,
  linen: 4210091775,
  magenta: 4278255615,
  maroon: 2147483903,
  mediumaquamarine: 1724754687,
  mediumblue: 52735,
  mediumorchid: 3126187007,
  mediumpurple: 2473647103,
  mediumseagreen: 1018393087,
  mediumslateblue: 2070474495,
  mediumspringgreen: 16423679,
  mediumturquoise: 1221709055,
  mediumvioletred: 3340076543,
  midnightblue: 421097727,
  mintcream: 4127193855,
  mistyrose: 4293190143,
  moccasin: 4293178879,
  navajowhite: 4292783615,
  navy: 33023,
  oldlace: 4260751103,
  olive: 2155872511,
  olivedrab: 1804477439,
  orange: 4289003775,
  orangered: 4282712319,
  orchid: 3664828159,
  palegoldenrod: 4008225535,
  palegreen: 2566625535,
  paleturquoise: 2951671551,
  palevioletred: 3681588223,
  papayawhip: 4293907967,
  peachpuff: 4292524543,
  peru: 3448061951,
  pink: 4290825215,
  plum: 3718307327,
  powderblue: 2967529215,
  purple: 2147516671,
  rebeccapurple: 1714657791,
  red: 4278190335,
  rosybrown: 3163525119,
  royalblue: 1097458175,
  saddlebrown: 2336560127,
  salmon: 4202722047,
  sandybrown: 4104413439,
  seagreen: 780883967,
  seashell: 4294307583,
  sienna: 2689740287,
  silver: 3233857791,
  skyblue: 2278484991,
  slateblue: 1784335871,
  slategray: 1887473919,
  slategrey: 1887473919,
  snow: 4294638335,
  springgreen: 16744447,
  steelblue: 1182971135,
  tan: 3535047935,
  teal: 8421631,
  thistle: 3636451583,
  tomato: 4284696575,
  turquoise: 1088475391,
  violet: 4001558271,
  wheat: 4125012991,
  white: 4294967295,
  whitesmoke: 4126537215,
  yellow: 4294902015,
  yellowgreen: 2597139199
};
function normalizeColor(color) {
  const matchers = getMatchers();
  let match;
  if (matchers.hex6) {
    if (match = matchers.hex6.exec(color)) {
      return Number.parseInt(match[1] + "ff", 16) >>> 0;
    }
  }
  if (colorNames[color] !== undefined) {
    return colorNames[color];
  }
  if (matchers.rgb) {
    if (match = matchers.rgb.exec(color)) {
      return (parse255(match[1]) << 24 | parse255(match[2]) << 16 | parse255(match[3]) << 8 | 255) >>> 0;
    }
  }
  if (matchers.rgba) {
    if (match = matchers.rgba.exec(color)) {
      return (parse255(match[1]) << 24 | parse255(match[2]) << 16 | parse255(match[3]) << 8 | parse1(match[4])) >>> 0;
    }
  }
  if (matchers.hex3) {
    if (match = matchers.hex3.exec(color)) {
      return Number.parseInt(match[1] + match[1] + match[2] + match[2] + match[3] + match[3] + "ff", 16) >>> 0;
    }
  }
  if (matchers.hex8) {
    if (match = matchers.hex8.exec(color)) {
      return Number.parseInt(match[1], 16) >>> 0;
    }
  }
  if (matchers.hex4) {
    if (match = matchers.hex4.exec(color)) {
      return Number.parseInt(match[1] + match[1] + match[2] + match[2] + match[3] + match[3] + match[4] + match[4], 16) >>> 0;
    }
  }
  if (matchers.hsl) {
    if (match = matchers.hsl.exec(color)) {
      return (hslToRgb(parse360(match[1]), parsePercentage(match[2]), parsePercentage(match[3])) | 255) >>> 0;
    }
  }
  if (matchers.hsla) {
    if (match = matchers.hsla.exec(color)) {
      return (hslToRgb(parse360(match[1]), parsePercentage(match[2]), parsePercentage(match[3])) | parse1(match[4])) >>> 0;
    }
  }
  if (matchers.oklch) {
    if (match = matchers.oklch.exec(color)) {
      const L = parseModernComponent(match[1], 1);
      const C = parseModernComponent(match[2], 0.4);
      const H = parseHueAngle(match[3]);
      const alpha = parseModernAlpha(match[4]);
      const hRad = H * Math.PI / 180;
      const [r, g, b2] = oklabToSrgb(L, C * Math.cos(hRad), C * Math.sin(hRad));
      return rgbFloatToInt(r, g, b2, alpha);
    }
  }
  if (matchers.oklab) {
    if (match = matchers.oklab.exec(color)) {
      const L = parseModernComponent(match[1], 1);
      const a2 = parseModernComponent(match[2], 0.4);
      const b2 = parseModernComponent(match[3], 0.4);
      const alpha = parseModernAlpha(match[4]);
      const [r, g, bl] = oklabToSrgb(L, a2, b2);
      return rgbFloatToInt(r, g, bl, alpha);
    }
  }
  if (matchers.lab) {
    if (match = matchers.lab.exec(color)) {
      const L = parseModernComponent(match[1], 100);
      const a2 = parseModernComponent(match[2], 125);
      const b2 = parseModernComponent(match[3], 125);
      const alpha = parseModernAlpha(match[4]);
      const [r, g, bl] = labToSrgb(L, a2, b2);
      return rgbFloatToInt(r, g, bl, alpha);
    }
  }
  if (matchers.lch) {
    if (match = matchers.lch.exec(color)) {
      const L = parseModernComponent(match[1], 100);
      const C = parseModernComponent(match[2], 150);
      const H = parseHueAngle(match[3]);
      const alpha = parseModernAlpha(match[4]);
      const hRad = H * Math.PI / 180;
      const [r, g, bl] = labToSrgb(L, C * Math.cos(hRad), C * Math.sin(hRad));
      return rgbFloatToInt(r, g, bl, alpha);
    }
  }
  if (matchers.hwb) {
    if (match = matchers.hwb.exec(color)) {
      const H = parseHueAngle(match[1]);
      const W = parseModernComponent(match[2], 1);
      const B = parseModernComponent(match[3], 1);
      const alpha = parseModernAlpha(match[4]);
      const [r, g, bl] = hwbToSrgb(H / 360, W, B);
      return rgbFloatToInt(r, g, bl, alpha);
    }
  }
  throw new Error(`invalid color string ${color} provided`);
}
function processColor(color) {
  const normalizedColor = normalizeColor(color);
  return (normalizedColor << 24 | normalizedColor >>> 8) >>> 0;
}

// src/prores-profile.ts
var proResProfileOptions = [
  "4444-xq",
  "4444",
  "hq",
  "standard",
  "light",
  "proxy"
];

// src/scale-value.ts
var defaultScaleValue = [1, 1, 1];
var parseScaleString = (value) => {
  const parts = value.trim().split(/\s+/);
  if (parts.length < 1 || parts.length > 3 || parts[0] === "") {
    return null;
  }
  const parsed = parts.map((part) => Number(part));
  if (!parsed.every((part) => Number.isFinite(part))) {
    return null;
  }
  const x = parsed[0];
  const y = parsed[1] ?? x;
  const z = parsed[2] ?? 1;
  return [x, y, z];
};
var parseValidScaleValue = (value) => {
  if (typeof value === "number") {
    return Number.isFinite(value) ? [value, value, 1] : null;
  }
  if (typeof value === "string") {
    return parseScaleString(value);
  }
  return null;
};
var parseScaleValue = (value) => {
  return parseValidScaleValue(value) ?? defaultScaleValue;
};
var serializeScaleValue = ([x, y, z]) => {
  const normalizedX = normalizeNumber(x);
  const normalizedY = normalizeNumber(y);
  const normalizedZ = normalizeNumber(z);
  if (normalizedX === normalizedY && normalizedZ === 1) {
    return normalizedX;
  }
  if (normalizedZ === 1) {
    return `${normalizedX} ${normalizedY}`;
  }
  return `${normalizedX} ${normalizedY} ${normalizedZ}`;
};

// src/truthy.ts
function truthy(value) {
  return Boolean(value);
}

// src/v5-flag.ts
var ENABLE_V5_BREAKING_CHANGES = false;

// src/codec.ts
var validCodecs = [
  "h264",
  "h265",
  "vp8",
  "vp9",
  "av1",
  "mp3",
  "aac",
  "wav",
  "prores",
  "h264-mkv",
  "h264-ts",
  "gif"
];

// src/validation/validate-default-codec.ts
function validateCodec(defaultCodec, location, name) {
  if (typeof defaultCodec === "undefined") {
    return;
  }
  if (typeof defaultCodec !== "string") {
    throw new TypeError(`The "${name}" prop ${location} must be a string, but you passed a value of type ${typeof defaultCodec}.`);
  }
  if (!validCodecs.includes(defaultCodec)) {
    throw new Error(`The "${name}" prop ${location} must be one of ${validCodecs.join(", ")}, but you passed ${defaultCodec}.`);
  }
}

// src/validation/validate-default-props.ts
var validateDefaultAndInputProps = (defaultProps, name, compositionId) => {
  if (!defaultProps) {
    return;
  }
  if (typeof defaultProps !== "object") {
    throw new Error(`"${name}" must be an object, but you passed a value of type ${typeof defaultProps}`);
  }
  if (Array.isArray(defaultProps)) {
    throw new Error(`"${name}" must be an object, an array was passed ${compositionId ? `for composition "${compositionId}"` : ""}`);
  }
};

// src/validation/validate-dimensions.ts
function validateDimension(amount, nameOfProp, location) {
  if (typeof amount !== "number") {
    throw new Error(`The "${nameOfProp}" prop ${location} must be a number, but you passed a value of type ${typeof amount}`);
  }
  if (isNaN(amount)) {
    throw new TypeError(`The "${nameOfProp}" prop ${location} must not be NaN, but is NaN.`);
  }
  if (!Number.isFinite(amount)) {
    throw new TypeError(`The "${nameOfProp}" prop ${location} must be finite, but is ${amount}.`);
  }
  if (amount % 1 !== 0) {
    throw new TypeError(`The "${nameOfProp}" prop ${location} must be an integer, but is ${amount}.`);
  }
  if (amount <= 0) {
    throw new TypeError(`The "${nameOfProp}" prop ${location} must be positive, but got ${amount}.`);
  }
}

// src/validation/validate-duration-in-frames.ts
function validateDurationInFrames(durationInFrames, options) {
  const { allowFloats, component } = options;
  if (typeof durationInFrames === "undefined") {
    throw new Error(`The "durationInFrames" prop ${component} is missing.`);
  }
  if (typeof durationInFrames !== "number") {
    throw new Error(`The "durationInFrames" prop ${component} must be a number, but you passed a value of type ${typeof durationInFrames}`);
  }
  if (durationInFrames <= 0) {
    throw new TypeError(`The "durationInFrames" prop ${component} must be positive, but got ${durationInFrames}.`);
  }
  if (!allowFloats && durationInFrames % 1 !== 0) {
    throw new TypeError(`The "durationInFrames" prop ${component} must be an integer, but got ${durationInFrames}.`);
  }
  if (!Number.isFinite(durationInFrames)) {
    throw new TypeError(`The "durationInFrames" prop ${component} must be finite, but got ${durationInFrames}.`);
  }
}

// src/video/get-current-time.ts
var getExpectedMediaFrameUncorrected = ({
  frame,
  playbackRate,
  startFrom
}) => {
  return interpolate(frame, [-1, startFrom, startFrom + 1], [-1, startFrom, startFrom + playbackRate]);
};

// src/absolute-src.ts
var getAbsoluteSrc = (relativeSrc) => {
  if (typeof window === "undefined") {
    return relativeSrc;
  }
  if (relativeSrc.startsWith("http://") || relativeSrc.startsWith("https://") || relativeSrc.startsWith("file://") || relativeSrc.startsWith("blob:") || relativeSrc.startsWith("data:")) {
    return relativeSrc;
  }
  return new URL(relativeSrc, window.origin).href;
};

// src/video/offthread-video-source.ts
var getOffthreadVideoSource = ({
  src,
  transparent,
  currentTime,
  toneMapped
}) => {
  return `http://localhost:${window.remotion_proxyPort}/proxy?src=${encodeURIComponent(getAbsoluteSrc(src))}&time=${encodeURIComponent(Math.max(0, currentTime))}&transparent=${String(transparent)}&toneMapped=${String(toneMapped)}`;
};

// src/no-react.ts
var NoReactInternals = {
  processColor,
  truthy,
  validateFps,
  validateDimension,
  validateDurationInFrames,
  validateDefaultAndInputProps,
  validateFrame,
  serializeJSONWithSpecialTypes,
  bundleName: "bundle.js",
  bundleMapName: "bundle.js.map",
  deserializeJSONWithSpecialTypes,
  DELAY_RENDER_CALLSTACK_TOKEN,
  DELAY_RENDER_RETRY_TOKEN,
  DELAY_RENDER_CLEAR_TOKEN,
  DELAY_RENDER_ATTEMPT_TOKEN: DELAY_RENDER_RETRIES_LEFT,
  getOffthreadVideoSource,
  getExpectedMediaFrameUncorrected,
  ENABLE_V5_BREAKING_CHANGES,
  MIN_NODE_VERSION: ENABLE_V5_BREAKING_CHANGES ? 22 : 16,
  MIN_BUN_VERSION: ENABLE_V5_BREAKING_CHANGES ? "1.1.3" : "1.0.3",
  MIN_ESLINT_VERSION: ENABLE_V5_BREAKING_CHANGES ? "8.57.0" : "7.15.0",
  colorNames,
  DATE_TOKEN,
  FILE_TOKEN,
  validateCodec,
  proResProfileOptions,
  findPropsToDelete,
  sequenceSchema,
  parseScaleValue,
  serializeScaleValue
};
export {
  random,
  interpolate,
  assertValidInterpolatePosterizeOption,
  assertValidInterpolateEasingOption,
  NoReactInternals
};