Ressources gratuites

Quelques scripts After Effects — copier, coller, c'est fait.

After Effects

Renommer les calques en lot

Renomme tous les calques sélectionnés avec un préfixe et une numérotation séquentielle automatique — pratique pour nettoyer un projet avant livraison.

script.jsx
// Batch Layer Renamer
// Renames all selected layers with a sequential prefix, e.g. "SHOT_01", "SHOT_02"...
(function batchLayerRenamer() {
  var comp = app.project.activeItem;
  if (!(comp && comp instanceof CompItem)) {
    alert("Select or open a composition first.");
    return;
  }

  var selectedLayers = comp.selectedLayers;
  if (selectedLayers.length === 0) {
    alert("Select at least one layer to rename.");
    return;
  }

  var prefix = prompt("Prefix?", "SHOT_");
  if (prefix === null) return;

  var startInput = prompt("Start numbering at?", "1");
  var start = parseInt(startInput, 10);
  if (isNaN(start)) start = 1;

  var padInput = prompt("Zero-pad to how many digits?", "2");
  var pad = parseInt(padInput, 10);
  if (isNaN(pad) || pad < 1) pad = 2;

  function padNumber(n, width) {
    var s = String(n);
    while (s.length < width) s = "0" + s;
    return s;
  }

  // Sort by current stacking order so the rename follows what you see in the timeline.
  var ordered = [];
  for (var i = 0; i < selectedLayers.length; i++) ordered.push(selectedLayers[i]);
  ordered.sort(function (a, b) {
    return a.index - b.index;
  });

  app.beginUndoGroup("Batch Layer Renamer");

  for (var j = 0; j < ordered.length; j++) {
    ordered[j].name = prefix + padNumber(start + j, pad);
  }

  app.endUndoGroup();
})();
After Effects

Parenter à un null centré

Crée un calque null positionné au centre de la sélection et y parente automatiquement tous les calques sélectionnés, sans décalage de position.

script.jsx
// Parent to Centered Null
// Creates a null at the bounding-box center of the selected layers and parents them to it,
// so you get a single rig handle without nudging anything out of place.
(function parentToCenteredNull() {
  var comp = app.project.activeItem;
  if (!(comp && comp instanceof CompItem)) {
    alert("Select or open a composition first.");
    return;
  }

  var selectedLayers = comp.selectedLayers;
  if (selectedLayers.length === 0) {
    alert("Select at least one layer to parent.");
    return;
  }

  var time = comp.time;
  var minX = Infinity,
    minY = Infinity,
    maxX = -Infinity,
    maxY = -Infinity;

  for (var i = 0; i < selectedLayers.length; i++) {
    var layer = selectedLayers[i];
    var pos = layer.position ? layer.position.valueAtTime(time, false) : [comp.width / 2, comp.height / 2];
    var bounds;
    try {
      bounds = layer.sourceRectAtTime(time, false);
    } catch (e) {
      bounds = { left: 0, top: 0, width: 0, height: 0 };
    }

    var anchor = layer.anchorPoint ? layer.anchorPoint.valueAtTime(time, false) : [0, 0];
    var left = pos[0] + bounds.left - anchor[0];
    var top = pos[1] + bounds.top - anchor[1];
    var right = left + bounds.width;
    var bottom = top + bounds.height;

    if (left < minX) minX = left;
    if (top < minY) minY = top;
    if (right > maxX) maxX = right;
    if (bottom > maxY) maxY = bottom;
  }

  var centerX = (minX + maxX) / 2;
  var centerY = (minY + maxY) / 2;

  app.beginUndoGroup("Parent to Centered Null");

  var nullLayer = comp.layers.addNull();
  nullLayer.name = "NULL_" + selectedLayers[0].name;
  nullLayer.position.setValue([centerX, centerY]);
  nullLayer.moveToBeginning();

  for (var j = 0; j < selectedLayers.length; j++) {
    if (selectedLayers[j] !== nullLayer) {
      selectedLayers[j].parent = nullLayer;
    }
  }

  app.endUndoGroup();
})();
After Effects

Rebond inertiel (spring physique)

Expression à coller sur Position, Scale ou Rotation qui simule un ressort masse-amorti pour un atterrissage naturel sur la dernière keyframe — réglages masse / raideur / amortissement inclus.

expression.js
// Inertial Bounce — Spring Simulation
// Apply to Position, Scale, or Rotation. Simulates a mass-spring-damper settling
// into the last keyframe instead of a closed-form decay curve — tune mass / stiffness /
// damping for anything from a soft landing to a rubbery overshoot.
mass = 2; // heavier = slower to settle
stiffness = 250; // higher = snappier
damping = 12; // higher = less oscillation, lower = more bounces

n = 0;
if (numKeys > 0) {
  n = nearestKey(time).index;
  if (key(n).time > time) n--;
}

if (n === 0) {
  value;
} else {
  t0 = key(n).time;
  target = key(n).value;
  v0 = velocityAtTime(t0 - thisComp.frameDuration / 10);

  pos = 0;
  vel = v0;
  dt = 1 / (thisComp.frameRate * 4);
  steps = Math.min(Math.ceil((time - t0) / dt), 400); // cap for perf on long holds

  for (i = 0; i < steps; i++) {
    accel = (-stiffness * pos - damping * vel) / mass;
    vel += accel * dt;
    pos += vel * dt;
  }

  target + pos;
}
After Effects

Convertir les expressions en keyframes

Échantillonne les propriétés sélectionnées sur la zone de travail et remplace leur expression par de vraies keyframes — utile avant un rendu, une précomposition ou un partage de projet.

script.jsx
// Bake Expressions to Keyframes
// Converts expressions on selected properties into real keyframes across the work area,
// then removes the expression — useful before rendering, precomposing, or sharing a project.
(function bakeExpressions() {
  var comp = app.project.activeItem;
  if (!(comp && comp instanceof CompItem)) {
    alert("Select or open a composition first.");
    return;
  }

  var props = comp.selectedProperties;
  if (props.length === 0) {
    alert("Select at least one property with an expression.");
    return;
  }

  var stepInput = prompt("Sample every N frames?", "1");
  var step = parseInt(stepInput, 10);
  if (isNaN(step) || step < 1) step = 1;

  app.beginUndoGroup("Bake Expressions to Keyframes");

  var frameDuration = comp.frameDuration;
  var startFrame = Math.round(comp.workAreaStart / frameDuration);
  var endFrame = Math.round((comp.workAreaStart + comp.workAreaDuration) / frameDuration);

  for (var i = 0; i < props.length; i++) {
    var prop = props[i];
    if (!(prop instanceof Property) || !prop.canSetExpression || !prop.expressionEnabled) {
      continue;
    }

    var samples = [];
    for (var f = startFrame; f <= endFrame; f += step) {
      var t = f * frameDuration;
      samples.push({ time: t, value: prop.valueAtTime(t, false) });
    }

    prop.expression = "";

    for (var s = 0; s < samples.length; s++) {
      prop.setValueAtTime(samples[s].time, samples[s].value);
    }
  }

  app.endUndoGroup();
})();
After Effects

Dupliquer & renommer les calques

Duplique le calque sélectionné N fois dans la composition active, en incrémentant automatiquement le nom et en décalant le point d'entrée de chaque copie.

script.jsx
// Duplicate & Rename Layers
// Duplicates the selected layer(s) N times, incrementing name and stagger offset.
(function duplicateAndRename() {
  var comp = app.project.activeItem;
  if (!(comp && comp instanceof CompItem)) {
    alert("Select or open a composition first.");
    return;
  }

  var selectedLayers = comp.selectedLayers;
  if (selectedLayers.length === 0) {
    alert("Select at least one layer to duplicate.");
    return;
  }

  var count = parseInt(prompt("How many copies?", "5"), 10);
  var staggerFrames = parseInt(prompt("Stagger offset (frames)?", "2"), 10);
  if (isNaN(count) || count < 1) return;

  app.beginUndoGroup("Duplicate & Rename Layers");

  for (var i = 0; i < selectedLayers.length; i++) {
    var source = selectedLayers[i];
    var baseName = source.name.replace(/\s\d+$/, "");

    for (var n = 1; n <= count; n++) {
      var copy = source.duplicate();
      copy.name = baseName + " " + (n + 1);
      copy.startTime = source.startTime + n * staggerFrames * comp.frameDuration;
    }
  }

  app.endUndoGroup();
})();
After Effects

Expression d'overshoot

Expression à coller sur Scale ou Position qui ajoute un léger rebond ressort par-dessus vos keyframes existantes — aucune keyframe supplémentaire nécessaire.

overshoot.js
// Overshoot Ease Expression
// Apply to Scale or Position. Adds a spring overshoot on top of existing keyframes.
amp = 0.08; // overshoot amount (fraction of the value change)
freq = 3.0; // oscillations per second
decay = 6.0; // how quickly the overshoot settles

n = 0;
if (numKeys > 0) {
  n = nearestKey(time).index;
  if (key(n).time > time) n--;
}

if (n === 0) {
  value;
} else {
  t = time - key(n).time;
  v = velocityAtTime(key(n).time - thisComp.frameDuration / 10);
  value + v * amp * Math.sin(freq * t * 2 * Math.PI) * Math.exp(-decay * t);
}