premiere-pro-mcp 1.17.0 → 1.18.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.
- package/CHANGELOG.md +43 -0
- package/README.md +11 -11
- package/after-effects-cep-plugin/CSXS/manifest.xml +2 -2
- package/artifacts/MCPBridgeCEP.zxp +0 -0
- package/cep-plugin/CSXS/manifest.xml +3 -3
- package/cep-plugin/index.html +1 -1
- package/cep-plugin/updater.cjs +1 -1
- package/dist/bridge/script-builder.js +17 -5
- package/dist/http-server.js +2 -2
- package/dist/server.js +2 -2
- package/dist/telemetry.d.ts +2 -0
- package/dist/telemetry.js +9 -0
- package/dist/tools/advanced.d.ts +8 -0
- package/dist/tools/advanced.js +29 -2
- package/dist/tools/export.d.ts +5 -1
- package/dist/tools/export.js +47 -13
- package/dist/tools/media.js +57 -5
- package/dist/tools/metadata.js +5 -2
- package/dist/tools/mogrt-authoring.d.ts +26 -3
- package/dist/tools/mogrt-authoring.js +188 -42
- package/dist/tools/mogrt-text.d.ts +39 -0
- package/dist/tools/mogrt-text.js +107 -0
- package/dist/tools/text.d.ts +8 -0
- package/dist/tools/text.js +52 -3
- package/dist/workflows/agent-instructions.js +1 -0
- package/docs/mogrt-authoring.md +26 -2
- package/docs/supported-actions.md +4 -4
- package/package.json +1 -1
- package/public-product-manifest.json +1 -1
- package/uxp-plugin/commands.cjs +22 -11
- package/uxp-plugin/manifest.json +1 -1
- package/uxp-plugin/workflows.cjs +17 -7
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,49 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.18.0] - 2026-09-23
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- MOGRT text recipes default to `text_controls: "full"`: each text layer exposes
|
|
14
|
+
Font Size, Stroke Width, Fill Color, and Stroke Color controls plus named
|
|
15
|
+
Position, Scale, Rotation, Anchor Point, and Opacity Essential Graphics
|
|
16
|
+
controls. The create result reads back source-comp controller names.
|
|
17
|
+
`text_only` keeps the previous behavior. Font-family editing is not scriptable
|
|
18
|
+
and is reported as a known gap. (#618)
|
|
19
|
+
- `media_placeholder` MOGRT recipe imports a workspace-contained PNG, JPEG, MOV,
|
|
20
|
+
or MP4, requests a replaceable Essential Graphics media slot, and exposes its
|
|
21
|
+
transform controls. Not verified on a live After Effects or Premiere host.
|
|
22
|
+
(#619)
|
|
23
|
+
- `import_mogrt` accepts `text_values`, writes each named text control after
|
|
24
|
+
insertion (replacing only the text value so styling is kept), and reports
|
|
25
|
+
`verified`, `mismatch`, `missing_property`, or `committed_unverified` per
|
|
26
|
+
field. `get_mogrt_component` returns `textValue` for every parameter and an
|
|
27
|
+
optional `expected_values` audit that flags stale Headline text. (#617)
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- `encode_file` and `encode_project_item` pass natively typed arguments (String
|
|
32
|
+
paths, Boolean removal flag, Time in/out), fixing "Illegal Parameter type";
|
|
33
|
+
`encode_file` fails early when the preset file is missing. (#615)
|
|
34
|
+
- `set_xmp_metadata` passes numeric `XMPConst` options to
|
|
35
|
+
`XMPUtils.appendProperties`, fixing "Bad argument list". (#611)
|
|
36
|
+
- `manage_proxies` auto-discovery skips "Same as Project" proxy presets whose
|
|
37
|
+
output never reached `output_path`, and asks for `preset_path` when no safe
|
|
38
|
+
preset exists. (#610)
|
|
39
|
+
- `manage_metadata_uxp` and `create_subclip_uxp` find items inside nested bins.
|
|
40
|
+
(#612, #613)
|
|
41
|
+
- `set_scale_to_frame_size` accepts timeline clip IDs and reports `verified` or
|
|
42
|
+
`committed_unverified`. (#614)
|
|
43
|
+
|
|
44
|
+
### Known limitations
|
|
45
|
+
|
|
46
|
+
- The Essential Graphics panel can display a stale Headline after a MOGRT text
|
|
47
|
+
write. The tools read stored values and cannot refresh the host panel (#616
|
|
48
|
+
remains open).
|
|
49
|
+
- These fixes are covered by mocked automated tests only; they are not verified
|
|
50
|
+
on a licensed Premiere or After Effects host.
|
|
51
|
+
|
|
9
52
|
## [1.17.0] - 2026-09-21
|
|
10
53
|
|
|
11
54
|
### Added
|
package/README.md
CHANGED
|
@@ -108,10 +108,10 @@ The current source exposes 384 core tools for supported workflow steps spanning
|
|
|
108
108
|
|
|
109
109
|
<a id="latest-release"></a>
|
|
110
110
|
|
|
111
|
-
### Latest release: 1.
|
|
111
|
+
### Latest release: 1.18.0
|
|
112
112
|
|
|
113
|
-
The published v1.
|
|
114
|
-
and
|
|
113
|
+
The published v1.17.0 npm artifact contains **384 core tools**, 382 in its default profile,
|
|
114
|
+
and 477 with a compatible UXP connection. The development catalog above can include
|
|
115
115
|
unreleased work. See the [versioned facts and package provenance](https://premiere-pro-mcp.com/facts/).
|
|
116
116
|
|
|
117
117
|
### Try a bounded workflow
|
|
@@ -160,7 +160,7 @@ if the connection is unavailable.
|
|
|
160
160
|
local Premiere processes. See the generated [supported action catalog](docs/supported-actions.md)
|
|
161
161
|
for individual capability and verification contracts.
|
|
162
162
|
|
|
163
|
-
See the [v1.
|
|
163
|
+
See the [v1.18.0 release notes](https://github.com/leancoderkavy/premiere-pro-mcp/releases/tag/v1.18.0)
|
|
164
164
|
for complete details. Live installation in Premiere Pro still requires host verification.
|
|
165
165
|
|
|
166
166
|
### Current MCP protocol support
|
|
@@ -208,7 +208,7 @@ their bins, media rules, and organization rules before a facility uses one.
|
|
|
208
208
|
> ### Install the published package (verify the name)
|
|
209
209
|
>
|
|
210
210
|
> ```bash
|
|
211
|
-
> npm i -g premiere-pro-mcp@1.
|
|
211
|
+
> npm i -g premiere-pro-mcp@1.18.0
|
|
212
212
|
> ```
|
|
213
213
|
>
|
|
214
214
|
> This repository publishes only **`premiere-pro-mcp`**. A differently named package (`adobe-premiere-pro-mcp`) may also declare a `premiere-pro-mcp` executable. Before configuring a client, confirm:
|
|
@@ -216,7 +216,7 @@ their bins, media rules, and organization rules before a facility uses one.
|
|
|
216
216
|
> | Check | Expected |
|
|
217
217
|
> | --- | --- |
|
|
218
218
|
> | Package name | `premiere-pro-mcp` (not `adobe-premiere-pro-mcp`) |
|
|
219
|
-
> | Version | `1.
|
|
219
|
+
> | Version | `1.18.0` |
|
|
220
220
|
> | Homepage / repo | https://premiere-pro-mcp.com/ · https://github.com/leancoderkavy/premiere-pro-mcp |
|
|
221
221
|
>
|
|
222
222
|
> ```bash
|
|
@@ -229,9 +229,9 @@ their bins, media rules, and organization rules before a facility uses one.
|
|
|
229
229
|
|
|
230
230
|
### Easiest supported path: Claude Desktop
|
|
231
231
|
|
|
232
|
-
1. Download the current [Claude Desktop bundle (`.mcpb`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.
|
|
232
|
+
1. Download the current [Claude Desktop bundle (`.mcpb`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.18.0/premiere-pro-mcp-1.18.0.mcpb).
|
|
233
233
|
2. In Claude Desktop, open **Settings > Extensions > Advanced settings > Install Extension**, select the downloaded bundle, and restart Claude Desktop.
|
|
234
|
-
3. Download the separate [signed Premiere connector (`.zxp`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.
|
|
234
|
+
3. Download the separate [signed Premiere connector (`.zxp`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.18.0/MCPBridgeCEP.zxp). Open it with your trusted ZXP installer. If your computer has no ZXP installer, use the npm connector installer in **Advanced setup** below.
|
|
235
235
|
4. Restart Premiere, open a project, then open **Window > Extensions > MCP for Adobe Premiere Pro**.
|
|
236
236
|
5. In Claude, enter: `Safely check my Premiere connection with verify_premiere_connection. Make no changes.`
|
|
237
237
|
|
|
@@ -531,11 +531,11 @@ From a clone of this repository:
|
|
|
531
531
|
```bash
|
|
532
532
|
codex plugin marketplace add .
|
|
533
533
|
codex plugin add premiere-pro@premiere-pro-mcp
|
|
534
|
-
npx -y premiere-pro-mcp@1.
|
|
534
|
+
npx -y premiere-pro-mcp@1.17.0 --install-cep
|
|
535
535
|
```
|
|
536
536
|
|
|
537
537
|
Restart Premiere Pro and start a new Codex session after installation. The plugin
|
|
538
|
-
launches `premiere-pro-mcp@1.
|
|
538
|
+
launches `premiere-pro-mcp@1.17.0` through `npx`; the separate CEP installation is
|
|
539
539
|
required because the MCP server communicates with the running Premiere host through
|
|
540
540
|
the local bridge.
|
|
541
541
|
|
|
@@ -566,7 +566,7 @@ For Claude Code, add this repository as a marketplace and install the plugin:
|
|
|
566
566
|
Then install the Premiere bridge and start a new Claude Code session:
|
|
567
567
|
|
|
568
568
|
```bash
|
|
569
|
-
npx -y premiere-pro-mcp@1.
|
|
569
|
+
npx -y premiere-pro-mcp@1.17.0 --install-cep
|
|
570
570
|
```
|
|
571
571
|
|
|
572
572
|
The Claude Code package lives in
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.aftereffects.bridge" ExtensionBundleVersion="1.
|
|
2
|
+
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.aftereffects.bridge" ExtensionBundleVersion="1.18.0" ExtensionBundleName="MCP for Adobe After Effects">
|
|
3
3
|
<ExtensionList>
|
|
4
|
-
<Extension Id="com.mcp.aftereffects.bridge.panel" Version="1.
|
|
4
|
+
<Extension Id="com.mcp.aftereffects.bridge.panel" Version="1.18.0"/>
|
|
5
5
|
</ExtensionList>
|
|
6
6
|
<ExecutionEnvironment>
|
|
7
7
|
<HostList>
|
|
Binary file
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.premiere.bridge" ExtensionBundleVersion="1.
|
|
2
|
+
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.premiere.bridge" ExtensionBundleVersion="1.18.0" ExtensionBundleName="MCP for Adobe Premiere Pro">
|
|
3
3
|
<ExtensionList>
|
|
4
|
-
<Extension Id="com.mcp.premiere.bridge.panel" Version="1.
|
|
5
|
-
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.
|
|
4
|
+
<Extension Id="com.mcp.premiere.bridge.panel" Version="1.18.0"/>
|
|
5
|
+
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.18.0"/>
|
|
6
6
|
</ExtensionList>
|
|
7
7
|
<ExecutionEnvironment>
|
|
8
8
|
<HostList>
|
package/cep-plugin/index.html
CHANGED
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
<section class="update-section" aria-live="polite">
|
|
82
82
|
<div class="update-copy">
|
|
83
83
|
<span class="section-label">MCP updates</span>
|
|
84
|
-
<strong id="updateTitle">Version 1.
|
|
84
|
+
<strong id="updateTitle">Version 1.18.0</strong>
|
|
85
85
|
<span id="updateDetail">Checking the global MCP server and connector release…</span>
|
|
86
86
|
</div>
|
|
87
87
|
<button id="btnUpdate" class="button button-update" onclick="handleUpdateClick()" type="button" aria-describedby="updateDetail" disabled>
|
package/cep-plugin/updater.cjs
CHANGED
|
@@ -520,17 +520,29 @@ function __findH264Preset() {
|
|
|
520
520
|
return candidates[0].path;
|
|
521
521
|
}
|
|
522
522
|
|
|
523
|
-
|
|
523
|
+
// Candidate presets for manage_proxies auto-discovery, in preference order:
|
|
524
|
+
// Premiere's IngestPresets/Proxy files first, then AME's H.264 system presets.
|
|
525
|
+
// Adobe ships the Proxy folder presets with a "Same as Project" destination, so
|
|
526
|
+
// the TypeScript handler must content-scan every candidate (gzip-aware) before
|
|
527
|
+
// using one. ExtendScript cannot inflate gzipped .epr files, so no filtering here.
|
|
528
|
+
function __listProxyPresetCandidates() {
|
|
529
|
+
var out = [];
|
|
524
530
|
var ppro = __adobeAppFolders("Adobe Premiere Pro");
|
|
525
531
|
for (var i = 0; i < ppro.length; i++) {
|
|
526
532
|
var proxyDir = __adobeApplicationResourceFolder(ppro[i], "Settings/IngestPresets/Proxy");
|
|
527
533
|
var eprs = __collectEprFiles(proxyDir, []);
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
534
|
+
eprs.sort(function(a, b) { return a.displayName < b.displayName ? -1 : 1; });
|
|
535
|
+
for (var e = 0; e < eprs.length; e++) out.push(eprs[e].fsName);
|
|
536
|
+
}
|
|
537
|
+
var presets = __collectAllPresets();
|
|
538
|
+
for (var p = 0; p < presets.length; p++) {
|
|
539
|
+
var haystack = (presets[p].name + " " + presets[p].format).toLowerCase();
|
|
540
|
+
if (presets[p].path.indexOf("IngestPresets") !== -1) continue;
|
|
541
|
+
if (haystack.indexOf("h264") !== -1 || haystack.indexOf("h.264") !== -1 || haystack.indexOf("48323634") !== -1) {
|
|
542
|
+
out.push(presets[p].path);
|
|
531
543
|
}
|
|
532
544
|
}
|
|
533
|
-
return
|
|
545
|
+
return out;
|
|
534
546
|
}
|
|
535
547
|
|
|
536
548
|
function __findStillPreset(outputPath) {
|
package/dist/http-server.js
CHANGED
|
@@ -35,7 +35,7 @@ import { toNodeHandler } from "@modelcontextprotocol/node";
|
|
|
35
35
|
import { createMcpHandler } from "@modelcontextprotocol/server";
|
|
36
36
|
import { createServer } from "./server.js";
|
|
37
37
|
import { cleanupTempDir, getTempDir } from "./bridge/file-bridge.js";
|
|
38
|
-
import { getTelemetry } from "./telemetry.js";
|
|
38
|
+
import { getTelemetry, telemetryErrorType } from "./telemetry.js";
|
|
39
39
|
import { createHomepageExperiment, injectFirstPaintExposure } from "./homepage-experiment.js";
|
|
40
40
|
import { shouldGzipLanding } from "./landing-compression.js";
|
|
41
41
|
import { LandingDocumentRenderer, assertLandingDocumentSize, readBoundedUtf8, readLandingDocumentSettings, } from "./landing-documents.js";
|
|
@@ -482,7 +482,7 @@ const httpServer = http.createServer(async (req, res) => {
|
|
|
482
482
|
method: req.method ?? "unknown",
|
|
483
483
|
status_code: 500,
|
|
484
484
|
duration_ms: Date.now() - requestStartedAt,
|
|
485
|
-
error_type: err
|
|
485
|
+
error_type: telemetryErrorType(err),
|
|
486
486
|
});
|
|
487
487
|
console.error("[premiere-pro-mcp] Request error:", err);
|
|
488
488
|
if (!res.headersSent) {
|
package/dist/server.js
CHANGED
|
@@ -67,7 +67,7 @@ import { buildPremiereInstructions } from "./workflows/agent-instructions.js";
|
|
|
67
67
|
import { WORKFLOW_PROMPTS, WORKFLOW_RESOURCE } from "./workflows/catalog.js";
|
|
68
68
|
import { annotationsForTool, structuredToolResult, } from "./workflows/tool-metadata.js";
|
|
69
69
|
import { isToolInSelectedPacks, resolveToolPacks, } from "./workflows/tool-packs.js";
|
|
70
|
-
import { getTelemetry } from "./telemetry.js";
|
|
70
|
+
import { getTelemetry, telemetryErrorType } from "./telemetry.js";
|
|
71
71
|
import { z } from "zod";
|
|
72
72
|
import { readFileSync } from "node:fs";
|
|
73
73
|
import { fileURLToPath } from "node:url";
|
|
@@ -360,7 +360,7 @@ export function createServer(bridgeOptions, serverOptions = {}) {
|
|
|
360
360
|
tool: name,
|
|
361
361
|
outcome: "failed",
|
|
362
362
|
duration_ms: Date.now() - startedAt,
|
|
363
|
-
error_type: err
|
|
363
|
+
error_type: telemetryErrorType(err),
|
|
364
364
|
});
|
|
365
365
|
return {
|
|
366
366
|
structuredContent: structuredToolResult(name, false, undefined, err instanceof Error ? err.message : String(err)),
|
package/dist/telemetry.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export interface Telemetry {
|
|
|
4
4
|
capture(event: string, properties?: TelemetryProperties): void;
|
|
5
5
|
shutdown(): Promise<void>;
|
|
6
6
|
}
|
|
7
|
+
/** Error names are mutable and may contain host data; never transmit them raw. */
|
|
8
|
+
export declare function telemetryErrorType(error: unknown): string;
|
|
7
9
|
/**
|
|
8
10
|
* Activation telemetry is deliberately narrower than operational tool
|
|
9
11
|
* telemetry. Emit it only after the read-only connection check has confirmed
|
package/dist/telemetry.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { PostHog } from "posthog-node";
|
|
3
|
+
/** Error names are mutable and may contain host data; never transmit them raw. */
|
|
4
|
+
export function telemetryErrorType(error) {
|
|
5
|
+
if (!(error instanceof Error))
|
|
6
|
+
return "UnknownError";
|
|
7
|
+
return ["Error", "TypeError", "RangeError", "SyntaxError", "ReferenceError", "URIError", "EvalError", "AggregateError"].includes(error.name)
|
|
8
|
+
? error.name
|
|
9
|
+
: "Error";
|
|
10
|
+
}
|
|
3
11
|
/**
|
|
4
12
|
* Activation telemetry is deliberately narrower than operational tool
|
|
5
13
|
* telemetry. Emit it only after the read-only connection check has confirmed
|
|
@@ -59,6 +67,7 @@ export function getTelemetry() {
|
|
|
59
67
|
`server-${randomUUID()}`;
|
|
60
68
|
const client = new PostHog(apiKey, {
|
|
61
69
|
host,
|
|
70
|
+
disableGeoip: true,
|
|
62
71
|
// MCP servers may be idle for long stretches. Flush each bounded operational
|
|
63
72
|
// event promptly so a low-volume deployment remains observable.
|
|
64
73
|
flushAt: 1,
|
package/dist/tools/advanced.d.ts
CHANGED
|
@@ -567,11 +567,19 @@ export declare function getAdvancedTools(bridgeOptions: BridgeOptions): {
|
|
|
567
567
|
type: string;
|
|
568
568
|
description: string;
|
|
569
569
|
};
|
|
570
|
+
expected_values: {
|
|
571
|
+
type: string;
|
|
572
|
+
description: string;
|
|
573
|
+
additionalProperties: {
|
|
574
|
+
type: string;
|
|
575
|
+
};
|
|
576
|
+
};
|
|
570
577
|
};
|
|
571
578
|
required: string[];
|
|
572
579
|
};
|
|
573
580
|
handler: (args: {
|
|
574
581
|
node_id: string;
|
|
582
|
+
expected_values?: Record<string, string>;
|
|
575
583
|
}) => Promise<import("../bridge/file-bridge.js").CommandResult>;
|
|
576
584
|
};
|
|
577
585
|
};
|
package/dist/tools/advanced.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { buildToolScript, escapeForExtendScript, } from "../bridge/script-builder.js";
|
|
2
2
|
import { sendCommand } from "../bridge/file-bridge.js";
|
|
3
|
+
import { compareMogrtText, extractMogrtText, summarizeMogrtText, validateMogrtTextMap } from "./mogrt-text.js";
|
|
3
4
|
import { SPEED_UNAVAILABLE_DESCRIPTION, SPEED_UNAVAILABLE_ERROR } from "./timeline.js";
|
|
4
5
|
export function getAdvancedTools(bridgeOptions) {
|
|
5
6
|
return {
|
|
@@ -1487,7 +1488,7 @@ export function getAdvancedTools(bridgeOptions) {
|
|
|
1487
1488
|
},
|
|
1488
1489
|
},
|
|
1489
1490
|
get_mogrt_component: {
|
|
1490
|
-
description: "Get MOGRT (Motion Graphics Template) component parameters from a clip",
|
|
1491
|
+
description: "Get MOGRT (Motion Graphics Template) component parameters from a clip. Each parameter includes textValue (visible text extracted from textEditValue when present). Pass expected_values to audit text controls such as Headline; the result flags verified, mismatch, or missing_property per field. Reads the stored property, not the Essential Graphics panel display, which Premiere can show stale (host UI behavior this tool cannot refresh).",
|
|
1491
1492
|
parameters: {
|
|
1492
1493
|
type: "object",
|
|
1493
1494
|
properties: {
|
|
@@ -1495,10 +1496,16 @@ export function getAdvancedTools(bridgeOptions) {
|
|
|
1495
1496
|
type: "string",
|
|
1496
1497
|
description: "Node ID of the MOGRT clip on the timeline",
|
|
1497
1498
|
},
|
|
1499
|
+
expected_values: {
|
|
1500
|
+
type: "object",
|
|
1501
|
+
description: "Optional read-only audit map of MOGRT text parameter display names to the text each should contain (for example { \"Headline\": \"Chapter 3\" }). Result audit.status is verified, mismatch, or missing_property.",
|
|
1502
|
+
additionalProperties: { type: "string" },
|
|
1503
|
+
},
|
|
1498
1504
|
},
|
|
1499
1505
|
required: ["node_id"],
|
|
1500
1506
|
},
|
|
1501
1507
|
handler: async (args) => {
|
|
1508
|
+
const expected = validateMogrtTextMap(args.expected_values, "expected_values");
|
|
1502
1509
|
const script = buildToolScript(`
|
|
1503
1510
|
var result = __findClip("${escapeForExtendScript(args.node_id)}");
|
|
1504
1511
|
if (!result) return __error("Clip not found");
|
|
@@ -1517,7 +1524,27 @@ export function getAdvancedTools(bridgeOptions) {
|
|
|
1517
1524
|
|
|
1518
1525
|
return __result({ clipName: result.clip.name, parameters: params });
|
|
1519
1526
|
`);
|
|
1520
|
-
|
|
1527
|
+
const response = await sendCommand(script, bridgeOptions);
|
|
1528
|
+
if (!response.success)
|
|
1529
|
+
return response;
|
|
1530
|
+
const data = (response.data ?? {});
|
|
1531
|
+
const rawParams = Array.isArray(data.parameters) ? data.parameters : [];
|
|
1532
|
+
const parameters = rawParams.map((p) => ({ ...p, textValue: extractMogrtText(p.value) }));
|
|
1533
|
+
if (!expected)
|
|
1534
|
+
return { ...response, data: { ...data, parameters } };
|
|
1535
|
+
const checks = compareMogrtText(expected, parameters);
|
|
1536
|
+
return {
|
|
1537
|
+
...response,
|
|
1538
|
+
data: {
|
|
1539
|
+
...data,
|
|
1540
|
+
parameters,
|
|
1541
|
+
audit: {
|
|
1542
|
+
status: summarizeMogrtText(checks),
|
|
1543
|
+
checks,
|
|
1544
|
+
scope: "Stored MOGRT property values only; the Essential Graphics panel display is not read.",
|
|
1545
|
+
},
|
|
1546
|
+
},
|
|
1547
|
+
};
|
|
1521
1548
|
},
|
|
1522
1549
|
},
|
|
1523
1550
|
};
|
package/dist/tools/export.d.ts
CHANGED
|
@@ -790,7 +790,11 @@ export declare function getExportTools(bridgeOptions: BridgeOptions): {
|
|
|
790
790
|
proxy_path?: string;
|
|
791
791
|
output_path?: string;
|
|
792
792
|
preset_path?: string;
|
|
793
|
-
}) => Promise<import("../bridge/file-bridge.js").CommandResult
|
|
793
|
+
}) => Promise<import("../bridge/file-bridge.js").CommandResult | {
|
|
794
|
+
success: boolean;
|
|
795
|
+
error: string;
|
|
796
|
+
skippedPresetCount: number;
|
|
797
|
+
}>;
|
|
794
798
|
};
|
|
795
799
|
};
|
|
796
800
|
//# sourceMappingURL=export.d.ts.map
|
package/dist/tools/export.js
CHANGED
|
@@ -1331,7 +1331,7 @@ export function getExportTools(bridgeOptions) {
|
|
|
1331
1331
|
outputFile.fsName,
|
|
1332
1332
|
"${escapeForExtendScript(args.preset_path)}",
|
|
1333
1333
|
app.encoder.ENCODE_IN_TO_OUT,
|
|
1334
|
-
${args.remove_on_completion !== false ?
|
|
1334
|
+
${args.remove_on_completion !== false ? "true" : "false"}
|
|
1335
1335
|
);
|
|
1336
1336
|
if (!jobId || String(jobId) === "0") return __error("Adobe Media Encoder did not queue the project-item export.");
|
|
1337
1337
|
app.encoder.startBatch();
|
|
@@ -1411,13 +1411,18 @@ export function getExportTools(bridgeOptions) {
|
|
|
1411
1411
|
var srcOut = new Time();
|
|
1412
1412
|
srcOut.seconds = ${outSeconds};
|
|
1413
1413
|
var workArea = ${hasRange ? 1 : 0};
|
|
1414
|
-
|
|
1414
|
+
var removeUponCompletion = ${args.remove_on_completion !== false ? "true" : "false"};
|
|
1415
|
+
var presetFile = new File("${escapeForExtendScript(args.preset_path)}");
|
|
1416
|
+
if (!presetFile.exists) return __error("AME preset file does not exist: " + presetFile.fsName);
|
|
1417
|
+
|
|
1418
|
+
// Premiere type-checks encodeFile natively: paths must be Strings,
|
|
1419
|
+
// workArea a Number, removeUponCompletion a Boolean, and in/out Time objects.
|
|
1415
1420
|
var jobId = app.encoder.encodeFile(
|
|
1416
|
-
inputFile.fsName,
|
|
1417
|
-
outputFile.fsName,
|
|
1418
|
-
|
|
1421
|
+
String(inputFile.fsName),
|
|
1422
|
+
String(outputFile.fsName),
|
|
1423
|
+
String(presetFile.fsName),
|
|
1419
1424
|
workArea,
|
|
1420
|
-
|
|
1425
|
+
removeUponCompletion,
|
|
1421
1426
|
srcIn,
|
|
1422
1427
|
srcOut
|
|
1423
1428
|
);
|
|
@@ -1467,12 +1472,44 @@ export function getExportTools(bridgeOptions) {
|
|
|
1467
1472
|
preset_path: {
|
|
1468
1473
|
type: "string",
|
|
1469
1474
|
description: "Path to a proxy ingest preset (.epr) for 'create'. " +
|
|
1470
|
-
"If omitted, the
|
|
1475
|
+
"If omitted, the server lists Premiere's IngestPresets/Proxy presets and AME H.264 system presets, " +
|
|
1476
|
+
"skips every preset whose output destination is Same as Project (Adobe's shipped proxy presets are), " +
|
|
1477
|
+
"and uses the first remaining one. Fails with a clear error when none qualify.",
|
|
1471
1478
|
},
|
|
1472
1479
|
},
|
|
1473
1480
|
required: ["item_id", "action"],
|
|
1474
1481
|
},
|
|
1475
1482
|
handler: async (args) => {
|
|
1483
|
+
let presetPath = args.preset_path;
|
|
1484
|
+
const skippedPresets = [];
|
|
1485
|
+
if (args.action === "create" && args.output_path && !presetPath) {
|
|
1486
|
+
const listing = await sendCommand(buildToolScript(`return __result({ candidates: __listProxyPresetCandidates() });`), bridgeOptions);
|
|
1487
|
+
if (!listing.success)
|
|
1488
|
+
return listing;
|
|
1489
|
+
const rawCandidates = listing.data?.candidates;
|
|
1490
|
+
const candidates = Array.isArray(rawCandidates)
|
|
1491
|
+
? rawCandidates.filter((value) => typeof value === "string" && value.length > 0)
|
|
1492
|
+
: [];
|
|
1493
|
+
for (const candidate of candidates) {
|
|
1494
|
+
try {
|
|
1495
|
+
presetPath = inspectExportPresetFile(candidate).path;
|
|
1496
|
+
break;
|
|
1497
|
+
}
|
|
1498
|
+
catch {
|
|
1499
|
+
skippedPresets.push(candidate);
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
if (!presetPath) {
|
|
1503
|
+
return {
|
|
1504
|
+
success: false,
|
|
1505
|
+
error: candidates.length === 0
|
|
1506
|
+
? "Could not locate any proxy or H.264 export preset. Pass preset_path explicitly (an .epr with an explicit output destination)."
|
|
1507
|
+
: `All ${candidates.length} auto-discovered presets use a Same as Project output destination or could not be read, so AME would not write the proxy to output_path. Pass preset_path explicitly (an .epr with an explicit output destination).`,
|
|
1508
|
+
skippedPresetCount: skippedPresets.length,
|
|
1509
|
+
};
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
const autoDiscovered = presetPath !== args.preset_path;
|
|
1476
1513
|
const script = buildToolScript(`
|
|
1477
1514
|
var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
|
|
1478
1515
|
if (!item) return __error("Item not found");
|
|
@@ -1483,12 +1520,7 @@ export function getExportTools(bridgeOptions) {
|
|
|
1483
1520
|
${!args.output_path
|
|
1484
1521
|
? `return __error("output_path is required for the 'create' action");`
|
|
1485
1522
|
: `var outputPath = "${escapeForExtendScript(args.output_path)}";
|
|
1486
|
-
${
|
|
1487
|
-
? `var presetPath = "${escapeForExtendScript(args.preset_path)}";`
|
|
1488
|
-
: `var presetPath = __findProxyPreset();
|
|
1489
|
-
if (!presetPath) {
|
|
1490
|
-
return __error("Could not locate a proxy ingest preset. Pass preset_path explicitly (an .epr under Premiere's Settings/IngestPresets/Proxy folder).");
|
|
1491
|
-
}`}
|
|
1523
|
+
var presetPath = "${escapeForExtendScript(presetPath ?? "")}";
|
|
1492
1524
|
|
|
1493
1525
|
// ProjectItem has no createProxy(). Proxy generation must go through
|
|
1494
1526
|
// Adobe Media Encoder; the result is attached in a separate step once
|
|
@@ -1507,6 +1539,8 @@ export function getExportTools(bridgeOptions) {
|
|
|
1507
1539
|
jobId: String(jobId),
|
|
1508
1540
|
outputPath: outputPath,
|
|
1509
1541
|
presetUsed: presetPath,
|
|
1542
|
+
presetAutoDiscovered: ${autoDiscovered ? "true" : "false"},
|
|
1543
|
+
skippedSameAsProjectPresets: ${skippedPresets.length},
|
|
1510
1544
|
verificationScope: "Premiere returned an AME job ID. Queue presence and proxy-file creation are not verified by this tool.",
|
|
1511
1545
|
nextStep: "Verify the proxy file exists, then call manage_proxies with action 'attach' and proxy_path set to outputPath."
|
|
1512
1546
|
});`}
|
package/dist/tools/media.js
CHANGED
|
@@ -460,23 +460,75 @@ export function getMediaTools(bridgeOptions) {
|
|
|
460
460
|
},
|
|
461
461
|
},
|
|
462
462
|
set_scale_to_frame_size: {
|
|
463
|
-
description: "Enable 'Scale to Frame Size'
|
|
463
|
+
description: "Enable 'Scale to Frame Size' so media fills the sequence frame. Accepts a timeline clip node ID " +
|
|
464
|
+
"(active sequence, same IDs as get_clip_properties) or a project item node ID or name. A timeline " +
|
|
465
|
+
"clip is resolved first and its source project item is updated through ProjectItem.setScaleToFrameSize(). " +
|
|
466
|
+
"ExtendScript exposes no getter for this flag, so the result is committed_unverified unless the timeline " +
|
|
467
|
+
"clip's Motion > Scale reads back changed (verified). Check with get_clip_properties.",
|
|
464
468
|
parameters: {
|
|
465
469
|
type: "object",
|
|
466
470
|
properties: {
|
|
467
471
|
item_id: {
|
|
468
472
|
type: "string",
|
|
469
|
-
description: "
|
|
473
|
+
description: "Timeline clip node ID in the active sequence, or project item node ID or name",
|
|
470
474
|
},
|
|
471
475
|
},
|
|
472
476
|
required: ["item_id"],
|
|
473
477
|
},
|
|
474
478
|
handler: async (args) => {
|
|
475
479
|
const script = buildToolScript(`
|
|
476
|
-
var
|
|
477
|
-
|
|
480
|
+
var requestedId = "${escapeForExtendScript(args.item_id)}";
|
|
481
|
+
function __motionScale(trackItem) {
|
|
482
|
+
try {
|
|
483
|
+
var comps = trackItem.components;
|
|
484
|
+
for (var ci = 0; ci < comps.numItems; ci++) {
|
|
485
|
+
var comp = comps[ci];
|
|
486
|
+
if (comp.displayName !== "Motion" && comp.matchName !== "AE.ADBE Motion") continue;
|
|
487
|
+
for (var pi = 0; pi < comp.properties.numItems; pi++) {
|
|
488
|
+
var prop = comp.properties[pi];
|
|
489
|
+
if (prop.displayName === "Scale") return prop.getValue();
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
} catch (e) {}
|
|
493
|
+
return null;
|
|
494
|
+
}
|
|
495
|
+
var target = "projectItem";
|
|
496
|
+
var trackItem = null;
|
|
497
|
+
var trackInfo = null;
|
|
498
|
+
var item = null;
|
|
499
|
+
var found = __findClip(requestedId);
|
|
500
|
+
if (found) {
|
|
501
|
+
target = "timelineClip";
|
|
502
|
+
trackItem = found.clip;
|
|
503
|
+
trackInfo = { trackType: found.trackType, trackIndex: found.trackIndex, clipIndex: found.clipIndex };
|
|
504
|
+
try { item = trackItem.projectItem; } catch (e) { item = null; }
|
|
505
|
+
if (!item) return __error("Timeline clip " + requestedId + " has no source project item");
|
|
506
|
+
} else {
|
|
507
|
+
item = __findProjectItem(requestedId);
|
|
508
|
+
}
|
|
509
|
+
if (!item) return __error("Item not found: no timeline clip in the active sequence or project item matches " + requestedId);
|
|
510
|
+
var scaleBefore = trackItem ? __motionScale(trackItem) : null;
|
|
478
511
|
item.setScaleToFrameSize();
|
|
479
|
-
|
|
512
|
+
var scaleAfter = trackItem ? __motionScale(trackItem) : null;
|
|
513
|
+
var changed = scaleBefore !== null && scaleAfter !== null && scaleBefore !== scaleAfter;
|
|
514
|
+
var out = {
|
|
515
|
+
set: true,
|
|
516
|
+
target: target,
|
|
517
|
+
item: item.name,
|
|
518
|
+
projectItemNodeId: __nodeIdOf(item),
|
|
519
|
+
status: changed ? "verified" : "committed_unverified",
|
|
520
|
+
motionScaleBefore: scaleBefore,
|
|
521
|
+
motionScaleAfter: scaleAfter
|
|
522
|
+
};
|
|
523
|
+
if (trackItem) {
|
|
524
|
+
out.clipNodeId = String(trackItem.nodeId);
|
|
525
|
+
out.clipName = trackItem.name;
|
|
526
|
+
out.trackType = trackInfo.trackType;
|
|
527
|
+
out.trackIndex = trackInfo.trackIndex;
|
|
528
|
+
out.clipIndex = trackInfo.clipIndex;
|
|
529
|
+
}
|
|
530
|
+
if (!changed) out.note = "ExtendScript has no getter for Scale to Frame Size; confirm with get_clip_properties.";
|
|
531
|
+
return __result(out);
|
|
480
532
|
`);
|
|
481
533
|
return sendCommand(script, bridgeOptions);
|
|
482
534
|
},
|
package/dist/tools/metadata.js
CHANGED
|
@@ -485,7 +485,8 @@ export function getMetadataTools(bridgeOptions) {
|
|
|
485
485
|
} catch (e) {
|
|
486
486
|
return __error("Premiere could not load the Adobe XMP library; no metadata was changed: " + e.toString());
|
|
487
487
|
}
|
|
488
|
-
if (typeof XMPMeta !== "function" || typeof XMPUtils === "undefined" || typeof XMPUtils.appendProperties !== "function"
|
|
488
|
+
if (typeof XMPMeta !== "function" || typeof XMPUtils === "undefined" || typeof XMPUtils.appendProperties !== "function" ||
|
|
489
|
+
typeof XMPConst === "undefined" || typeof XMPConst.APPEND_ALL_PROPERTIES !== "number" || typeof XMPConst.APPEND_REPLACE_OLD_VALUES !== "number") {
|
|
489
490
|
return __error("Premiere's XMP merge APIs are unavailable; no metadata was changed.");
|
|
490
491
|
}
|
|
491
492
|
|
|
@@ -496,7 +497,9 @@ export function getMetadataTools(bridgeOptions) {
|
|
|
496
497
|
var patchXmp = new XMPMeta("${escapeForExtendScript(args.xmp_xml)}");
|
|
497
498
|
// Copy every supplied top-level field into the existing packet, replacing
|
|
498
499
|
// only fields named by the patch and retaining unrelated metadata.
|
|
499
|
-
|
|
500
|
+
// AdobeXMPScript signature: appendProperties(source, dest, options: Number).
|
|
501
|
+
var appendOptions = XMPConst.APPEND_ALL_PROPERTIES | XMPConst.APPEND_REPLACE_OLD_VALUES;
|
|
502
|
+
XMPUtils.appendProperties(patchXmp, existingXmp, appendOptions);
|
|
500
503
|
item.setXMPMetadata(existingXmp.serialize());
|
|
501
504
|
|
|
502
505
|
// Reparse the host readback so a malformed or rejected packet never
|