app
Premiere Pro Bridge
Public Made by Adomby adom
Let the AI edit video in Adobe Premiere Pro on your desktop (import, cut, trim, razor, effects, audio, previews, export) with no mouse or keyboard. Check adom-bridge bridge_list for 'premiere'; install with bridge_install + adom-wiki pkg install adom/premiere-bridge, then start with premiere_status.
main
anastasia
Premiere Pro Bridge 0.1.0: Rust bridge, UXP plugin, CEP helper, skills, macOS manifest
32fb583
10d ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
// Adom Bridge — ExtendScript side of the CEP helper (ES3: no JSON, no let/const).
// adom_dispatch(jsonString) -> JSON string {ok, result|error, errorCode}
function adom_json(v) {
var t = typeof v;
if (v === null || v === undefined) return "null";
if (t === "number") return isFinite(v) ? String(v) : "null";
if (t === "boolean") return v ? "true" : "false";
if (t === "string") {
return '"' + v.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t") + '"';
}
if (v instanceof Array) {
var a = [];
for (var i = 0; i < v.length; i++) a.push(adom_json(v[i]));
return "[" + a.join(",") + "]";
}
if (t === "object") {
var parts = [];
for (var k in v) {
if (v.hasOwnProperty(k) && typeof v[k] !== "function") parts.push(adom_json(String(k)) + ":" + adom_json(v[k]));
}
return "{" + parts.join(",") + "}";
}
return adom_json(String(v));
}
function adom_hello() {
var proj = app.project ? app.project.name : null;
var seq = app.project && app.project.activeSequence ? app.project.activeSequence.name : null;
return adom_json({ premiereVersion: app.version, build: app.build, project: proj, sequence: seq });
}
function adom_fail(code, msg) {
var e = new Error(msg);
e.adomCode = code;
return e;
}
function adom_seq() {
var seq = app.project.activeSequence;
if (!seq) throw adom_fail("no_sequence", "No active sequence");
app.enableQE();
var qseq = qe.project.getActiveSequence();
if (!qseq) throw adom_fail("no_sequence", "QE has no active sequence");
return { seq: seq, qseq: qseq };
}
// "V1" -> {video:true, index:0}
function adom_track(ref) {
var m = /^([VvAa])(\d+)$/.exec(String(ref));
if (!m) throw adom_fail("bad_track", "Bad track '" + ref + "' (use V1, A2 …)");
return { video: m[1].toUpperCase() === "V", index: parseInt(m[2], 10) - 1 };
}
function adom_timecode(seq, seconds) {
var t = new Time();
t.seconds = Number(seconds);
var s = seq.getSettings();
return t.getFormatted(s.videoFrameRate, s.videoDisplayFormat);
}
// The QE item at (track, clipIndex) where clipIndex counts real clips in time order —
// the same numbering the UXP side uses ("V1:0"). QE lists gaps as "Empty" items.
function adom_qeClip(qtrack, clipIndex) {
var n = qtrack.numItems;
var k = 0;
for (var i = 0; i < n; i++) {
var it = qtrack.getItemAt(i);
if (!it || it.type === "Empty") continue;
if (k === clipIndex) return it;
k++;
}
throw adom_fail("clip_not_found", "No clip index " + clipIndex + " on that track");
}
var ADOM_VERBS = {
ping: function () {
return eval("(" + adom_hello() + ")");
},
razor: function (a) {
var c = adom_seq();
var tc = adom_timecode(c.seq, a.time);
var cut = [];
var i;
var want = null;
if (a.tracks) {
want = {};
for (i = 0; i < a.tracks.length; i++) want[String(a.tracks[i]).toUpperCase()] = true;
}
for (i = 0; i < c.qseq.numVideoTracks; i++) {
if (want && !want["V" + (i + 1)]) continue;
c.qseq.getVideoTrackAt(i).razor(tc);
cut.push("V" + (i + 1));
}
for (i = 0; i < c.qseq.numAudioTracks; i++) {
if (want && !want["A" + (i + 1)]) continue;
c.qseq.getAudioTrackAt(i).razor(tc);
cut.push("A" + (i + 1));
}
return { cutTracks: cut, timecode: tc, method: "qe-razor" };
},
set_speed: function (a) {
var c = adom_seq();
var m = /^([VvAa]\d+):(\d+)$/.exec(String(a.clip));
if (!m) throw adom_fail("bad_clip", "clip must look like V1:0");
var tr = adom_track(m[1]);
var qtrack = tr.video ? c.qseq.getVideoTrackAt(tr.index) : c.qseq.getAudioTrackAt(tr.index);
var item = adom_qeClip(qtrack, parseInt(m[2], 10));
// setSpeed(speed, unused, reverse, ripple, maintainAudioPitch)
item.setSpeed(Number(a.speed), "", !!a.reverse, !!a.ripple, a.maintainPitch !== false);
return { clip: a.clip, speed: Number(a.speed), reverse: !!a.reverse, ripple: !!a.ripple };
},
add_tracks: function (a) {
var c = adom_seq();
var v = Number(a.video || 0);
var au = Number(a.audio || 0);
// addTracks(numVideo, insertAfterVideoIdx, numAudio, audioType(0 mono,1 stereo,2 5.1), insertAfterAudioIdx, numSubmix, submixType, insertAfterSubmix)
c.qseq.addTracks(v, c.qseq.numVideoTracks, au, a.audioType === "mono" ? 0 : a.audioType === "5.1" ? 2 : 1, c.qseq.numAudioTracks, 0, 0, 0);
return { videoTracks: c.qseq.numVideoTracks, audioTracks: c.qseq.numAudioTracks };
},
remove_track: function (a) {
var c = adom_seq();
var tr = adom_track(a.track);
if (tr.video) c.qseq.removeVideoTrack(tr.index);
else c.qseq.removeAudioTrack(tr.index);
return { removed: a.track };
},
lock_track: function (a) {
var c = adom_seq();
var tr = adom_track(a.track);
var t = tr.video ? c.seq.videoTracks[tr.index] : c.seq.audioTracks[tr.index];
t.setLocked(a.locked !== false ? 1 : 0);
return { track: a.track, locked: a.locked !== false };
},
set_track_target: function (a) {
var c = adom_seq();
var tr = adom_track(a.track);
var t = tr.video ? c.seq.videoTracks[tr.index] : c.seq.audioTracks[tr.index];
t.setTargeted(a.targeted !== false, true);
return { track: a.track, targeted: a.targeted !== false };
},
export_frame_qe: function (a) {
var c = adom_seq();
var tc = adom_timecode(c.seq, a.time);
c.qseq.exportFramePNG(tc, a.path);
return { path: a.path, timecode: tc };
},
extendscript: function (a) {
// a.code is evaluated as a function body; `return` a value. Has app, qe (after app.enableQE()).
app.enableQE();
var f = new Function("args", a.code);
return { value: f(a.args || {}) };
},
};
function adom_dispatch(payload) {
try {
var req = eval("(" + payload + ")");
var fn = ADOM_VERBS[req.verb];
if (!fn) return adom_json({ ok: false, errorCode: "not_in_cep", error: "CEP helper has no verb '" + req.verb + "'" });
return adom_json({ ok: true, result: fn(req.args || {}) });
} catch (e) {
return adom_json({ ok: false, errorCode: e.adomCode || "extendscript_error", error: String(e.message || e), line: e.line });
}
}