Created
May 22, 2026 11:33
-
-
Save gordielachance/11b948223305035ad3f1735e5f84d0ea to your computer and use it in GitHub Desktop.
After Effects JSX Script - Offset markers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| After Effects JSX Script | |
| Offset markers V2 | |
| Author: G.Breant + Claude | |
| */ | |
| (function offsetMarkers() { | |
| var comp = app.project.activeItem; | |
| if (!comp || !(comp instanceof CompItem)) { | |
| alert("Open a composition first."); | |
| return; | |
| } | |
| // ── UI ──────────────────────────────────────────────────────────────── | |
| var dlg = new Window("dialog", "Offset Markers"); | |
| dlg.orientation = "column"; | |
| dlg.alignChildren = ["fill", "top"]; | |
| dlg.margins = 18; | |
| dlg.spacing = 12; | |
| var framesGrp = dlg.add("group"); | |
| framesGrp.add("statictext", undefined, "Offset (frames):"); | |
| var framesInput = framesGrp.add("edittext", undefined, "10"); | |
| framesInput.preferredSize.width = 60; | |
| var dirGrp = dlg.add("group"); | |
| dirGrp.add("statictext", undefined, "Active area:"); | |
| var dirMenu = dirGrp.add("dropdownlist", undefined, | |
| ["All", "Before playhead only", "After playhead only", "Work area"]); | |
| dirMenu.selection = 2; | |
| dirMenu.preferredSize.width = 180; | |
| var targetGrp = dlg.add("group"); | |
| targetGrp.add("statictext", undefined, "Target:"); | |
| var targetMenu = targetGrp.add("dropdownlist", undefined, | |
| ["Comp + all layers", "Comp markers only", "Layer markers only"]); | |
| targetMenu.selection = 1; | |
| targetMenu.preferredSize.width = 180; | |
| var btnGrp = dlg.add("group"); | |
| btnGrp.alignment = "right"; | |
| var cancelBtn = btnGrp.add("button", undefined, "Cancel", { name: "cancel" }); | |
| var okBtn = btnGrp.add("button", undefined, "OK", { name: "ok" }); | |
| cancelBtn.onClick = function () { dlg.close(); }; | |
| okBtn.onClick = function () { | |
| var frames = parseInt(framesInput.text, 10); | |
| if (isNaN(frames) || frames === 0) { | |
| alert("Enter a non-zero integer number of frames."); | |
| return; | |
| } | |
| var dir = dirMenu.selection.index; // 0 both | 1 before | 2 after | 3 work area | |
| var target = targetMenu.selection.index; // 0 both | 1 comp | 2 layers | |
| var fps = comp.frameRate; | |
| var playhead = comp.time; // seconds | |
| var offsetSec = frames / fps; // convert frames → seconds | |
| // ── work area bounds (only computed when needed) ─────────────── | |
| var workAreaStart = comp.workAreaStart; | |
| var workAreaEnd = comp.workAreaStart + comp.workAreaDuration; | |
| // ── helper: should this marker time be shifted? ──────────────── | |
| function shouldOffset(markerTime) { | |
| if (dir === 0) return true; | |
| if (dir === 1) return markerTime < playhead; | |
| if (dir === 2) return markerTime >= playhead; | |
| if (dir === 3) return markerTime >= workAreaStart && markerTime < workAreaEnd; | |
| } | |
| // ── helper: shift a MarkerValueCollection ────────────────────── | |
| function shiftMarkers(markerCollection) { | |
| var indices = []; | |
| for (var i = 1; i <= markerCollection.numKeys; i++) { | |
| indices.push(i); | |
| } | |
| // Iterate in reverse when moving forward to avoid key collisions | |
| if (offsetSec > 0) indices.reverse(); | |
| for (var j = 0; j < indices.length; j++) { | |
| var idx = indices[j]; | |
| var t = markerCollection.keyTime(idx); | |
| if (shouldOffset(t)) { | |
| var mv = markerCollection.keyValue(idx); | |
| markerCollection.removeKey(idx); | |
| markerCollection.setValueAtTime(t + offsetSec, mv); | |
| } | |
| } | |
| } | |
| app.beginUndoGroup("Offset Markers"); | |
| // ── Comp markers ─────────────────────────────────────────────── | |
| if (target === 0 || target === 1) { | |
| shiftMarkers(comp.markerProperty); | |
| } | |
| // ── Layer markers ────────────────────────────────────────────── | |
| if (target === 0 || target === 2) { | |
| for (var li = 1; li <= comp.numLayers; li++) { | |
| var layer = comp.layer(li); | |
| if (layer.marker && layer.marker.numKeys > 0) { | |
| shiftMarkers(layer.marker); | |
| } | |
| } | |
| } | |
| app.endUndoGroup(); | |
| dlg.close(); | |
| alert("Done. Markers offset by " + frames + " frame(s)."); | |
| }; | |
| dlg.show(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment