@synthetic-ai/premiere-mcp 2.1.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 (58) hide show
  1. package/CHANGELOG.md +135 -123
  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/index.js +103 -4
  12. package/dist/license.js +38 -0
  13. package/dist/server.js +60 -60
  14. package/dist/tools/advanced.js +357 -357
  15. package/dist/tools/audio-advanced.js +1049 -1049
  16. package/dist/tools/audio.js +42 -42
  17. package/dist/tools/captions.js +27 -27
  18. package/dist/tools/clipboard.js +214 -214
  19. package/dist/tools/color-advanced.js +253 -253
  20. package/dist/tools/discovery.js +291 -291
  21. package/dist/tools/effects.js +285 -285
  22. package/dist/tools/export-presets.js +206 -206
  23. package/dist/tools/export.js +255 -255
  24. package/dist/tools/health.js +10 -10
  25. package/dist/tools/inspection.js +885 -885
  26. package/dist/tools/keyframes.js +369 -369
  27. package/dist/tools/markers.js +89 -89
  28. package/dist/tools/media.js +178 -178
  29. package/dist/tools/metadata.js +94 -94
  30. package/dist/tools/multicam.js +50 -50
  31. package/dist/tools/playback.js +15 -15
  32. package/dist/tools/playhead.js +95 -95
  33. package/dist/tools/project-manager.js +21 -21
  34. package/dist/tools/project.js +149 -149
  35. package/dist/tools/scripting.js +319 -319
  36. package/dist/tools/selection.js +202 -202
  37. package/dist/tools/sequence-advanced.js +379 -379
  38. package/dist/tools/sequence-settings.js +564 -564
  39. package/dist/tools/sequence.js +167 -167
  40. package/dist/tools/source-monitor.js +68 -68
  41. package/dist/tools/text.js +58 -58
  42. package/dist/tools/timeline.js +312 -312
  43. package/dist/tools/track-management.js +446 -446
  44. package/dist/tools/track-targeting.js +635 -635
  45. package/dist/tools/tracks.js +87 -87
  46. package/dist/tools/transitions-motion.js +174 -174
  47. package/dist/tools/transitions.js +111 -111
  48. package/dist/tools/utility.js +606 -606
  49. package/dist/tools/workspace.js +29 -29
  50. package/package.json +66 -66
  51. package/scripts/build-chat-dmg.sh +210 -210
  52. package/scripts/build-chat-zip.sh +291 -291
  53. package/scripts/install-cep-windows.ps1 +99 -99
  54. package/scripts/install-cep.sh +66 -66
  55. package/scripts/install-chat-plugin.bat +67 -67
  56. package/scripts/install-chat-plugin.sh +85 -85
  57. package/scripts/install-windows.bat +95 -95
  58. package/scripts/package.mjs +254 -254
@@ -6,24 +6,24 @@ import { tmpdir } from "node:os";
6
6
  export function getExportTools(bridgeOptions) {
7
7
  return {
8
8
  export_sequence: {
9
- description: `Export the active sequence to a file using Adobe Media Encoder (AME).
10
-
11
- Preconditions: An active sequence must exist. Adobe Media Encoder must be installed. The output directory must exist and be writable.
12
-
13
- Export runs asynchronously via AME — this tool queues and starts the export, but completion may take minutes. The tool returns after the export job is queued (not after it finishes).
14
-
15
- Common preset paths:
16
- - macOS H.264 1080p: /Applications/Adobe Media Encoder [year]/MediaIO/systempresets/4028/HDTV 1080p 29.97 High Quality.epr
17
- - Windows H.264: C:\\Program Files\\Adobe\\Adobe Media Encoder [year]\\MediaIO\\systempresets\\4028\\HDTV 1080p 29.97 High Quality.epr
18
-
19
- If preset_path is omitted, uses default H.264 1080p settings.
20
-
21
- Parameters:
22
- - output_path: Absolute path for the output file including extension (e.g., .mp4, .mov, .mxf).
23
- - preset_path: Path to an AME .epr preset file. Determines codec, bitrate, and format.
24
- - work_area_only: If true, exports only the range between work area in/out points instead of the full sequence.
25
-
26
- Example: export_sequence({ output_path: "C:\\\\Exports\\\\final.mp4" })
9
+ description: `Export the active sequence to a file using Adobe Media Encoder (AME).
10
+
11
+ Preconditions: An active sequence must exist. Adobe Media Encoder must be installed. The output directory must exist and be writable.
12
+
13
+ Export runs asynchronously via AME — this tool queues and starts the export, but completion may take minutes. The tool returns after the export job is queued (not after it finishes).
14
+
15
+ Common preset paths:
16
+ - macOS H.264 1080p: /Applications/Adobe Media Encoder [year]/MediaIO/systempresets/4028/HDTV 1080p 29.97 High Quality.epr
17
+ - Windows H.264: C:\\Program Files\\Adobe\\Adobe Media Encoder [year]\\MediaIO\\systempresets\\4028\\HDTV 1080p 29.97 High Quality.epr
18
+
19
+ If preset_path is omitted, uses default H.264 1080p settings.
20
+
21
+ Parameters:
22
+ - output_path: Absolute path for the output file including extension (e.g., .mp4, .mov, .mxf).
23
+ - preset_path: Path to an AME .epr preset file. Determines codec, bitrate, and format.
24
+ - work_area_only: If true, exports only the range between work area in/out points instead of the full sequence.
25
+
26
+ Example: export_sequence({ output_path: "C:\\\\Exports\\\\final.mp4" })
27
27
  Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_path: "/path/to/ProRes422.epr", work_area_only: false })`,
28
28
  parameters: {
29
29
  type: "object",
@@ -44,41 +44,41 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
44
44
  required: ["output_path"],
45
45
  },
46
46
  handler: async (args) => {
47
- const script = buildToolScript(`
48
- var seq = app.project.activeSequence;
49
- if (!seq) return __error("No active sequence");
50
-
51
- var outputPath = "${escapeForExtendScript(args.output_path)}";
52
-
47
+ const script = buildToolScript(`
48
+ var seq = app.project.activeSequence;
49
+ if (!seq) return __error("No active sequence");
50
+
51
+ var outputPath = "${escapeForExtendScript(args.output_path)}";
52
+
53
53
  ${args.preset_path
54
54
  ? `var presetPath = "${escapeForExtendScript(args.preset_path)}";`
55
- : `// No preset_path provided — build a default by probing common locations.
56
- var presetPath = "";
57
- var presetCandidates = [
58
- // Windows — Adobe Media Encoder 2026 / 2025 / 2024 / generic
59
- "C:\\\\Program Files\\\\Adobe\\\\Adobe Media Encoder 2026\\\\MediaIO\\\\systempresets\\\\4028\\\\HDTV 1080p 29.97 High Quality.epr",
60
- "C:\\\\Program Files\\\\Adobe\\\\Adobe Media Encoder 2025\\\\MediaIO\\\\systempresets\\\\4028\\\\HDTV 1080p 29.97 High Quality.epr",
61
- "C:\\\\Program Files\\\\Adobe\\\\Adobe Media Encoder 2024\\\\MediaIO\\\\systempresets\\\\4028\\\\HDTV 1080p 29.97 High Quality.epr",
62
- // macOS — Adobe Media Encoder 2026 / 2025 / 2024
63
- "/Applications/Adobe Media Encoder 2026/MediaIO/systempresets/4028/HDTV 1080p 29.97 High Quality.epr",
64
- "/Applications/Adobe Media Encoder 2025/MediaIO/systempresets/4028/HDTV 1080p 29.97 High Quality.epr",
65
- "/Applications/Adobe Media Encoder 2024/MediaIO/systempresets/4028/HDTV 1080p 29.97 High Quality.epr"
66
- ];
67
- for (var i = 0; i < presetCandidates.length; i++) {
68
- var presetFile = new File(presetCandidates[i]);
69
- if (presetFile.exists) { presetPath = presetFile.fsName; break; }
70
- }
71
- if (presetPath === "") {
72
- return __error("No default export preset (.epr) could be found on this system. Pass preset_path with an absolute path to an AME .epr preset file.");
73
- }`}
74
-
75
- var exportResult = seq.exportAsMediaDirect(
76
- outputPath,
77
- presetPath,
78
- ${args.work_area_only ? "app.encoder.ENCODE_WORKAREA" : "app.encoder.ENCODE_ENTIRE"}
79
- );
80
-
81
- return __result({ exported: true, outputPath: outputPath });
55
+ : `// No preset_path provided — build a default by probing common locations.
56
+ var presetPath = "";
57
+ var presetCandidates = [
58
+ // Windows — Adobe Media Encoder 2026 / 2025 / 2024 / generic
59
+ "C:\\\\Program Files\\\\Adobe\\\\Adobe Media Encoder 2026\\\\MediaIO\\\\systempresets\\\\4028\\\\HDTV 1080p 29.97 High Quality.epr",
60
+ "C:\\\\Program Files\\\\Adobe\\\\Adobe Media Encoder 2025\\\\MediaIO\\\\systempresets\\\\4028\\\\HDTV 1080p 29.97 High Quality.epr",
61
+ "C:\\\\Program Files\\\\Adobe\\\\Adobe Media Encoder 2024\\\\MediaIO\\\\systempresets\\\\4028\\\\HDTV 1080p 29.97 High Quality.epr",
62
+ // macOS — Adobe Media Encoder 2026 / 2025 / 2024
63
+ "/Applications/Adobe Media Encoder 2026/MediaIO/systempresets/4028/HDTV 1080p 29.97 High Quality.epr",
64
+ "/Applications/Adobe Media Encoder 2025/MediaIO/systempresets/4028/HDTV 1080p 29.97 High Quality.epr",
65
+ "/Applications/Adobe Media Encoder 2024/MediaIO/systempresets/4028/HDTV 1080p 29.97 High Quality.epr"
66
+ ];
67
+ for (var i = 0; i < presetCandidates.length; i++) {
68
+ var presetFile = new File(presetCandidates[i]);
69
+ if (presetFile.exists) { presetPath = presetFile.fsName; break; }
70
+ }
71
+ if (presetPath === "") {
72
+ return __error("No default export preset (.epr) could be found on this system. Pass preset_path with an absolute path to an AME .epr preset file.");
73
+ }`}
74
+
75
+ var exportResult = seq.exportAsMediaDirect(
76
+ outputPath,
77
+ presetPath,
78
+ ${args.work_area_only ? "app.encoder.ENCODE_WORKAREA" : "app.encoder.ENCODE_ENTIRE"}
79
+ );
80
+
81
+ return __result({ exported: true, outputPath: outputPath });
82
82
  `);
83
83
  return sendCommand(script, { ...bridgeOptions, timeoutMs: 120000 }); // 2 min timeout for exports
84
84
  },
@@ -100,18 +100,18 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
100
100
  required: ["output_path"],
101
101
  },
102
102
  handler: async (args) => {
103
- const script = buildToolScript(`
104
- var seq = app.project.activeSequence;
105
- if (!seq) return __error("No active sequence");
106
-
103
+ const script = buildToolScript(`
104
+ var seq = app.project.activeSequence;
105
+ if (!seq) return __error("No active sequence");
106
+
107
107
  ${args.time_seconds !== undefined
108
108
  ? `seq.setPlayerPosition(__secondsToTicks(${args.time_seconds}).toString());`
109
- : ""}
110
-
111
- var outputPath = "${escapeForExtendScript(args.output_path)}";
112
- seq.exportFramePNG(seq.getPlayerPosition().ticks, outputPath);
113
-
114
- return __result({ exported: true, outputPath: outputPath });
109
+ : ""}
110
+
111
+ var outputPath = "${escapeForExtendScript(args.output_path)}";
112
+ seq.exportFramePNG(seq.getPlayerPosition().ticks, outputPath);
113
+
114
+ return __result({ exported: true, outputPath: outputPath });
115
115
  `);
116
116
  return sendCommand(script, bridgeOptions);
117
117
  },
@@ -129,12 +129,12 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
129
129
  required: ["output_path"],
130
130
  },
131
131
  handler: async (args) => {
132
- const script = buildToolScript(`
133
- var seq = app.project.activeSequence;
134
- if (!seq) return __error("No active sequence");
135
-
136
- seq.exportAsFinalCutProXML("${escapeForExtendScript(args.output_path)}");
137
- return __result({ exported: true, outputPath: "${escapeForExtendScript(args.output_path)}", format: "FCP XML" });
132
+ const script = buildToolScript(`
133
+ var seq = app.project.activeSequence;
134
+ if (!seq) return __error("No active sequence");
135
+
136
+ seq.exportAsFinalCutProXML("${escapeForExtendScript(args.output_path)}");
137
+ return __result({ exported: true, outputPath: "${escapeForExtendScript(args.output_path)}", format: "FCP XML" });
138
138
  `);
139
139
  return sendCommand(script, bridgeOptions);
140
140
  },
@@ -168,19 +168,19 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
168
168
  required: ["output_path"],
169
169
  },
170
170
  handler: async (args) => {
171
- const script = buildToolScript(`
172
- var seq = app.project.activeSequence;
173
- if (!seq) return __error("No active sequence");
174
-
175
- seq.exportAsAAF(
176
- "${escapeForExtendScript(args.output_path)}",
177
- ${args.mix_down_video !== false ? 1 : 0},
178
- ${args.explode_to_mono ? 1 : 0},
179
- ${args.sample_rate ?? 48000},
180
- ${args.bits_per_sample ?? 16}
181
- );
182
-
183
- return __result({ exported: true, outputPath: "${escapeForExtendScript(args.output_path)}", format: "AAF" });
171
+ const script = buildToolScript(`
172
+ var seq = app.project.activeSequence;
173
+ if (!seq) return __error("No active sequence");
174
+
175
+ seq.exportAsAAF(
176
+ "${escapeForExtendScript(args.output_path)}",
177
+ ${args.mix_down_video !== false ? 1 : 0},
178
+ ${args.explode_to_mono ? 1 : 0},
179
+ ${args.sample_rate ?? 48000},
180
+ ${args.bits_per_sample ?? 16}
181
+ );
182
+
183
+ return __result({ exported: true, outputPath: "${escapeForExtendScript(args.output_path)}", format: "AAF" });
184
184
  `);
185
185
  return sendCommand(script, bridgeOptions);
186
186
  },
@@ -202,29 +202,29 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
202
202
  required: ["output_path"],
203
203
  },
204
204
  handler: async (args) => {
205
- const script = buildToolScript(`
206
- var seq = app.project.activeSequence;
207
- if (!seq) return __error("No active sequence");
208
-
209
- var encoder = app.encoder;
210
- if (!encoder) return __error("Adobe Media Encoder not available");
211
-
212
- encoder.launchEncoder();
213
-
214
- var outputPath = "${escapeForExtendScript(args.output_path)}";
205
+ const script = buildToolScript(`
206
+ var seq = app.project.activeSequence;
207
+ if (!seq) return __error("No active sequence");
208
+
209
+ var encoder = app.encoder;
210
+ if (!encoder) return __error("Adobe Media Encoder not available");
211
+
212
+ encoder.launchEncoder();
213
+
214
+ var outputPath = "${escapeForExtendScript(args.output_path)}";
215
215
  ${args.preset_path
216
216
  ? `var presetPath = "${escapeForExtendScript(args.preset_path)}";`
217
- : `var presetPath = encoder.ENCODE_MATCH_SEQUENCE;`}
218
-
219
- encoder.encodeSequence(
220
- seq,
221
- outputPath,
222
- presetPath,
223
- 0, // workAreaType
224
- 1 // removeOnCompletion
225
- );
226
-
227
- return __result({ queued: true, outputPath: outputPath });
217
+ : `var presetPath = encoder.ENCODE_MATCH_SEQUENCE;`}
218
+
219
+ encoder.encodeSequence(
220
+ seq,
221
+ outputPath,
222
+ presetPath,
223
+ 0, // workAreaType
224
+ 1 // removeOnCompletion
225
+ );
226
+
227
+ return __result({ queued: true, outputPath: outputPath });
228
228
  `);
229
229
  return sendCommand(script, bridgeOptions);
230
230
  },
@@ -233,14 +233,14 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
233
233
  description: "Get the current status of the Adobe Media Encoder render queue",
234
234
  parameters: {},
235
235
  handler: async () => {
236
- const script = buildToolScript(`
237
- var encoder = app.encoder;
238
- if (!encoder) return __error("Adobe Media Encoder not available");
239
-
240
- return __result({
241
- isRunning: encoder.isRunning ? encoder.isRunning() : "unknown",
242
- info: "Check Adobe Media Encoder application for detailed queue status"
243
- });
236
+ const script = buildToolScript(`
237
+ var encoder = app.encoder;
238
+ if (!encoder) return __error("Adobe Media Encoder not available");
239
+
240
+ return __result({
241
+ isRunning: encoder.isRunning ? encoder.isRunning() : "unknown",
242
+ info: "Check Adobe Media Encoder application for detailed queue status"
243
+ });
244
244
  `);
245
245
  return sendCommand(script, bridgeOptions);
246
246
  },
@@ -270,24 +270,24 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
270
270
  required: ["item_id", "name", "in_seconds", "out_seconds"],
271
271
  },
272
272
  handler: async (args) => {
273
- const script = buildToolScript(`
274
- var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
275
- if (!item) return __error("Item not found");
276
-
277
- var inTicks = __secondsToTicks(${args.in_seconds}).toString();
278
- var outTicks = __secondsToTicks(${args.out_seconds}).toString();
279
-
280
- var subclip = item.createSubClip(
281
- "${escapeForExtendScript(args.name)}",
282
- inTicks,
283
- outTicks,
284
- 0, // hasHardBoundaries
285
- 1, // takeVideo
286
- 1 // takeAudio
287
- );
288
-
289
- if (!subclip) return __error("Failed to create subclip");
290
- return __result({ created: true, name: "${escapeForExtendScript(args.name)}", source: item.name });
273
+ const script = buildToolScript(`
274
+ var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
275
+ if (!item) return __error("Item not found");
276
+
277
+ var inTicks = __secondsToTicks(${args.in_seconds}).toString();
278
+ var outTicks = __secondsToTicks(${args.out_seconds}).toString();
279
+
280
+ var subclip = item.createSubClip(
281
+ "${escapeForExtendScript(args.name)}",
282
+ inTicks,
283
+ outTicks,
284
+ 0, // hasHardBoundaries
285
+ 1, // takeVideo
286
+ 1 // takeAudio
287
+ );
288
+
289
+ if (!subclip) return __error("Failed to create subclip");
290
+ return __result({ created: true, name: "${escapeForExtendScript(args.name)}", source: item.name });
291
291
  `);
292
292
  return sendCommand(script, bridgeOptions);
293
293
  },
@@ -306,51 +306,51 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
306
306
  handler: async (args) => {
307
307
  const tempPath = join(tmpdir(), `mcp_frame_capture_${Date.now()}.png`);
308
308
  const escapedPath = escapeForExtendScript(tempPath);
309
- const script = buildToolScript(`
310
- var seq = app.project.activeSequence;
311
- if (!seq) return __error("No active sequence");
312
-
309
+ const script = buildToolScript(`
310
+ var seq = app.project.activeSequence;
311
+ if (!seq) return __error("No active sequence");
312
+
313
313
  ${args.time_seconds !== undefined
314
314
  ? `seq.setPlayerPosition(__secondsToTicks(${args.time_seconds}).toString());`
315
- : ""}
316
-
317
- var outputPath = "${escapedPath}";
318
- // seq.exportFramePNG does not exist in PP 2026. Use the QE DOM approach:
319
- // app.enableQE(); qe.project.getActiveSequence().exportFrameJPG(ticks, path)
320
- // falls back to source monitor PNG if that also fails.
321
- // PP 2026 host bug verified at runtime: seq.exportFramePNG / exportFrameJPEG
322
- // do NOT exist on the DOM Sequence object, and qe.project.getActiveSequence()
323
- // exposes exportFramePNG as a "function" but the call returns successfully
324
- // WITHOUT writing the file (waited 5s, file never appears).
325
- // The only working frame-export path in PP 2026 is via Adobe Media Encoder
326
- // with a single-frame preset, which is heavy and asynchronous.
327
- // Return an honest error with a recommended workaround.
328
- app.enableQE();
329
- var pos = seq.getPlayerPosition();
330
- var posTicks = pos ? pos.ticks : "0";
331
- var attempted = [];
332
- var hadAnyFunction = false;
333
- try {
334
- var qeSeq2 = qe.project.getActiveSequence();
335
- if (qeSeq2 && typeof qeSeq2.exportFramePNG === "function") {
336
- hadAnyFunction = true;
337
- attempted.push("qeSeq.exportFramePNG(path, ticks)");
338
- qeSeq2.exportFramePNG(outputPath, posTicks);
339
- // Wait a moment in case PP is fast enough
340
- $.sleep(800);
341
- var f = new File(outputPath);
342
- if (f.exists && f.length > 0) {
343
- return __result({ exported: true, outputPath: outputPath, atTicks: posTicks });
344
- }
345
- }
346
- } catch (eQE) { attempted.push("qe error: " + eQE.toString()); }
347
-
348
- return __error("capture_frame is not supported in Premiere Pro 2026 via ExtendScript. " +
349
- "Verified at runtime: seq.exportFramePNG/exportFrameJPEG do not exist on the DOM Sequence, " +
350
- "and qe.project.getActiveSequence().exportFramePNG reports success but never writes the file. " +
351
- "Workaround: use 'File > Export > Media > Single Frame' in the Premiere Pro UI, " +
352
- "or use export_sequence with a single-frame preset via AME (heavy/async). " +
353
- "Attempted: [" + attempted.join("; ") + "]. hadFunction=" + hadAnyFunction);
315
+ : ""}
316
+
317
+ var outputPath = "${escapedPath}";
318
+ // seq.exportFramePNG does not exist in PP 2026. Use the QE DOM approach:
319
+ // app.enableQE(); qe.project.getActiveSequence().exportFrameJPG(ticks, path)
320
+ // falls back to source monitor PNG if that also fails.
321
+ // PP 2026 host bug verified at runtime: seq.exportFramePNG / exportFrameJPEG
322
+ // do NOT exist on the DOM Sequence object, and qe.project.getActiveSequence()
323
+ // exposes exportFramePNG as a "function" but the call returns successfully
324
+ // WITHOUT writing the file (waited 5s, file never appears).
325
+ // The only working frame-export path in PP 2026 is via Adobe Media Encoder
326
+ // with a single-frame preset, which is heavy and asynchronous.
327
+ // Return an honest error with a recommended workaround.
328
+ app.enableQE();
329
+ var pos = seq.getPlayerPosition();
330
+ var posTicks = pos ? pos.ticks : "0";
331
+ var attempted = [];
332
+ var hadAnyFunction = false;
333
+ try {
334
+ var qeSeq2 = qe.project.getActiveSequence();
335
+ if (qeSeq2 && typeof qeSeq2.exportFramePNG === "function") {
336
+ hadAnyFunction = true;
337
+ attempted.push("qeSeq.exportFramePNG(path, ticks)");
338
+ qeSeq2.exportFramePNG(outputPath, posTicks);
339
+ // Wait a moment in case PP is fast enough
340
+ $.sleep(800);
341
+ var f = new File(outputPath);
342
+ if (f.exists && f.length > 0) {
343
+ return __result({ exported: true, outputPath: outputPath, atTicks: posTicks });
344
+ }
345
+ }
346
+ } catch (eQE) { attempted.push("qe error: " + eQE.toString()); }
347
+
348
+ return __error("capture_frame is not supported in Premiere Pro 2026 via ExtendScript. " +
349
+ "Verified at runtime: seq.exportFramePNG/exportFrameJPEG do not exist on the DOM Sequence, " +
350
+ "and qe.project.getActiveSequence().exportFramePNG reports success but never writes the file. " +
351
+ "Workaround: use 'File > Export > Media > Single Frame' in the Premiere Pro UI, " +
352
+ "or use export_sequence with a single-frame preset via AME (heavy/async). " +
353
+ "Attempted: [" + attempted.join("; ") + "]. hadFunction=" + hadAnyFunction);
354
354
  `);
355
355
  const result = await sendCommand(script, bridgeOptions);
356
356
  if (!result.success)
@@ -424,23 +424,23 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
424
424
  required: ["output_path"],
425
425
  },
426
426
  handler: async (args) => {
427
- const script = buildToolScript(`
428
- var seq = app.project.activeSequence;
429
- if (!seq) return __error("No active sequence");
430
-
431
- app.project.exportOMF(
432
- seq,
433
- "${escapeForExtendScript(args.output_path)}",
434
- "OMFTitle",
435
- ${args.sample_rate ?? 48000},
436
- ${args.bits_per_sample ?? 16},
437
- ${args.audio_encapsulated !== false ? 1 : 0},
438
- ${args.audio_file_format ?? 1},
439
- ${args.trim_audio_files !== false ? 1 : 0},
440
- ${args.handle_frames ?? 1000}
441
- );
442
-
443
- return __result({ exported: true, outputPath: "${escapeForExtendScript(args.output_path)}", format: "OMF" });
427
+ const script = buildToolScript(`
428
+ var seq = app.project.activeSequence;
429
+ if (!seq) return __error("No active sequence");
430
+
431
+ app.project.exportOMF(
432
+ seq,
433
+ "${escapeForExtendScript(args.output_path)}",
434
+ "OMFTitle",
435
+ ${args.sample_rate ?? 48000},
436
+ ${args.bits_per_sample ?? 16},
437
+ ${args.audio_encapsulated !== false ? 1 : 0},
438
+ ${args.audio_file_format ?? 1},
439
+ ${args.trim_audio_files !== false ? 1 : 0},
440
+ ${args.handle_frames ?? 1000}
441
+ );
442
+
443
+ return __result({ exported: true, outputPath: "${escapeForExtendScript(args.output_path)}", format: "OMF" });
444
444
  `);
445
445
  return sendCommand(script, { ...bridgeOptions, timeoutMs: 120000 });
446
446
  },
@@ -470,25 +470,25 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
470
470
  required: ["item_id", "output_path", "preset_path"],
471
471
  },
472
472
  handler: async (args) => {
473
- const script = buildToolScript(`
474
- var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
475
- if (!item) return __error("Project item not found: ${escapeForExtendScript(args.item_id)}");
476
-
477
- app.encoder.launchEncoder();
478
- app.encoder.encodeProjectItem(
479
- item,
480
- "${escapeForExtendScript(args.output_path)}",
481
- "${escapeForExtendScript(args.preset_path)}",
482
- app.encoder.ENCODE_IN_TO_OUT,
483
- ${args.remove_on_completion !== false ? 1 : 0}
484
- );
485
- app.encoder.startBatch();
486
-
487
- return __result({
488
- queued: true,
489
- item: item.name,
490
- outputPath: "${escapeForExtendScript(args.output_path)}"
491
- });
473
+ const script = buildToolScript(`
474
+ var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
475
+ if (!item) return __error("Project item not found: ${escapeForExtendScript(args.item_id)}");
476
+
477
+ app.encoder.launchEncoder();
478
+ app.encoder.encodeProjectItem(
479
+ item,
480
+ "${escapeForExtendScript(args.output_path)}",
481
+ "${escapeForExtendScript(args.preset_path)}",
482
+ app.encoder.ENCODE_IN_TO_OUT,
483
+ ${args.remove_on_completion !== false ? 1 : 0}
484
+ );
485
+ app.encoder.startBatch();
486
+
487
+ return __result({
488
+ queued: true,
489
+ item: item.name,
490
+ outputPath: "${escapeForExtendScript(args.output_path)}"
491
+ });
492
492
  `);
493
493
  return sendCommand(script, bridgeOptions);
494
494
  },
@@ -532,31 +532,31 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
532
532
  const outPointCode = args.out_seconds !== undefined
533
533
  ? `var srcOut = new Time(); srcOut.seconds = ${args.out_seconds};`
534
534
  : `var srcOut = undefined;`;
535
- const script = buildToolScript(`
536
- app.encoder.launchEncoder();
537
-
538
- ${inPointCode}
539
- ${outPointCode}
540
-
541
- // Signature: encodeFile(inputPath, outputPath, presetPath, workArea,
542
- // removeUponCompletion, inPoint, outPoint). workArea 1 = in-to-out, 0 = entire.
543
- var workArea = (typeof srcIn !== "undefined" || typeof srcOut !== "undefined") ? 1 : 0;
544
- app.encoder.encodeFile(
545
- "${escapeForExtendScript(args.input_path)}",
546
- "${escapeForExtendScript(args.output_path)}",
547
- "${escapeForExtendScript(args.preset_path)}",
548
- workArea,
549
- ${args.remove_on_completion !== false ? 1 : 0},
550
- srcIn,
551
- srcOut
552
- );
553
- app.encoder.startBatch();
554
-
555
- return __result({
556
- queued: true,
557
- inputPath: "${escapeForExtendScript(args.input_path)}",
558
- outputPath: "${escapeForExtendScript(args.output_path)}"
559
- });
535
+ const script = buildToolScript(`
536
+ app.encoder.launchEncoder();
537
+
538
+ ${inPointCode}
539
+ ${outPointCode}
540
+
541
+ // Signature: encodeFile(inputPath, outputPath, presetPath, workArea,
542
+ // removeUponCompletion, inPoint, outPoint). workArea 1 = in-to-out, 0 = entire.
543
+ var workArea = (typeof srcIn !== "undefined" || typeof srcOut !== "undefined") ? 1 : 0;
544
+ app.encoder.encodeFile(
545
+ "${escapeForExtendScript(args.input_path)}",
546
+ "${escapeForExtendScript(args.output_path)}",
547
+ "${escapeForExtendScript(args.preset_path)}",
548
+ workArea,
549
+ ${args.remove_on_completion !== false ? 1 : 0},
550
+ srcIn,
551
+ srcOut
552
+ );
553
+ app.encoder.startBatch();
554
+
555
+ return __result({
556
+ queued: true,
557
+ inputPath: "${escapeForExtendScript(args.input_path)}",
558
+ outputPath: "${escapeForExtendScript(args.output_path)}"
559
+ });
560
560
  `);
561
561
  return sendCommand(script, bridgeOptions);
562
562
  },
@@ -583,32 +583,32 @@ Example: export_sequence({ output_path: "/Users/me/exports/prores.mov", preset_p
583
583
  required: ["item_id", "action"],
584
584
  },
585
585
  handler: async (args) => {
586
- const script = buildToolScript(`
587
- var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
588
- if (!item) return __error("Item not found");
589
-
590
- var action = "${args.action}";
591
-
592
- if (action === "create") {
593
- item.createProxy("", 0);
594
- return __result({ action: "create", item: item.name, status: "Proxy creation started" });
595
- } else if (action === "attach") {
586
+ const script = buildToolScript(`
587
+ var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
588
+ if (!item) return __error("Item not found");
589
+
590
+ var action = "${args.action}";
591
+
592
+ if (action === "create") {
593
+ item.createProxy("", 0);
594
+ return __result({ action: "create", item: item.name, status: "Proxy creation started" });
595
+ } else if (action === "attach") {
596
596
  ${args.proxy_path
597
- ? `item.attachProxy("${escapeForExtendScript(args.proxy_path)}", 0);
597
+ ? `item.attachProxy("${escapeForExtendScript(args.proxy_path)}", 0);
598
598
  return __result({ action: "attach", item: item.name, proxyPath: "${escapeForExtendScript(args.proxy_path)}" });`
599
- : `return __error("proxy_path is required for attach action");`}
600
- } else if (action === "toggle") {
601
- var hasP = false;
602
- try { hasP = item.hasProxy(); } catch(e) {}
603
- if (hasP) {
604
- try { item.detachProxy(); } catch(e) {}
605
- return __result({ action: "toggle", item: item.name, result: "proxy detached" });
606
- } else {
607
- return __result({ action: "toggle", item: item.name, result: "no proxy attached — use action='attach' with a proxy_path to add one" });
608
- }
609
- }
610
-
611
- return __error("Unknown proxy action: " + action);
599
+ : `return __error("proxy_path is required for attach action");`}
600
+ } else if (action === "toggle") {
601
+ var hasP = false;
602
+ try { hasP = item.hasProxy(); } catch(e) {}
603
+ if (hasP) {
604
+ try { item.detachProxy(); } catch(e) {}
605
+ return __result({ action: "toggle", item: item.name, result: "proxy detached" });
606
+ } else {
607
+ return __result({ action: "toggle", item: item.name, result: "no proxy attached — use action='attach' with a proxy_path to add one" });
608
+ }
609
+ }
610
+
611
+ return __error("Unknown proxy action: " + action);
612
612
  `);
613
613
  return sendCommand(script, bridgeOptions);
614
614
  },
@@ -6,16 +6,16 @@ export function getHealthTools(bridgeOptions) {
6
6
  description: "Health check — verify the CEP plugin is running and connected to Premiere Pro. Call this before other tools to confirm connectivity.",
7
7
  parameters: {},
8
8
  handler: async () => {
9
- const script = buildToolScript(`
10
- var version = app.version;
11
- var projectName = app.project && app.project.name ? app.project.name : "No project open";
12
- var activeSeq = app.project && app.project.activeSequence ? app.project.activeSequence.name : "None";
13
- return __result({
14
- connected: true,
15
- premiereVersion: version,
16
- projectName: projectName,
17
- activeSequence: activeSeq
18
- });
9
+ const script = buildToolScript(`
10
+ var version = app.version;
11
+ var projectName = app.project && app.project.name ? app.project.name : "No project open";
12
+ var activeSeq = app.project && app.project.activeSequence ? app.project.activeSequence.name : "None";
13
+ return __result({
14
+ connected: true,
15
+ premiereVersion: version,
16
+ projectName: projectName,
17
+ activeSequence: activeSeq
18
+ });
19
19
  `);
20
20
  return sendCommand(script, { ...bridgeOptions, timeoutMs: 5000 });
21
21
  },