@synthetic-ai/premiere-mcp 2.2.0 → 2.3.0-dev.0

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +135 -135
  2. package/LICENSE +21 -21
  3. package/README.md +242 -242
  4. package/cep-plugin/.debug +8 -8
  5. package/cep-plugin/CSInterface.js +92 -92
  6. package/cep-plugin/host.jsx +7 -7
  7. package/cep-plugin/index.html +472 -472
  8. package/cep-plugin/main.js +6 -0
  9. package/cep-plugin/premiere.jsx +24947 -24947
  10. package/dist/bridge/script-builder.js +378 -378
  11. package/dist/license.js +38 -0
  12. package/dist/server.js +60 -60
  13. package/dist/tools/advanced.js +357 -357
  14. package/dist/tools/audio-advanced.js +1049 -1049
  15. package/dist/tools/audio.js +42 -42
  16. package/dist/tools/captions.js +27 -27
  17. package/dist/tools/clipboard.js +214 -214
  18. package/dist/tools/color-advanced.js +253 -253
  19. package/dist/tools/discovery.js +291 -291
  20. package/dist/tools/effects.js +285 -285
  21. package/dist/tools/export-presets.js +206 -206
  22. package/dist/tools/export.js +255 -255
  23. package/dist/tools/health.js +10 -10
  24. package/dist/tools/inspection.js +885 -885
  25. package/dist/tools/keyframes.js +369 -369
  26. package/dist/tools/markers.js +89 -89
  27. package/dist/tools/media.js +178 -178
  28. package/dist/tools/metadata.js +94 -94
  29. package/dist/tools/multicam.js +50 -50
  30. package/dist/tools/playback.js +15 -15
  31. package/dist/tools/playhead.js +95 -95
  32. package/dist/tools/project-manager.js +21 -21
  33. package/dist/tools/project.js +149 -149
  34. package/dist/tools/scripting.js +319 -319
  35. package/dist/tools/selection.js +202 -202
  36. package/dist/tools/sequence-advanced.js +379 -379
  37. package/dist/tools/sequence-settings.js +564 -564
  38. package/dist/tools/sequence.js +167 -167
  39. package/dist/tools/source-monitor.js +68 -68
  40. package/dist/tools/text.js +58 -58
  41. package/dist/tools/timeline.js +312 -312
  42. package/dist/tools/track-management.js +446 -446
  43. package/dist/tools/track-targeting.js +635 -635
  44. package/dist/tools/tracks.js +87 -87
  45. package/dist/tools/transitions-motion.js +174 -174
  46. package/dist/tools/transitions.js +111 -111
  47. package/dist/tools/utility.js +606 -606
  48. package/dist/tools/workspace.js +29 -29
  49. package/package.json +66 -66
  50. package/scripts/build-chat-dmg.sh +210 -210
  51. package/scripts/build-chat-zip.sh +291 -291
  52. package/scripts/install-cep-windows.ps1 +99 -99
  53. package/scripts/install-cep.sh +66 -66
  54. package/scripts/install-chat-plugin.bat +67 -67
  55. package/scripts/install-chat-plugin.sh +85 -85
  56. package/scripts/install-windows.bat +95 -95
  57. package/scripts/package.mjs +254 -254
@@ -24,22 +24,22 @@ export function getTrackTargetingTools(bridgeOptions) {
24
24
  required: ["track_type", "track_index", "targeted"],
25
25
  },
26
26
  handler: async (args) => {
27
- const script = buildToolScript(`
28
- var seq = app.project.activeSequence;
29
- if (!seq) return __error("No active sequence");
30
-
31
- var tracks = ${args.track_type === "video" ? "seq.videoTracks" : "seq.audioTracks"};
32
- if (${args.track_index} >= tracks.numTracks) return __error("Track index out of range");
33
-
34
- var track = tracks[${args.track_index}];
35
- track.setTargeted(${args.targeted}, ${args.track_type === "video"});
36
-
37
- return __result({
38
- trackType: "${args.track_type}",
39
- trackIndex: ${args.track_index},
40
- trackName: track.name,
41
- targeted: ${args.targeted}
42
- });
27
+ const script = buildToolScript(`
28
+ var seq = app.project.activeSequence;
29
+ if (!seq) return __error("No active sequence");
30
+
31
+ var tracks = ${args.track_type === "video" ? "seq.videoTracks" : "seq.audioTracks"};
32
+ if (${args.track_index} >= tracks.numTracks) return __error("Track index out of range");
33
+
34
+ var track = tracks[${args.track_index}];
35
+ track.setTargeted(${args.targeted}, ${args.track_type === "video"});
36
+
37
+ return __result({
38
+ trackType: "${args.track_type}",
39
+ trackIndex: ${args.track_index},
40
+ trackName: track.name,
41
+ targeted: ${args.targeted}
42
+ });
43
43
  `);
44
44
  return sendCommand(script, bridgeOptions);
45
45
  },
@@ -48,29 +48,29 @@ export function getTrackTargetingTools(bridgeOptions) {
48
48
  description: "Get which tracks are currently targeted for editing.",
49
49
  parameters: {},
50
50
  handler: async () => {
51
- const script = buildToolScript(`
52
- var seq = app.project.activeSequence;
53
- if (!seq) return __error("No active sequence");
54
-
55
- var targets = { video: [], audio: [] };
56
- for (var t = 0; t < seq.videoTracks.numTracks; t++) {
57
- var track = seq.videoTracks[t];
58
- try {
59
- if (track.isTargeted()) {
60
- targets.video.push({ index: t, name: track.name });
61
- }
62
- } catch(e) {}
63
- }
64
- for (var t = 0; t < seq.audioTracks.numTracks; t++) {
65
- var track = seq.audioTracks[t];
66
- try {
67
- if (track.isTargeted()) {
68
- targets.audio.push({ index: t, name: track.name });
69
- }
70
- } catch(e) {}
71
- }
72
-
73
- return __result(targets);
51
+ const script = buildToolScript(`
52
+ var seq = app.project.activeSequence;
53
+ if (!seq) return __error("No active sequence");
54
+
55
+ var targets = { video: [], audio: [] };
56
+ for (var t = 0; t < seq.videoTracks.numTracks; t++) {
57
+ var track = seq.videoTracks[t];
58
+ try {
59
+ if (track.isTargeted()) {
60
+ targets.video.push({ index: t, name: track.name });
61
+ }
62
+ } catch(e) {}
63
+ }
64
+ for (var t = 0; t < seq.audioTracks.numTracks; t++) {
65
+ var track = seq.audioTracks[t];
66
+ try {
67
+ if (track.isTargeted()) {
68
+ targets.audio.push({ index: t, name: track.name });
69
+ }
70
+ } catch(e) {}
71
+ }
72
+
73
+ return __result(targets);
74
74
  `);
75
75
  return sendCommand(script, bridgeOptions);
76
76
  },
@@ -94,23 +94,23 @@ export function getTrackTargetingTools(bridgeOptions) {
94
94
  },
95
95
  handler: async (args) => {
96
96
  const trackType = args.track_type || "both";
97
- const script = buildToolScript(`
98
- var seq = app.project.activeSequence;
99
- if (!seq) return __error("No active sequence");
100
-
101
- var count = 0;
102
- if ("${trackType}" !== "audio") {
103
- for (var t = 0; t < seq.videoTracks.numTracks; t++) {
104
- try { seq.videoTracks[t].setTargeted(${args.targeted}, true); count++; } catch(e) {}
105
- }
106
- }
107
- if ("${trackType}" !== "video") {
108
- for (var t = 0; t < seq.audioTracks.numTracks; t++) {
109
- try { seq.audioTracks[t].setTargeted(${args.targeted}, false); count++; } catch(e) {}
110
- }
111
- }
112
-
113
- return __result({ tracksAffected: count, targeted: ${args.targeted} });
97
+ const script = buildToolScript(`
98
+ var seq = app.project.activeSequence;
99
+ if (!seq) return __error("No active sequence");
100
+
101
+ var count = 0;
102
+ if ("${trackType}" !== "audio") {
103
+ for (var t = 0; t < seq.videoTracks.numTracks; t++) {
104
+ try { seq.videoTracks[t].setTargeted(${args.targeted}, true); count++; } catch(e) {}
105
+ }
106
+ }
107
+ if ("${trackType}" !== "video") {
108
+ for (var t = 0; t < seq.audioTracks.numTracks; t++) {
109
+ try { seq.audioTracks[t].setTargeted(${args.targeted}, false); count++; } catch(e) {}
110
+ }
111
+ }
112
+
113
+ return __result({ tracksAffected: count, targeted: ${args.targeted} });
114
114
  `);
115
115
  return sendCommand(script, bridgeOptions);
116
116
  },
@@ -137,18 +137,18 @@ export function getTrackTargetingTools(bridgeOptions) {
137
137
  required: ["track_type", "track_index", "name"],
138
138
  },
139
139
  handler: async (args) => {
140
- const script = buildToolScript(`
141
- var seq = app.project.activeSequence;
142
- if (!seq) return __error("No active sequence");
143
-
144
- var tracks = ${args.track_type === "video" ? "seq.videoTracks" : "seq.audioTracks"};
145
- if (${args.track_index} >= tracks.numTracks) return __error("Track index out of range");
146
-
147
- var track = tracks[${args.track_index}];
148
- var oldName = track.name;
149
- track.name = "${escapeForExtendScript(args.name)}";
150
-
151
- return __result({ oldName: oldName, newName: track.name, trackType: "${args.track_type}", trackIndex: ${args.track_index} });
140
+ const script = buildToolScript(`
141
+ var seq = app.project.activeSequence;
142
+ if (!seq) return __error("No active sequence");
143
+
144
+ var tracks = ${args.track_type === "video" ? "seq.videoTracks" : "seq.audioTracks"};
145
+ if (${args.track_index} >= tracks.numTracks) return __error("Track index out of range");
146
+
147
+ var track = tracks[${args.track_index}];
148
+ var oldName = track.name;
149
+ track.name = "${escapeForExtendScript(args.name)}";
150
+
151
+ return __result({ oldName: oldName, newName: track.name, trackType: "${args.track_type}", trackIndex: ${args.track_index} });
152
152
  `);
153
153
  return sendCommand(script, bridgeOptions);
154
154
  },
@@ -171,55 +171,55 @@ export function getTrackTargetingTools(bridgeOptions) {
171
171
  required: ["track_type", "track_index"],
172
172
  },
173
173
  handler: async (args) => {
174
- const script = buildToolScript(`
175
- var seq = app.project.activeSequence;
176
- if (!seq) return __error("No active sequence");
177
-
178
- var tracks = ${args.track_type === "video" ? "seq.videoTracks" : "seq.audioTracks"};
179
- if (${args.track_index} >= tracks.numTracks) return __error("Track index out of range");
180
-
181
- var track = tracks[${args.track_index}];
182
- var info = {
183
- name: track.name,
184
- trackType: "${args.track_type}",
185
- trackIndex: ${args.track_index},
186
- clipCount: track.clips.numItems,
187
- isMuted: track.isMuted(),
188
- isLocked: track.isLocked()
189
- };
190
- try { info.isTargeted = track.isTargeted(); } catch(e) {}
191
-
192
- info.clips = [];
193
- for (var c = 0; c < track.clips.numItems; c++) {
194
- var clip = track.clips[c];
195
- var ci = {
196
- index: c,
197
- nodeId: clip.nodeId,
198
- name: clip.name,
199
- startSeconds: __ticksToSeconds(clip.start.ticks),
200
- endSeconds: __ticksToSeconds(clip.end.ticks),
201
- durationSeconds: __ticksToSeconds(clip.duration.ticks)
202
- };
203
- var clipDisabled = __readMaybe(clip, "disabled", null);
204
- if (clipDisabled === null) clipDisabled = __readMaybe(clip, "isDisabled", false);
205
- ci.enabled = !clipDisabled;
206
- var clipSpeed = __readMaybe(clip, "getSpeed", null);
207
- if (clipSpeed !== null) ci.speed = clipSpeed;
208
- info.clips.push(ci);
209
- }
210
-
211
- info.transitions = [];
212
- try {
213
- for (var t = 0; t < track.transitions.numItems; t++) {
214
- info.transitions.push({
215
- index: t,
216
- startSeconds: __ticksToSeconds(track.transitions[t].start.ticks),
217
- endSeconds: __ticksToSeconds(track.transitions[t].end.ticks)
218
- });
219
- }
220
- } catch(e) {}
221
-
222
- return __result(info);
174
+ const script = buildToolScript(`
175
+ var seq = app.project.activeSequence;
176
+ if (!seq) return __error("No active sequence");
177
+
178
+ var tracks = ${args.track_type === "video" ? "seq.videoTracks" : "seq.audioTracks"};
179
+ if (${args.track_index} >= tracks.numTracks) return __error("Track index out of range");
180
+
181
+ var track = tracks[${args.track_index}];
182
+ var info = {
183
+ name: track.name,
184
+ trackType: "${args.track_type}",
185
+ trackIndex: ${args.track_index},
186
+ clipCount: track.clips.numItems,
187
+ isMuted: track.isMuted(),
188
+ isLocked: track.isLocked()
189
+ };
190
+ try { info.isTargeted = track.isTargeted(); } catch(e) {}
191
+
192
+ info.clips = [];
193
+ for (var c = 0; c < track.clips.numItems; c++) {
194
+ var clip = track.clips[c];
195
+ var ci = {
196
+ index: c,
197
+ nodeId: clip.nodeId,
198
+ name: clip.name,
199
+ startSeconds: __ticksToSeconds(clip.start.ticks),
200
+ endSeconds: __ticksToSeconds(clip.end.ticks),
201
+ durationSeconds: __ticksToSeconds(clip.duration.ticks)
202
+ };
203
+ var clipDisabled = __readMaybe(clip, "disabled", null);
204
+ if (clipDisabled === null) clipDisabled = __readMaybe(clip, "isDisabled", false);
205
+ ci.enabled = !clipDisabled;
206
+ var clipSpeed = __readMaybe(clip, "getSpeed", null);
207
+ if (clipSpeed !== null) ci.speed = clipSpeed;
208
+ info.clips.push(ci);
209
+ }
210
+
211
+ info.transitions = [];
212
+ try {
213
+ for (var t = 0; t < track.transitions.numItems; t++) {
214
+ info.transitions.push({
215
+ index: t,
216
+ startSeconds: __ticksToSeconds(track.transitions[t].start.ticks),
217
+ endSeconds: __ticksToSeconds(track.transitions[t].end.ticks)
218
+ });
219
+ }
220
+ } catch(e) {}
221
+
222
+ return __result(info);
223
223
  `);
224
224
  return sendCommand(script, bridgeOptions);
225
225
  },
@@ -242,35 +242,35 @@ export function getTrackTargetingTools(bridgeOptions) {
242
242
  },
243
243
  handler: async (args) => {
244
244
  const trackType = args.track_type || "both";
245
- const script = buildToolScript(`
246
- app.enableQE();
247
- var seq = app.project.activeSequence;
248
- if (!seq) return __error("No active sequence");
249
-
250
- var qeSeq = qe.project.getActiveSequence();
245
+ const script = buildToolScript(`
246
+ app.enableQE();
247
+ var seq = app.project.activeSequence;
248
+ if (!seq) return __error("No active sequence");
249
+
250
+ var qeSeq = qe.project.getActiveSequence();
251
251
  ${args.time_seconds !== undefined
252
252
  ? `var ticks = __secondsToTicks(${args.time_seconds}).toString();`
253
- : `var ticks = seq.getPlayerPosition().ticks;`}
254
-
255
- var razored = 0;
256
- if ("${trackType}" !== "audio") {
257
- for (var t = 0; t < seq.videoTracks.numTracks; t++) {
258
- try {
259
- qeSeq.getVideoTrackAt(t).razor(ticks);
260
- razored++;
261
- } catch(e) {}
262
- }
263
- }
264
- if ("${trackType}" !== "video") {
265
- for (var t = 0; t < seq.audioTracks.numTracks; t++) {
266
- try {
267
- qeSeq.getAudioTrackAt(t).razor(ticks);
268
- razored++;
269
- } catch(e) {}
270
- }
271
- }
272
-
273
- return __result({ razored: razored, atSeconds: __ticksToSeconds(ticks) });
253
+ : `var ticks = seq.getPlayerPosition().ticks;`}
254
+
255
+ var razored = 0;
256
+ if ("${trackType}" !== "audio") {
257
+ for (var t = 0; t < seq.videoTracks.numTracks; t++) {
258
+ try {
259
+ qeSeq.getVideoTrackAt(t).razor(ticks);
260
+ razored++;
261
+ } catch(e) {}
262
+ }
263
+ }
264
+ if ("${trackType}" !== "video") {
265
+ for (var t = 0; t < seq.audioTracks.numTracks; t++) {
266
+ try {
267
+ qeSeq.getAudioTrackAt(t).razor(ticks);
268
+ razored++;
269
+ } catch(e) {}
270
+ }
271
+ }
272
+
273
+ return __result({ razored: razored, atSeconds: __ticksToSeconds(ticks) });
274
274
  `);
275
275
  return sendCommand(script, bridgeOptions);
276
276
  },
@@ -292,15 +292,15 @@ export function getTrackTargetingTools(bridgeOptions) {
292
292
  required: ["item_id", "start_seconds"],
293
293
  },
294
294
  handler: async (args) => {
295
- const script = buildToolScript(`
296
- var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
297
- if (!item) return __error("Item not found");
298
-
299
- var t = new Time();
300
- t.seconds = ${args.start_seconds};
301
- item.setStartTime(t.ticks);
302
-
303
- return __result({ item: item.name, startSeconds: ${args.start_seconds} });
295
+ const script = buildToolScript(`
296
+ var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
297
+ if (!item) return __error("Item not found");
298
+
299
+ var t = new Time();
300
+ t.seconds = ${args.start_seconds};
301
+ item.setStartTime(t.ticks);
302
+
303
+ return __result({ item: item.name, startSeconds: ${args.start_seconds} });
304
304
  `);
305
305
  return sendCommand(script, bridgeOptions);
306
306
  },
@@ -328,14 +328,14 @@ export function getTrackTargetingTools(bridgeOptions) {
328
328
  handler: async (args) => {
329
329
  const clearIn = args.clear_in !== false;
330
330
  const clearOut = args.clear_out !== false;
331
- const script = buildToolScript(`
332
- var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
333
- if (!item) return __error("Item not found");
334
-
335
- ${clearIn ? `item.clearInPoint();` : ""}
336
- ${clearOut ? `item.clearOutPoint();` : ""}
337
-
338
- return __result({ item: item.name, clearedIn: ${clearIn}, clearedOut: ${clearOut} });
331
+ const script = buildToolScript(`
332
+ var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
333
+ if (!item) return __error("Item not found");
334
+
335
+ ${clearIn ? `item.clearInPoint();` : ""}
336
+ ${clearOut ? `item.clearOutPoint();` : ""}
337
+
338
+ return __result({ item: item.name, clearedIn: ${clearIn}, clearedOut: ${clearOut} });
339
339
  `);
340
340
  return sendCommand(script, bridgeOptions);
341
341
  },
@@ -366,23 +366,23 @@ export function getTrackTargetingTools(bridgeOptions) {
366
366
  },
367
367
  handler: async (args) => {
368
368
  const mediaType = args.media_type ?? 4;
369
- const script = buildToolScript(`
370
- var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
371
- if (!item) return __error("Item not found");
372
-
373
- ${args.in_seconds !== undefined ? `
374
- var inTime = new Time();
375
- inTime.seconds = ${args.in_seconds};
376
- item.setInPoint(inTime.ticks, ${mediaType});
377
- ` : ""}
378
-
379
- ${args.out_seconds !== undefined ? `
380
- var outTime = new Time();
381
- outTime.seconds = ${args.out_seconds};
382
- item.setOutPoint(outTime.ticks, ${mediaType});
383
- ` : ""}
384
-
385
- return __result({ item: item.name, inSet: ${args.in_seconds !== undefined}, outSet: ${args.out_seconds !== undefined} });
369
+ const script = buildToolScript(`
370
+ var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
371
+ if (!item) return __error("Item not found");
372
+
373
+ ${args.in_seconds !== undefined ? `
374
+ var inTime = new Time();
375
+ inTime.seconds = ${args.in_seconds};
376
+ item.setInPoint(inTime.ticks, ${mediaType});
377
+ ` : ""}
378
+
379
+ ${args.out_seconds !== undefined ? `
380
+ var outTime = new Time();
381
+ outTime.seconds = ${args.out_seconds};
382
+ item.setOutPoint(outTime.ticks, ${mediaType});
383
+ ` : ""}
384
+
385
+ return __result({ item: item.name, inSet: ${args.in_seconds !== undefined}, outSet: ${args.out_seconds !== undefined} });
386
386
  `);
387
387
  return sendCommand(script, bridgeOptions);
388
388
  },
@@ -404,16 +404,16 @@ export function getTrackTargetingTools(bridgeOptions) {
404
404
  required: ["first_file_path"],
405
405
  },
406
406
  handler: async (args) => {
407
- const script = buildToolScript(`
408
- var targetBin = app.project.rootItem;
409
- ${args.target_bin ? `
410
- var found = __findProjectItem("${escapeForExtendScript(args.target_bin)}");
411
- if (found && found.type === 2) targetBin = found;
412
- ` : ""}
413
-
414
- app.project.importFiles(["${escapeForExtendScript(args.first_file_path)}"], true, targetBin, true);
415
-
416
- return __result({ imported: true, file: "${escapeForExtendScript(args.first_file_path)}", asImageSequence: true });
407
+ const script = buildToolScript(`
408
+ var targetBin = app.project.rootItem;
409
+ ${args.target_bin ? `
410
+ var found = __findProjectItem("${escapeForExtendScript(args.target_bin)}");
411
+ if (found && found.type === 2) targetBin = found;
412
+ ` : ""}
413
+
414
+ app.project.importFiles(["${escapeForExtendScript(args.first_file_path)}"], true, targetBin, true);
415
+
416
+ return __result({ imported: true, file: "${escapeForExtendScript(args.first_file_path)}", asImageSequence: true });
417
417
  `);
418
418
  return sendCommand(script, bridgeOptions);
419
419
  },
@@ -439,17 +439,17 @@ export function getTrackTargetingTools(bridgeOptions) {
439
439
  required: ["node_id", "x", "y"],
440
440
  },
441
441
  handler: async (args) => {
442
- const script = buildToolScript(`
443
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
444
- if (!result) return __error("Clip not found");
445
-
446
- var clip = result.clip;
447
- var motion = __findIntrinsic(clip, "motion");
448
- if (!motion) return __error("Motion component not found on clip");
449
- var posProp = __findProp(motion, ["Position", "Posición"]);
450
- if (!posProp) return __error("Position property not found in Motion");
451
- posProp.setValue([${args.x}, ${args.y}], true);
452
- return __result({ x: ${args.x}, y: ${args.y}, clip: clip.name });
442
+ const script = buildToolScript(`
443
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
444
+ if (!result) return __error("Clip not found");
445
+
446
+ var clip = result.clip;
447
+ var motion = __findIntrinsic(clip, "motion");
448
+ if (!motion) return __error("Motion component not found on clip");
449
+ var posProp = __findProp(motion, ["Position", "Posición"]);
450
+ if (!posProp) return __error("Position property not found in Motion");
451
+ posProp.setValue([${args.x}, ${args.y}], true);
452
+ return __result({ x: ${args.x}, y: ${args.y}, clip: clip.name });
453
453
  `);
454
454
  return sendCommand(script, bridgeOptions);
455
455
  },
@@ -471,17 +471,17 @@ export function getTrackTargetingTools(bridgeOptions) {
471
471
  required: ["node_id", "scale"],
472
472
  },
473
473
  handler: async (args) => {
474
- const script = buildToolScript(`
475
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
476
- if (!result) return __error("Clip not found");
477
-
478
- var clip = result.clip;
479
- var motion = __findIntrinsic(clip, "motion");
480
- if (!motion) return __error("Motion component not found on clip");
481
- var scaleProp = __findProp(motion, ["Scale", "Escala", "Skalierung", "Échelle"]);
482
- if (!scaleProp) return __error("Scale property not found in Motion");
483
- scaleProp.setValue(${args.scale}, true);
484
- return __result({ scale: ${args.scale}, clip: clip.name });
474
+ const script = buildToolScript(`
475
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
476
+ if (!result) return __error("Clip not found");
477
+
478
+ var clip = result.clip;
479
+ var motion = __findIntrinsic(clip, "motion");
480
+ if (!motion) return __error("Motion component not found on clip");
481
+ var scaleProp = __findProp(motion, ["Scale", "Escala", "Skalierung", "Échelle"]);
482
+ if (!scaleProp) return __error("Scale property not found in Motion");
483
+ scaleProp.setValue(${args.scale}, true);
484
+ return __result({ scale: ${args.scale}, clip: clip.name });
485
485
  `);
486
486
  return sendCommand(script, bridgeOptions);
487
487
  },
@@ -503,17 +503,17 @@ export function getTrackTargetingTools(bridgeOptions) {
503
503
  required: ["node_id", "degrees"],
504
504
  },
505
505
  handler: async (args) => {
506
- const script = buildToolScript(`
507
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
508
- if (!result) return __error("Clip not found");
509
-
510
- var clip = result.clip;
511
- var motion = __findIntrinsic(clip, "motion");
512
- if (!motion) return __error("Motion component not found on clip");
513
- var rotProp = __findProp(motion, ["Rotation", "Rotación", "Drehung"]);
514
- if (!rotProp) return __error("Rotation property not found in Motion");
515
- rotProp.setValue(${args.degrees}, true);
516
- return __result({ degrees: ${args.degrees}, clip: clip.name });
506
+ const script = buildToolScript(`
507
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
508
+ if (!result) return __error("Clip not found");
509
+
510
+ var clip = result.clip;
511
+ var motion = __findIntrinsic(clip, "motion");
512
+ if (!motion) return __error("Motion component not found on clip");
513
+ var rotProp = __findProp(motion, ["Rotation", "Rotación", "Drehung"]);
514
+ if (!rotProp) return __error("Rotation property not found in Motion");
515
+ rotProp.setValue(${args.degrees}, true);
516
+ return __result({ degrees: ${args.degrees}, clip: clip.name });
517
517
  `);
518
518
  return sendCommand(script, bridgeOptions);
519
519
  },
@@ -539,26 +539,26 @@ export function getTrackTargetingTools(bridgeOptions) {
539
539
  required: ["node_id", "x", "y"],
540
540
  },
541
541
  handler: async (args) => {
542
- const script = buildToolScript(`
543
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
544
- if (!result) return __error("Clip not found");
545
-
546
- var clip = result.clip;
547
- var set = false;
548
- for (var i = 0; i < clip.components.numItems; i++) {
549
- if (clip.components[i].displayName === "Motion") {
550
- for (var p = 0; p < clip.components[i].properties.numItems; p++) {
551
- if (clip.components[i].properties[p].displayName === "Anchor Point") {
552
- clip.components[i].properties[p].setValue([${args.x}, ${args.y}], true);
553
- set = true;
554
- break;
555
- }
556
- }
557
- break;
558
- }
559
- }
560
- if (!set) return __error("Could not set anchor point");
561
- return __result({ x: ${args.x}, y: ${args.y}, clip: clip.name });
542
+ const script = buildToolScript(`
543
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
544
+ if (!result) return __error("Clip not found");
545
+
546
+ var clip = result.clip;
547
+ var set = false;
548
+ for (var i = 0; i < clip.components.numItems; i++) {
549
+ if (clip.components[i].displayName === "Motion") {
550
+ for (var p = 0; p < clip.components[i].properties.numItems; p++) {
551
+ if (clip.components[i].properties[p].displayName === "Anchor Point") {
552
+ clip.components[i].properties[p].setValue([${args.x}, ${args.y}], true);
553
+ set = true;
554
+ break;
555
+ }
556
+ }
557
+ break;
558
+ }
559
+ }
560
+ if (!set) return __error("Could not set anchor point");
561
+ return __result({ x: ${args.x}, y: ${args.y}, clip: clip.name });
562
562
  `);
563
563
  return sendCommand(script, bridgeOptions);
564
564
  },
@@ -580,20 +580,20 @@ export function getTrackTargetingTools(bridgeOptions) {
580
580
  required: ["node_id", "opacity"],
581
581
  },
582
582
  handler: async (args) => {
583
- const script = buildToolScript(`
584
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
585
- if (!result) return __error("Clip not found");
586
-
587
- var clip = result.clip;
588
- // Locale-resilient lookup via __findIntrinsic (matchName first, then
589
- // localized displayName fallbacks). The Opacity property itself is
590
- // also localized (Opacidad / Opazität / Opacité).
591
- var opComp = __findIntrinsic(clip, "opacity");
592
- if (!opComp) return __error("Opacity component not found on clip");
593
- var opProp = __findProp(opComp, ["Opacity", "Opacidad", "Deckkraft", "Opacité"]);
594
- if (!opProp) return __error("Opacity property not found in Opacity component");
595
- opProp.setValue(${args.opacity}, true);
596
- return __result({ opacity: ${args.opacity}, clip: clip.name });
583
+ const script = buildToolScript(`
584
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
585
+ if (!result) return __error("Clip not found");
586
+
587
+ var clip = result.clip;
588
+ // Locale-resilient lookup via __findIntrinsic (matchName first, then
589
+ // localized displayName fallbacks). The Opacity property itself is
590
+ // also localized (Opacidad / Opazität / Opacité).
591
+ var opComp = __findIntrinsic(clip, "opacity");
592
+ if (!opComp) return __error("Opacity component not found on clip");
593
+ var opProp = __findProp(opComp, ["Opacity", "Opacidad", "Deckkraft", "Opacité"]);
594
+ if (!opProp) return __error("Opacity property not found in Opacity component");
595
+ opProp.setValue(${args.opacity}, true);
596
+ return __result({ opacity: ${args.opacity}, clip: clip.name });
597
597
  `);
598
598
  return sendCommand(script, bridgeOptions);
599
599
  },
@@ -615,26 +615,26 @@ export function getTrackTargetingTools(bridgeOptions) {
615
615
  required: ["node_id", "volume_db"],
616
616
  },
617
617
  handler: async (args) => {
618
- const script = buildToolScript(`
619
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
620
- if (!result) return __error("Clip not found");
621
-
622
- var clip = result.clip;
623
- var set = false;
624
- for (var i = 0; i < clip.components.numItems; i++) {
625
- if (clip.components[i].displayName === "Volume") {
626
- for (var p = 0; p < clip.components[i].properties.numItems; p++) {
627
- if (clip.components[i].properties[p].displayName === "Level") {
628
- clip.components[i].properties[p].setValue(${args.volume_db}, true);
629
- set = true;
630
- break;
631
- }
632
- }
633
- break;
634
- }
635
- }
636
- if (!set) return __error("Could not set volume - is this an audio clip?");
637
- return __result({ volumeDb: ${args.volume_db}, clip: clip.name });
618
+ const script = buildToolScript(`
619
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
620
+ if (!result) return __error("Clip not found");
621
+
622
+ var clip = result.clip;
623
+ var set = false;
624
+ for (var i = 0; i < clip.components.numItems; i++) {
625
+ if (clip.components[i].displayName === "Volume") {
626
+ for (var p = 0; p < clip.components[i].properties.numItems; p++) {
627
+ if (clip.components[i].properties[p].displayName === "Level") {
628
+ clip.components[i].properties[p].setValue(${args.volume_db}, true);
629
+ set = true;
630
+ break;
631
+ }
632
+ }
633
+ break;
634
+ }
635
+ }
636
+ if (!set) return __error("Could not set volume - is this an audio clip?");
637
+ return __result({ volumeDb: ${args.volume_db}, clip: clip.name });
638
638
  `);
639
639
  return sendCommand(script, bridgeOptions);
640
640
  },
@@ -656,26 +656,26 @@ export function getTrackTargetingTools(bridgeOptions) {
656
656
  required: ["node_id", "pan"],
657
657
  },
658
658
  handler: async (args) => {
659
- const script = buildToolScript(`
660
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
661
- if (!result) return __error("Clip not found");
662
-
663
- var clip = result.clip;
664
- var set = false;
665
- for (var i = 0; i < clip.components.numItems; i++) {
666
- if (clip.components[i].displayName === "Panner") {
667
- for (var p = 0; p < clip.components[i].properties.numItems; p++) {
668
- if (clip.components[i].properties[p].displayName === "Balance" || clip.components[i].properties[p].displayName === "Pan") {
669
- clip.components[i].properties[p].setValue(${args.pan}, true);
670
- set = true;
671
- break;
672
- }
673
- }
674
- break;
675
- }
676
- }
677
- if (!set) return __error("Could not set pan - is this an audio clip?");
678
- return __result({ pan: ${args.pan}, clip: clip.name });
659
+ const script = buildToolScript(`
660
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
661
+ if (!result) return __error("Clip not found");
662
+
663
+ var clip = result.clip;
664
+ var set = false;
665
+ for (var i = 0; i < clip.components.numItems; i++) {
666
+ if (clip.components[i].displayName === "Panner") {
667
+ for (var p = 0; p < clip.components[i].properties.numItems; p++) {
668
+ if (clip.components[i].properties[p].displayName === "Balance" || clip.components[i].properties[p].displayName === "Pan") {
669
+ clip.components[i].properties[p].setValue(${args.pan}, true);
670
+ set = true;
671
+ break;
672
+ }
673
+ }
674
+ break;
675
+ }
676
+ }
677
+ if (!set) return __error("Could not set pan - is this an audio clip?");
678
+ return __result({ pan: ${args.pan}, clip: clip.name });
679
679
  `);
680
680
  return sendCommand(script, bridgeOptions);
681
681
  },
@@ -711,38 +711,38 @@ export function getTrackTargetingTools(bridgeOptions) {
711
711
  },
712
712
  handler: async (args) => {
713
713
  const startNum = args.start_number ?? 1;
714
- const script = buildToolScript(`
715
- app.enableQE();
716
- var seq = app.project.activeSequence;
717
- if (!seq) return __error("No active sequence");
718
-
719
- var tracks = ${args.track_type === "video" ? "seq.videoTracks" : "seq.audioTracks"};
720
- if (${args.track_index} >= tracks.numTracks) return __error("Track index out of range");
721
-
722
- var qeSeq = qe.project.getActiveSequence();
714
+ const script = buildToolScript(`
715
+ app.enableQE();
716
+ var seq = app.project.activeSequence;
717
+ if (!seq) return __error("No active sequence");
718
+
719
+ var tracks = ${args.track_type === "video" ? "seq.videoTracks" : "seq.audioTracks"};
720
+ if (${args.track_index} >= tracks.numTracks) return __error("Track index out of range");
721
+
722
+ var qeSeq = qe.project.getActiveSequence();
723
723
  var qeTrack = ${args.track_type === "video"
724
724
  ? `qeSeq.getVideoTrackAt(${args.track_index})`
725
- : `qeSeq.getAudioTrackAt(${args.track_index})`};
726
-
727
- var track = tracks[${args.track_index}];
728
- var renamed = 0;
729
- var num = ${startNum};
730
- var pattern = "${escapeForExtendScript(args.pattern)}";
731
-
732
- for (var c = 0; c < track.clips.numItems; c++) {
733
- var clip = track.clips[c];
734
- ${args.selected_only ? `if (!clip.isSelected()) continue;` : ""}
735
-
736
- var newName = pattern.split("{n}").join("" + num).split("{name}").join(clip.name);
737
- try {
738
- var qeClip = qeTrack.getItemAt(c);
739
- qeClip.setName(newName);
740
- renamed++;
741
- } catch(e) {}
742
- num++;
743
- }
744
-
745
- return __result({ renamed: renamed, pattern: pattern });
725
+ : `qeSeq.getAudioTrackAt(${args.track_index})`};
726
+
727
+ var track = tracks[${args.track_index}];
728
+ var renamed = 0;
729
+ var num = ${startNum};
730
+ var pattern = "${escapeForExtendScript(args.pattern)}";
731
+
732
+ for (var c = 0; c < track.clips.numItems; c++) {
733
+ var clip = track.clips[c];
734
+ ${args.selected_only ? `if (!clip.isSelected()) continue;` : ""}
735
+
736
+ var newName = pattern.split("{n}").join("" + num).split("{name}").join(clip.name);
737
+ try {
738
+ var qeClip = qeTrack.getItemAt(c);
739
+ qeClip.setName(newName);
740
+ renamed++;
741
+ } catch(e) {}
742
+ num++;
743
+ }
744
+
745
+ return __result({ renamed: renamed, pattern: pattern });
746
746
  `);
747
747
  return sendCommand(script, bridgeOptions);
748
748
  },
@@ -774,33 +774,33 @@ export function getTrackTargetingTools(bridgeOptions) {
774
774
  required: ["enabled", "target"],
775
775
  },
776
776
  handler: async (args) => {
777
- const script = buildToolScript(`
778
- var seq = app.project.activeSequence;
779
- if (!seq) return __error("No active sequence");
780
-
781
- var count = 0;
782
- var disabled = ${!args.enabled};
783
-
784
- function setOnTrack(track) {
785
- for (var c = 0; c < track.clips.numItems; c++) {
786
- try {
787
- if ("${args.target}" === "selected" && !track.clips[c].isSelected()) continue;
788
- track.clips[c].setDisabled(disabled);
789
- count++;
790
- } catch(e) {}
791
- }
792
- }
793
-
794
- if ("${args.target}" === "track") {
795
- var tracks = ${(args.track_type || "video") === "video" ? "seq.videoTracks" : "seq.audioTracks"};
796
- if (${args.track_index ?? 0} >= tracks.numTracks) return __error("Track index out of range");
797
- setOnTrack(tracks[${args.track_index ?? 0}]);
798
- } else {
799
- for (var t = 0; t < seq.videoTracks.numTracks; t++) setOnTrack(seq.videoTracks[t]);
800
- for (var t = 0; t < seq.audioTracks.numTracks; t++) setOnTrack(seq.audioTracks[t]);
801
- }
802
-
803
- return __result({ affected: count, enabled: ${args.enabled} });
777
+ const script = buildToolScript(`
778
+ var seq = app.project.activeSequence;
779
+ if (!seq) return __error("No active sequence");
780
+
781
+ var count = 0;
782
+ var disabled = ${!args.enabled};
783
+
784
+ function setOnTrack(track) {
785
+ for (var c = 0; c < track.clips.numItems; c++) {
786
+ try {
787
+ if ("${args.target}" === "selected" && !track.clips[c].isSelected()) continue;
788
+ track.clips[c].setDisabled(disabled);
789
+ count++;
790
+ } catch(e) {}
791
+ }
792
+ }
793
+
794
+ if ("${args.target}" === "track") {
795
+ var tracks = ${(args.track_type || "video") === "video" ? "seq.videoTracks" : "seq.audioTracks"};
796
+ if (${args.track_index ?? 0} >= tracks.numTracks) return __error("Track index out of range");
797
+ setOnTrack(tracks[${args.track_index ?? 0}]);
798
+ } else {
799
+ for (var t = 0; t < seq.videoTracks.numTracks; t++) setOnTrack(seq.videoTracks[t]);
800
+ for (var t = 0; t < seq.audioTracks.numTracks; t++) setOnTrack(seq.audioTracks[t]);
801
+ }
802
+
803
+ return __result({ affected: count, enabled: ${args.enabled} });
804
804
  `);
805
805
  return sendCommand(script, bridgeOptions);
806
806
  },
@@ -817,33 +817,33 @@ export function getTrackTargetingTools(bridgeOptions) {
817
817
  },
818
818
  },
819
819
  handler: async (args) => {
820
- const script = buildToolScript(`
821
- var seq = app.project.activeSequence;
822
- if (!seq) return __error("No active sequence");
823
-
824
- var removed = 0;
825
- var toRemove = [];
826
-
827
- function collect(tracks) {
828
- for (var t = 0; t < tracks.numTracks; t++) {
829
- for (var c = tracks[t].clips.numItems - 1; c >= 0; c--) {
830
- if (tracks[t].clips[c].isSelected()) {
831
- toRemove.push(tracks[t].clips[c]);
832
- }
833
- }
834
- }
835
- }
836
- collect(seq.videoTracks);
837
- collect(seq.audioTracks);
838
-
839
- for (var i = 0; i < toRemove.length; i++) {
840
- try {
841
- toRemove[i].remove(${args.ripple ? "true" : "false"}, true);
842
- removed++;
843
- } catch(e) {}
844
- }
845
-
846
- return __result({ removed: removed, ripple: ${args.ripple ? "true" : "false"} });
820
+ const script = buildToolScript(`
821
+ var seq = app.project.activeSequence;
822
+ if (!seq) return __error("No active sequence");
823
+
824
+ var removed = 0;
825
+ var toRemove = [];
826
+
827
+ function collect(tracks) {
828
+ for (var t = 0; t < tracks.numTracks; t++) {
829
+ for (var c = tracks[t].clips.numItems - 1; c >= 0; c--) {
830
+ if (tracks[t].clips[c].isSelected()) {
831
+ toRemove.push(tracks[t].clips[c]);
832
+ }
833
+ }
834
+ }
835
+ }
836
+ collect(seq.videoTracks);
837
+ collect(seq.audioTracks);
838
+
839
+ for (var i = 0; i < toRemove.length; i++) {
840
+ try {
841
+ toRemove[i].remove(${args.ripple ? "true" : "false"}, true);
842
+ removed++;
843
+ } catch(e) {}
844
+ }
845
+
846
+ return __result({ removed: removed, ripple: ${args.ripple ? "true" : "false"} });
847
847
  `);
848
848
  return sendCommand(script, bridgeOptions);
849
849
  },
@@ -866,64 +866,64 @@ export function getTrackTargetingTools(bridgeOptions) {
866
866
  handler: async (args) => {
867
867
  const clearIn = args.clear_in !== false;
868
868
  const clearOut = args.clear_out !== false;
869
- const script = buildToolScript(`
870
- var seq = app.project.activeSequence;
871
- if (!seq) return __error("No active sequence");
872
-
873
- var clearIn = ${clearIn};
874
- var clearOut = ${clearOut};
875
- var inDone = false;
876
- var outDone = false;
877
- var usedDedicated = false;
878
- var errMsg = null;
879
-
880
- // Prefer a dedicated clear method if it exists (clears both at once).
881
- if (clearIn && clearOut) {
882
- try {
883
- if (typeof seq.clearInOutPoints === "function") {
884
- seq.clearInOutPoints();
885
- usedDedicated = true;
886
- inDone = true;
887
- outDone = true;
888
- }
889
- } catch(eClear) { errMsg = "clearInOutPoints: " + eClear.toString(); usedDedicated = false; }
890
- }
891
-
892
- if (!usedDedicated) {
893
- // setInPoint/setOutPoint expect ticks as a STRING. Resolve both as
894
- // ticks strings so the two calls are consistent.
895
- var zeroTicks = "0";
896
- try {
897
- if (seq.zeroPoint && seq.zeroPoint.ticks) zeroTicks = seq.zeroPoint.ticks.toString();
898
- } catch(eZero) {}
899
-
900
- var endTicks = null;
901
- try {
902
- if (seq.end && seq.end.ticks) endTicks = seq.end.ticks.toString();
903
- } catch(eEnd) {}
904
-
905
- if (clearIn) {
906
- try {
907
- seq.setInPoint(zeroTicks);
908
- inDone = true;
909
- } catch(eIn) { errMsg = (errMsg ? errMsg + "; " : "") + "in: " + eIn.toString(); }
910
- }
911
-
912
- if (clearOut && endTicks !== null) {
913
- try {
914
- seq.setOutPoint(endTicks);
915
- outDone = true;
916
- } catch(eOut) { errMsg = (errMsg ? errMsg + "; " : "") + "out: " + eOut.toString(); }
917
- }
918
- }
919
-
920
- return __result({
921
- success: ((!clearIn || inDone) && (!clearOut || outDone)),
922
- clearedIn: inDone,
923
- clearedOut: outDone,
924
- usedDedicatedMethod: usedDedicated,
925
- error: errMsg
926
- });
869
+ const script = buildToolScript(`
870
+ var seq = app.project.activeSequence;
871
+ if (!seq) return __error("No active sequence");
872
+
873
+ var clearIn = ${clearIn};
874
+ var clearOut = ${clearOut};
875
+ var inDone = false;
876
+ var outDone = false;
877
+ var usedDedicated = false;
878
+ var errMsg = null;
879
+
880
+ // Prefer a dedicated clear method if it exists (clears both at once).
881
+ if (clearIn && clearOut) {
882
+ try {
883
+ if (typeof seq.clearInOutPoints === "function") {
884
+ seq.clearInOutPoints();
885
+ usedDedicated = true;
886
+ inDone = true;
887
+ outDone = true;
888
+ }
889
+ } catch(eClear) { errMsg = "clearInOutPoints: " + eClear.toString(); usedDedicated = false; }
890
+ }
891
+
892
+ if (!usedDedicated) {
893
+ // setInPoint/setOutPoint expect ticks as a STRING. Resolve both as
894
+ // ticks strings so the two calls are consistent.
895
+ var zeroTicks = "0";
896
+ try {
897
+ if (seq.zeroPoint && seq.zeroPoint.ticks) zeroTicks = seq.zeroPoint.ticks.toString();
898
+ } catch(eZero) {}
899
+
900
+ var endTicks = null;
901
+ try {
902
+ if (seq.end && seq.end.ticks) endTicks = seq.end.ticks.toString();
903
+ } catch(eEnd) {}
904
+
905
+ if (clearIn) {
906
+ try {
907
+ seq.setInPoint(zeroTicks);
908
+ inDone = true;
909
+ } catch(eIn) { errMsg = (errMsg ? errMsg + "; " : "") + "in: " + eIn.toString(); }
910
+ }
911
+
912
+ if (clearOut && endTicks !== null) {
913
+ try {
914
+ seq.setOutPoint(endTicks);
915
+ outDone = true;
916
+ } catch(eOut) { errMsg = (errMsg ? errMsg + "; " : "") + "out: " + eOut.toString(); }
917
+ }
918
+ }
919
+
920
+ return __result({
921
+ success: ((!clearIn || inDone) && (!clearOut || outDone)),
922
+ clearedIn: inDone,
923
+ clearedOut: outDone,
924
+ usedDedicatedMethod: usedDedicated,
925
+ error: errMsg
926
+ });
927
927
  `);
928
928
  return sendCommand(script, bridgeOptions);
929
929
  },
@@ -940,31 +940,31 @@ export function getTrackTargetingTools(bridgeOptions) {
940
940
  },
941
941
  },
942
942
  handler: async (args) => {
943
- const script = buildToolScript(`
944
- var encoder = app.encoder;
945
- if (!encoder) return __error("Encoder not available");
946
-
947
- try {
948
- var formats = encoder.getFormatList();
949
- if (!formats) return __error("Could not get format list");
950
-
951
- var result = [];
952
- for (var f = 0; f < formats.length; f++) {
953
- var formatName = formats[f];
954
- ${args.format ? `if (formatName.toLowerCase().indexOf("${escapeForExtendScript(args.format)}".toLowerCase()) === -1) continue;` : ""}
955
- var presets = encoder.getPresetList(formatName);
956
- var presetNames = [];
957
- if (presets) {
958
- for (var p = 0; p < presets.length; p++) {
959
- presetNames.push(presets[p]);
960
- }
961
- }
962
- result.push({ format: formatName, presets: presetNames });
963
- }
964
- return __result(result);
965
- } catch(e) {
966
- return __error("Encoder preset listing failed: " + e.message);
967
- }
943
+ const script = buildToolScript(`
944
+ var encoder = app.encoder;
945
+ if (!encoder) return __error("Encoder not available");
946
+
947
+ try {
948
+ var formats = encoder.getFormatList();
949
+ if (!formats) return __error("Could not get format list");
950
+
951
+ var result = [];
952
+ for (var f = 0; f < formats.length; f++) {
953
+ var formatName = formats[f];
954
+ ${args.format ? `if (formatName.toLowerCase().indexOf("${escapeForExtendScript(args.format)}".toLowerCase()) === -1) continue;` : ""}
955
+ var presets = encoder.getPresetList(formatName);
956
+ var presetNames = [];
957
+ if (presets) {
958
+ for (var p = 0; p < presets.length; p++) {
959
+ presetNames.push(presets[p]);
960
+ }
961
+ }
962
+ result.push({ format: formatName, presets: presetNames });
963
+ }
964
+ return __result(result);
965
+ } catch(e) {
966
+ return __error("Encoder preset listing failed: " + e.message);
967
+ }
968
968
  `);
969
969
  return sendCommand(script, bridgeOptions);
970
970
  },
@@ -991,51 +991,51 @@ export function getTrackTargetingTools(bridgeOptions) {
991
991
  required: ["track_type", "track_index", "clip_index"],
992
992
  },
993
993
  handler: async (args) => {
994
- const script = buildToolScript(`
995
- app.enableQE();
996
- var qeSeq = qe.project.getActiveSequence();
997
- if (!qeSeq) return __error("No active sequence");
998
-
994
+ const script = buildToolScript(`
995
+ app.enableQE();
996
+ var qeSeq = qe.project.getActiveSequence();
997
+ if (!qeSeq) return __error("No active sequence");
998
+
999
999
  var qeTrack = ${args.track_type === "video"
1000
1000
  ? `qeSeq.getVideoTrackAt(${args.track_index})`
1001
- : `qeSeq.getAudioTrackAt(${args.track_index})`};
1002
- if (!qeTrack) return __error("Track not found");
1003
-
1004
- var qeClip = qeTrack.getItemAt(${args.clip_index});
1005
- if (!qeClip) return __error("Clip not found at index ${args.clip_index}");
1006
-
1007
- var info = { trackType: "${args.track_type}", trackIndex: ${args.track_index}, clipIndex: ${args.clip_index} };
1008
-
1009
- // Try to read all QE clip properties
1010
- var props = ["name", "type", "mediaType", "duration", "start", "end", "inPoint", "outPoint",
1011
- "speed", "audioChannelType", "numAudioChannels"];
1012
- for (var i = 0; i < props.length; i++) {
1013
- try { info[props[i]] = qeClip[props[i]]; } catch(e) {}
1014
- }
1015
-
1016
- // Enumerate any additional properties
1017
- var extra = [];
1018
- try {
1019
- for (var key in qeClip) {
1020
- if (typeof qeClip[key] !== "function") {
1021
- extra.push(key);
1022
- }
1023
- }
1024
- } catch(e) {}
1025
- info.availableProperties = extra;
1026
-
1027
- // Enumerate methods
1028
- var methods = [];
1029
- try {
1030
- for (var key in qeClip) {
1031
- if (typeof qeClip[key] === "function") {
1032
- methods.push(key);
1033
- }
1034
- }
1035
- } catch(e) {}
1036
- info.availableMethods = methods;
1037
-
1038
- return __result(info);
1001
+ : `qeSeq.getAudioTrackAt(${args.track_index})`};
1002
+ if (!qeTrack) return __error("Track not found");
1003
+
1004
+ var qeClip = qeTrack.getItemAt(${args.clip_index});
1005
+ if (!qeClip) return __error("Clip not found at index ${args.clip_index}");
1006
+
1007
+ var info = { trackType: "${args.track_type}", trackIndex: ${args.track_index}, clipIndex: ${args.clip_index} };
1008
+
1009
+ // Try to read all QE clip properties
1010
+ var props = ["name", "type", "mediaType", "duration", "start", "end", "inPoint", "outPoint",
1011
+ "speed", "audioChannelType", "numAudioChannels"];
1012
+ for (var i = 0; i < props.length; i++) {
1013
+ try { info[props[i]] = qeClip[props[i]]; } catch(e) {}
1014
+ }
1015
+
1016
+ // Enumerate any additional properties
1017
+ var extra = [];
1018
+ try {
1019
+ for (var key in qeClip) {
1020
+ if (typeof qeClip[key] !== "function") {
1021
+ extra.push(key);
1022
+ }
1023
+ }
1024
+ } catch(e) {}
1025
+ info.availableProperties = extra;
1026
+
1027
+ // Enumerate methods
1028
+ var methods = [];
1029
+ try {
1030
+ for (var key in qeClip) {
1031
+ if (typeof qeClip[key] === "function") {
1032
+ methods.push(key);
1033
+ }
1034
+ }
1035
+ } catch(e) {}
1036
+ info.availableMethods = methods;
1037
+
1038
+ return __result(info);
1039
1039
  `);
1040
1040
  return sendCommand(script, bridgeOptions);
1041
1041
  },
@@ -1044,14 +1044,14 @@ export function getTrackTargetingTools(bridgeOptions) {
1044
1044
  description: "Redo the last undone action in Premiere Pro.",
1045
1045
  parameters: {},
1046
1046
  handler: async () => {
1047
- const script = buildToolScript(`
1048
- app.enableQE();
1049
- try {
1050
- qe.project.redo();
1051
- return __result({ redone: true });
1052
- } catch(e) {
1053
- return __error("Redo failed: " + e.message);
1054
- }
1047
+ const script = buildToolScript(`
1048
+ app.enableQE();
1049
+ try {
1050
+ qe.project.redo();
1051
+ return __result({ redone: true });
1052
+ } catch(e) {
1053
+ return __error("Redo failed: " + e.message);
1054
+ }
1055
1055
  `);
1056
1056
  return sendCommand(script, bridgeOptions);
1057
1057
  },
@@ -1069,15 +1069,15 @@ export function getTrackTargetingTools(bridgeOptions) {
1069
1069
  },
1070
1070
  handler: async (args) => {
1071
1071
  const count = args.count ?? 1;
1072
- const script = buildToolScript(`
1073
- var undone = 0;
1074
- for (var i = 0; i < ${count}; i++) {
1075
- try {
1076
- app.project.undo();
1077
- undone++;
1078
- } catch(e) { break; }
1079
- }
1080
- return __result({ undone: undone });
1072
+ const script = buildToolScript(`
1073
+ var undone = 0;
1074
+ for (var i = 0; i < ${count}; i++) {
1075
+ try {
1076
+ app.project.undo();
1077
+ undone++;
1078
+ } catch(e) { break; }
1079
+ }
1080
+ return __result({ undone: undone });
1081
1081
  `);
1082
1082
  return sendCommand(script, bridgeOptions);
1083
1083
  },
@@ -1099,26 +1099,26 @@ export function getTrackTargetingTools(bridgeOptions) {
1099
1099
  required: ["item_id", "time_seconds"],
1100
1100
  },
1101
1101
  handler: async (args) => {
1102
- const script = buildToolScript(`
1103
- var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
1104
- if (!item) {
1105
- // Fall back to treating item_id as a timeline clip node id
1106
- var res = __findClip("${escapeForExtendScript(args.item_id)}");
1107
- if (res && res.clip && res.clip.projectItem) item = res.clip.projectItem;
1108
- }
1109
- if (!item) return __error("Item not found");
1110
-
1111
- if (typeof item.setPosterFrame !== "function") {
1112
- return __error("setPosterFrame is not available on this project item in this Premiere Pro version");
1113
- }
1114
-
1115
- try {
1116
- var posterTicks = __secondsToTicks(${args.time_seconds}).toString();
1117
- item.setPosterFrame(posterTicks);
1118
- return __result({ item: item.name, timeSeconds: ${args.time_seconds}, posterTicks: posterTicks });
1119
- } catch(e) {
1120
- return __error("Failed to set poster frame: " + e.message);
1121
- }
1102
+ const script = buildToolScript(`
1103
+ var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
1104
+ if (!item) {
1105
+ // Fall back to treating item_id as a timeline clip node id
1106
+ var res = __findClip("${escapeForExtendScript(args.item_id)}");
1107
+ if (res && res.clip && res.clip.projectItem) item = res.clip.projectItem;
1108
+ }
1109
+ if (!item) return __error("Item not found");
1110
+
1111
+ if (typeof item.setPosterFrame !== "function") {
1112
+ return __error("setPosterFrame is not available on this project item in this Premiere Pro version");
1113
+ }
1114
+
1115
+ try {
1116
+ var posterTicks = __secondsToTicks(${args.time_seconds}).toString();
1117
+ item.setPosterFrame(posterTicks);
1118
+ return __result({ item: item.name, timeSeconds: ${args.time_seconds}, posterTicks: posterTicks });
1119
+ } catch(e) {
1120
+ return __error("Failed to set poster frame: " + e.message);
1121
+ }
1122
1122
  `);
1123
1123
  return sendCommand(script, bridgeOptions);
1124
1124
  },
@@ -1127,14 +1127,14 @@ export function getTrackTargetingTools(bridgeOptions) {
1127
1127
  description: "Get Premiere Pro version and build information.",
1128
1128
  parameters: {},
1129
1129
  handler: async () => {
1130
- const script = buildToolScript(`
1131
- var info = {
1132
- version: app.version,
1133
- buildNumber: app.build
1134
- };
1135
- try { info.isDocumentOpen = app.isDocumentOpen(); } catch(e) {}
1136
- try { info.path = app.path; } catch(e) {}
1137
- return __result(info);
1130
+ const script = buildToolScript(`
1131
+ var info = {
1132
+ version: app.version,
1133
+ buildNumber: app.build
1134
+ };
1135
+ try { info.isDocumentOpen = app.isDocumentOpen(); } catch(e) {}
1136
+ try { info.path = app.path; } catch(e) {}
1137
+ return __result(info);
1138
1138
  `);
1139
1139
  return sendCommand(script, bridgeOptions);
1140
1140
  },
@@ -1157,23 +1157,23 @@ export function getTrackTargetingTools(bridgeOptions) {
1157
1157
  },
1158
1158
  handler: async (args) => {
1159
1159
  const idsJson = JSON.stringify(args.item_ids);
1160
- const script = buildToolScript(`
1161
- var targetBin = __findProjectItem("${escapeForExtendScript(args.target_bin)}");
1162
- if (!targetBin || targetBin.type !== 2) return __error("Target bin not found: ${escapeForExtendScript(args.target_bin)}");
1163
-
1164
- var ids = ${idsJson};
1165
- var moved = 0;
1166
- for (var i = 0; i < ids.length; i++) {
1167
- var item = __findProjectItem(ids[i]);
1168
- if (item) {
1169
- try {
1170
- item.moveBin(targetBin);
1171
- moved++;
1172
- } catch(e) {}
1173
- }
1174
- }
1175
-
1176
- return __result({ moved: moved, total: ids.length, targetBin: targetBin.name });
1160
+ const script = buildToolScript(`
1161
+ var targetBin = __findProjectItem("${escapeForExtendScript(args.target_bin)}");
1162
+ if (!targetBin || targetBin.type !== 2) return __error("Target bin not found: ${escapeForExtendScript(args.target_bin)}");
1163
+
1164
+ var ids = ${idsJson};
1165
+ var moved = 0;
1166
+ for (var i = 0; i < ids.length; i++) {
1167
+ var item = __findProjectItem(ids[i]);
1168
+ if (item) {
1169
+ try {
1170
+ item.moveBin(targetBin);
1171
+ moved++;
1172
+ } catch(e) {}
1173
+ }
1174
+ }
1175
+
1176
+ return __result({ moved: moved, total: ids.length, targetBin: targetBin.name });
1177
1177
  `);
1178
1178
  return sendCommand(script, bridgeOptions);
1179
1179
  },
@@ -1195,27 +1195,27 @@ export function getTrackTargetingTools(bridgeOptions) {
1195
1195
  required: ["node_id", "enabled"],
1196
1196
  },
1197
1197
  handler: async (args) => {
1198
- const script = buildToolScript(`
1199
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
1200
- if (!result) return __error("Clip not found");
1201
-
1202
- var clip = result.clip;
1203
- var set = false;
1204
- for (var i = 0; i < clip.components.numItems; i++) {
1205
- if (clip.components[i].displayName === "Motion") {
1206
- for (var p = 0; p < clip.components[i].properties.numItems; p++) {
1207
- var pName = clip.components[i].properties[p].displayName;
1208
- if (pName === "Anti-flicker Filter" || pName === "Use Composition's Shutter Angle") {
1209
- clip.components[i].properties[p].setValue(${args.enabled}, true);
1210
- set = true;
1211
- break;
1212
- }
1213
- }
1214
- break;
1215
- }
1216
- }
1217
-
1218
- return __result({ clip: clip.name, antiAlias: ${args.enabled}, propertyFound: set });
1198
+ const script = buildToolScript(`
1199
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
1200
+ if (!result) return __error("Clip not found");
1201
+
1202
+ var clip = result.clip;
1203
+ var set = false;
1204
+ for (var i = 0; i < clip.components.numItems; i++) {
1205
+ if (clip.components[i].displayName === "Motion") {
1206
+ for (var p = 0; p < clip.components[i].properties.numItems; p++) {
1207
+ var pName = clip.components[i].properties[p].displayName;
1208
+ if (pName === "Anti-flicker Filter" || pName === "Use Composition's Shutter Angle") {
1209
+ clip.components[i].properties[p].setValue(${args.enabled}, true);
1210
+ set = true;
1211
+ break;
1212
+ }
1213
+ }
1214
+ break;
1215
+ }
1216
+ }
1217
+
1218
+ return __result({ clip: clip.name, antiAlias: ${args.enabled}, propertyFound: set });
1219
1219
  `);
1220
1220
  return sendCommand(script, bridgeOptions);
1221
1221
  },
@@ -1237,26 +1237,26 @@ export function getTrackTargetingTools(bridgeOptions) {
1237
1237
  required: ["node_id", "uniform"],
1238
1238
  },
1239
1239
  handler: async (args) => {
1240
- const script = buildToolScript(`
1241
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
1242
- if (!result) return __error("Clip not found");
1243
-
1244
- var clip = result.clip;
1245
- var set = false;
1246
- for (var i = 0; i < clip.components.numItems; i++) {
1247
- if (clip.components[i].displayName === "Motion") {
1248
- for (var p = 0; p < clip.components[i].properties.numItems; p++) {
1249
- if (clip.components[i].properties[p].displayName === "Uniform Scale") {
1250
- clip.components[i].properties[p].setValue(${args.uniform}, true);
1251
- set = true;
1252
- break;
1253
- }
1254
- }
1255
- break;
1256
- }
1257
- }
1258
- if (!set) return __error("Uniform Scale property not found");
1259
- return __result({ clip: clip.name, uniformScale: ${args.uniform} });
1240
+ const script = buildToolScript(`
1241
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
1242
+ if (!result) return __error("Clip not found");
1243
+
1244
+ var clip = result.clip;
1245
+ var set = false;
1246
+ for (var i = 0; i < clip.components.numItems; i++) {
1247
+ if (clip.components[i].displayName === "Motion") {
1248
+ for (var p = 0; p < clip.components[i].properties.numItems; p++) {
1249
+ if (clip.components[i].properties[p].displayName === "Uniform Scale") {
1250
+ clip.components[i].properties[p].setValue(${args.uniform}, true);
1251
+ set = true;
1252
+ break;
1253
+ }
1254
+ }
1255
+ break;
1256
+ }
1257
+ }
1258
+ if (!set) return __error("Uniform Scale property not found");
1259
+ return __result({ clip: clip.name, uniformScale: ${args.uniform} });
1260
1260
  `);
1261
1261
  return sendCommand(script, bridgeOptions);
1262
1262
  },
@@ -1282,33 +1282,33 @@ export function getTrackTargetingTools(bridgeOptions) {
1282
1282
  required: ["node_id", "scale_width", "scale_height"],
1283
1283
  },
1284
1284
  handler: async (args) => {
1285
- const script = buildToolScript(`
1286
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
1287
- if (!result) return __error("Clip not found");
1288
-
1289
- var clip = result.clip;
1290
- var motion = null;
1291
- for (var i = 0; i < clip.components.numItems; i++) {
1292
- if (clip.components[i].displayName === "Motion") { motion = clip.components[i]; break; }
1293
- }
1294
- if (!motion) return __error("Motion component not found");
1295
-
1296
- // Disable uniform scale first
1297
- for (var p = 0; p < motion.properties.numItems; p++) {
1298
- if (motion.properties[p].displayName === "Uniform Scale") {
1299
- motion.properties[p].setValue(false, true);
1300
- break;
1301
- }
1302
- }
1303
-
1304
- var setW = false, setH = false;
1305
- for (var p = 0; p < motion.properties.numItems; p++) {
1306
- var pName = motion.properties[p].displayName;
1307
- if (pName === "Scale Width") { motion.properties[p].setValue(${args.scale_width}, true); setW = true; }
1308
- if (pName === "Scale Height") { motion.properties[p].setValue(${args.scale_height}, true); setH = true; }
1309
- }
1310
-
1311
- return __result({ clip: clip.name, scaleWidth: ${args.scale_width}, scaleHeight: ${args.scale_height}, widthSet: setW, heightSet: setH });
1285
+ const script = buildToolScript(`
1286
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
1287
+ if (!result) return __error("Clip not found");
1288
+
1289
+ var clip = result.clip;
1290
+ var motion = null;
1291
+ for (var i = 0; i < clip.components.numItems; i++) {
1292
+ if (clip.components[i].displayName === "Motion") { motion = clip.components[i]; break; }
1293
+ }
1294
+ if (!motion) return __error("Motion component not found");
1295
+
1296
+ // Disable uniform scale first
1297
+ for (var p = 0; p < motion.properties.numItems; p++) {
1298
+ if (motion.properties[p].displayName === "Uniform Scale") {
1299
+ motion.properties[p].setValue(false, true);
1300
+ break;
1301
+ }
1302
+ }
1303
+
1304
+ var setW = false, setH = false;
1305
+ for (var p = 0; p < motion.properties.numItems; p++) {
1306
+ var pName = motion.properties[p].displayName;
1307
+ if (pName === "Scale Width") { motion.properties[p].setValue(${args.scale_width}, true); setW = true; }
1308
+ if (pName === "Scale Height") { motion.properties[p].setValue(${args.scale_height}, true); setH = true; }
1309
+ }
1310
+
1311
+ return __result({ clip: clip.name, scaleWidth: ${args.scale_width}, scaleHeight: ${args.scale_height}, widthSet: setW, heightSet: setH });
1312
1312
  `);
1313
1313
  return sendCommand(script, bridgeOptions);
1314
1314
  },