@synthetic-ai/premiere-mcp 2.0.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 +73 -0
- package/LICENSE +21 -0
- package/README.md +242 -0
- package/cep-plugin/.debug +8 -0
- package/cep-plugin/CSInterface.js +70 -0
- package/cep-plugin/CSXS/manifest.xml +49 -0
- package/cep-plugin/host.jsx +7 -0
- package/cep-plugin/index.html +419 -0
- package/cep-plugin/main.js +327 -0
- package/cep-plugin/premiere.jsx +24947 -0
- package/cep-plugin/synthetic-logo.png +0 -0
- package/dist/bridge/file-bridge.d.ts +29 -0
- package/dist/bridge/file-bridge.js +145 -0
- package/dist/bridge/script-builder.d.ts +19 -0
- package/dist/bridge/script-builder.js +408 -0
- package/dist/http-server.d.ts +21 -0
- package/dist/http-server.js +140 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +70 -0
- package/dist/resources/extendscript-reference.d.ts +2 -0
- package/dist/resources/extendscript-reference.js +219 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +276 -0
- package/dist/tools/advanced.d.ts +530 -0
- package/dist/tools/advanced.js +923 -0
- package/dist/tools/audio-advanced.d.ts +847 -0
- package/dist/tools/audio-advanced.js +1653 -0
- package/dist/tools/audio.d.ts +84 -0
- package/dist/tools/audio.js +123 -0
- package/dist/tools/captions.d.ts +30 -0
- package/dist/tools/captions.js +73 -0
- package/dist/tools/clipboard.d.ts +153 -0
- package/dist/tools/clipboard.js +381 -0
- package/dist/tools/color-advanced.d.ts +821 -0
- package/dist/tools/color-advanced.js +772 -0
- package/dist/tools/discovery.d.ts +128 -0
- package/dist/tools/discovery.js +445 -0
- package/dist/tools/effects.d.ts +211 -0
- package/dist/tools/effects.js +554 -0
- package/dist/tools/export-presets.d.ts +333 -0
- package/dist/tools/export-presets.js +490 -0
- package/dist/tools/export.d.ts +320 -0
- package/dist/tools/export.js +618 -0
- package/dist/tools/health.d.ts +9 -0
- package/dist/tools/health.js +25 -0
- package/dist/tools/inspection.d.ts +179 -0
- package/dist/tools/inspection.js +1089 -0
- package/dist/tools/keyframes.d.ts +253 -0
- package/dist/tools/keyframes.js +611 -0
- package/dist/tools/markers.d.ts +117 -0
- package/dist/tools/markers.js +206 -0
- package/dist/tools/media.d.ts +297 -0
- package/dist/tools/media.js +493 -0
- package/dist/tools/metadata.d.ts +178 -0
- package/dist/tools/metadata.js +278 -0
- package/dist/tools/multicam.d.ts +199 -0
- package/dist/tools/multicam.js +212 -0
- package/dist/tools/playback.d.ts +34 -0
- package/dist/tools/playback.js +63 -0
- package/dist/tools/playhead.d.ts +77 -0
- package/dist/tools/playhead.js +185 -0
- package/dist/tools/project-manager.d.ts +65 -0
- package/dist/tools/project-manager.js +81 -0
- package/dist/tools/project.d.ts +390 -0
- package/dist/tools/project.js +596 -0
- package/dist/tools/scripting.d.ts +98 -0
- package/dist/tools/scripting.js +434 -0
- package/dist/tools/selection.d.ts +120 -0
- package/dist/tools/selection.js +334 -0
- package/dist/tools/sequence-advanced.d.ts +84 -0
- package/dist/tools/sequence-advanced.js +471 -0
- package/dist/tools/sequence-settings.d.ts +397 -0
- package/dist/tools/sequence-settings.js +967 -0
- package/dist/tools/sequence.d.ts +211 -0
- package/dist/tools/sequence.js +378 -0
- package/dist/tools/source-monitor.d.ts +95 -0
- package/dist/tools/source-monitor.js +180 -0
- package/dist/tools/text.d.ts +97 -0
- package/dist/tools/text.js +159 -0
- package/dist/tools/timeline.d.ts +265 -0
- package/dist/tools/timeline.js +575 -0
- package/dist/tools/track-management.d.ts +482 -0
- package/dist/tools/track-management.js +787 -0
- package/dist/tools/track-targeting.d.ts +666 -0
- package/dist/tools/track-targeting.js +1318 -0
- package/dist/tools/tracks.d.ts +90 -0
- package/dist/tools/tracks.js +183 -0
- package/dist/tools/transitions-motion.d.ts +788 -0
- package/dist/tools/transitions-motion.js +680 -0
- package/dist/tools/transitions.d.ts +124 -0
- package/dist/tools/transitions.js +267 -0
- package/dist/tools/utility.d.ts +469 -0
- package/dist/tools/utility.js +1118 -0
- package/dist/tools/workspace.d.ts +25 -0
- package/dist/tools/workspace.js +61 -0
- package/package.json +66 -0
- package/scripts/build-chat-dmg.sh +210 -0
- package/scripts/build-chat-zip.sh +291 -0
- package/scripts/install-cep-windows.ps1 +99 -0
- package/scripts/install-cep.sh +66 -0
- package/scripts/install-chat-plugin.bat +67 -0
- package/scripts/install-chat-plugin.sh +85 -0
- package/scripts/install-windows.bat +95 -0
- package/scripts/package.mjs +218 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { buildToolScript, escapeForExtendScript } from "../bridge/script-builder.js";
|
|
2
|
+
import { sendCommand } from "../bridge/file-bridge.js";
|
|
3
|
+
export function getClipboardTools(bridgeOptions) {
|
|
4
|
+
return {
|
|
5
|
+
copy_effects_between_clips: {
|
|
6
|
+
description: "Copy all effects (or a specific effect) from one clip to another. Does not copy intrinsic properties like Motion/Opacity unless specified.",
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
source_node_id: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Node ID of the source clip to copy effects from",
|
|
13
|
+
},
|
|
14
|
+
target_node_id: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Node ID of the target clip to paste effects to",
|
|
17
|
+
},
|
|
18
|
+
effect_name: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "Specific effect display name to copy (copies all non-intrinsic effects if omitted)",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
required: ["source_node_id", "target_node_id"],
|
|
24
|
+
},
|
|
25
|
+
handler: async (args) => {
|
|
26
|
+
const script = buildToolScript(`
|
|
27
|
+
app.enableQE();
|
|
28
|
+
var srcResult = __findClip("${escapeForExtendScript(args.source_node_id)}");
|
|
29
|
+
if (!srcResult) return __error("Source clip not found");
|
|
30
|
+
var tgtResult = __findClip("${escapeForExtendScript(args.target_node_id)}");
|
|
31
|
+
if (!tgtResult) return __error("Target clip not found");
|
|
32
|
+
|
|
33
|
+
var src = srcResult.clip;
|
|
34
|
+
var tgt = tgtResult.clip;
|
|
35
|
+
var copied = 0;
|
|
36
|
+
var effectFilter = ${args.effect_name ? `"${escapeForExtendScript(args.effect_name)}"` : "null"};
|
|
37
|
+
var intrinsic = ["Motion", "Opacity", "Time Remapping", "Volume", "Channel Volume", "Panner"];
|
|
38
|
+
|
|
39
|
+
// Use QE to copy effects by name
|
|
40
|
+
var qeSeq = qe.project.getActiveSequence();
|
|
41
|
+
var tgtTrackType = tgtResult.trackType;
|
|
42
|
+
var tgtTrack = tgtTrackType === "video"
|
|
43
|
+
? qeSeq.getVideoTrackAt(tgtResult.trackIndex)
|
|
44
|
+
: qeSeq.getAudioTrackAt(tgtResult.trackIndex);
|
|
45
|
+
var qeTgtClip = tgtTrack.getItemAt(tgtResult.clipIndex);
|
|
46
|
+
|
|
47
|
+
for (var i = 0; i < src.components.numItems; i++) {
|
|
48
|
+
var comp = src.components[i];
|
|
49
|
+
var name = comp.displayName;
|
|
50
|
+
|
|
51
|
+
if (effectFilter && name !== effectFilter) continue;
|
|
52
|
+
if (!effectFilter) {
|
|
53
|
+
var skip = false;
|
|
54
|
+
for (var k = 0; k < intrinsic.length; k++) {
|
|
55
|
+
if (name === intrinsic[k]) { skip = true; break; }
|
|
56
|
+
}
|
|
57
|
+
if (skip) continue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Apply effect via QE
|
|
61
|
+
try {
|
|
62
|
+
var qeEffect = tgtTrackType === "video"
|
|
63
|
+
? qe.project.getVideoEffectByName(name)
|
|
64
|
+
: qe.project.getAudioEffectByName(name);
|
|
65
|
+
if (qeEffect) {
|
|
66
|
+
if (tgtTrackType === "video") {
|
|
67
|
+
qeTgtClip.addVideoEffect(qeEffect);
|
|
68
|
+
} else {
|
|
69
|
+
qeTgtClip.addAudioEffect(qeEffect);
|
|
70
|
+
}
|
|
71
|
+
copied++;
|
|
72
|
+
}
|
|
73
|
+
} catch(e) {}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return __result({ copiedEffects: copied, source: src.name, target: tgt.name });
|
|
77
|
+
`);
|
|
78
|
+
return sendCommand(script, bridgeOptions);
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
copy_effect_values: {
|
|
82
|
+
description: "Copy all property values from one effect to the matching effect on another clip. Both clips must already have the same effect applied.",
|
|
83
|
+
parameters: {
|
|
84
|
+
type: "object",
|
|
85
|
+
properties: {
|
|
86
|
+
source_node_id: {
|
|
87
|
+
type: "string",
|
|
88
|
+
description: "Node ID of the source clip",
|
|
89
|
+
},
|
|
90
|
+
target_node_id: {
|
|
91
|
+
type: "string",
|
|
92
|
+
description: "Node ID of the target clip",
|
|
93
|
+
},
|
|
94
|
+
effect_name: {
|
|
95
|
+
type: "string",
|
|
96
|
+
description: "Display name of the effect to copy values for",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
required: ["source_node_id", "target_node_id", "effect_name"],
|
|
100
|
+
},
|
|
101
|
+
handler: async (args) => {
|
|
102
|
+
const script = buildToolScript(`
|
|
103
|
+
var srcResult = __findClip("${escapeForExtendScript(args.source_node_id)}");
|
|
104
|
+
if (!srcResult) return __error("Source clip not found");
|
|
105
|
+
var tgtResult = __findClip("${escapeForExtendScript(args.target_node_id)}");
|
|
106
|
+
if (!tgtResult) return __error("Target clip not found");
|
|
107
|
+
|
|
108
|
+
var srcComp = null;
|
|
109
|
+
var tgtComp = null;
|
|
110
|
+
for (var i = 0; i < srcResult.clip.components.numItems; i++) {
|
|
111
|
+
if (srcResult.clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}") {
|
|
112
|
+
srcComp = srcResult.clip.components[i];
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (!srcComp) return __error("Effect not found on source clip: ${escapeForExtendScript(args.effect_name)}");
|
|
117
|
+
|
|
118
|
+
for (var i = 0; i < tgtResult.clip.components.numItems; i++) {
|
|
119
|
+
if (tgtResult.clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}") {
|
|
120
|
+
tgtComp = tgtResult.clip.components[i];
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (!tgtComp) return __error("Effect not found on target clip: ${escapeForExtendScript(args.effect_name)}");
|
|
125
|
+
|
|
126
|
+
var copied = 0;
|
|
127
|
+
for (var p = 0; p < srcComp.properties.numItems; p++) {
|
|
128
|
+
var srcProp = srcComp.properties[p];
|
|
129
|
+
for (var q = 0; q < tgtComp.properties.numItems; q++) {
|
|
130
|
+
if (tgtComp.properties[q].displayName === srcProp.displayName) {
|
|
131
|
+
try {
|
|
132
|
+
var val = srcProp.getValue(0, 0);
|
|
133
|
+
tgtComp.properties[q].setValue(val, true);
|
|
134
|
+
copied++;
|
|
135
|
+
} catch(e) {}
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return __result({ copiedProperties: copied, effect: "${escapeForExtendScript(args.effect_name)}" });
|
|
142
|
+
`);
|
|
143
|
+
return sendCommand(script, bridgeOptions);
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
replace_clip_media: {
|
|
147
|
+
description: "Replace the source media of a clip on the timeline with a different project item, keeping the clip's position and duration.",
|
|
148
|
+
parameters: {
|
|
149
|
+
type: "object",
|
|
150
|
+
properties: {
|
|
151
|
+
clip_node_id: {
|
|
152
|
+
type: "string",
|
|
153
|
+
description: "Node ID of the timeline clip to replace media on",
|
|
154
|
+
},
|
|
155
|
+
new_item_id: {
|
|
156
|
+
type: "string",
|
|
157
|
+
description: "Node ID or name of the new source project item",
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
required: ["clip_node_id", "new_item_id"],
|
|
161
|
+
},
|
|
162
|
+
handler: async (args) => {
|
|
163
|
+
const script = buildToolScript(`
|
|
164
|
+
var clipResult = __findClip("${escapeForExtendScript(args.clip_node_id)}");
|
|
165
|
+
if (!clipResult) return __error("Clip not found");
|
|
166
|
+
var newItem = __findProjectItem("${escapeForExtendScript(args.new_item_id)}");
|
|
167
|
+
if (!newItem) return __error("New project item not found: ${escapeForExtendScript(args.new_item_id)}");
|
|
168
|
+
|
|
169
|
+
var clip = clipResult.clip;
|
|
170
|
+
var seq = app.project.activeSequence;
|
|
171
|
+
var startTicks = clip.start.ticks.toString();
|
|
172
|
+
var trackType = clipResult.trackType;
|
|
173
|
+
var trackIndex = clipResult.trackIndex;
|
|
174
|
+
|
|
175
|
+
// Overwrite at the same position with new media
|
|
176
|
+
if (trackType === "video") {
|
|
177
|
+
seq.overwriteClip(newItem, startTicks, trackIndex, -1);
|
|
178
|
+
} else {
|
|
179
|
+
seq.overwriteClip(newItem, startTicks, -1, trackIndex);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return __result({ replaced: true, clipName: clip.name, newSource: newItem.name });
|
|
183
|
+
`);
|
|
184
|
+
return sendCommand(script, bridgeOptions);
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
batch_apply_effect: {
|
|
188
|
+
description: "Apply an effect to multiple clips at once. Can target selected clips, all clips on a track, or all clips in the sequence.",
|
|
189
|
+
parameters: {
|
|
190
|
+
type: "object",
|
|
191
|
+
properties: {
|
|
192
|
+
effect_name: {
|
|
193
|
+
type: "string",
|
|
194
|
+
description: "Display name of the effect to apply (e.g., 'Gaussian Blur', 'Lumetri Color')",
|
|
195
|
+
},
|
|
196
|
+
target: {
|
|
197
|
+
type: "string",
|
|
198
|
+
enum: ["selected", "track", "all"],
|
|
199
|
+
description: "Which clips to apply to: selected clips, all on a track, or all in sequence",
|
|
200
|
+
},
|
|
201
|
+
track_type: {
|
|
202
|
+
type: "string",
|
|
203
|
+
enum: ["video", "audio"],
|
|
204
|
+
description: "Track type (required when target is 'track')",
|
|
205
|
+
},
|
|
206
|
+
track_index: {
|
|
207
|
+
type: "number",
|
|
208
|
+
description: "Track index (required when target is 'track')",
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
required: ["effect_name", "target"],
|
|
212
|
+
},
|
|
213
|
+
handler: async (args) => {
|
|
214
|
+
const script = buildToolScript(`
|
|
215
|
+
app.enableQE();
|
|
216
|
+
var seq = app.project.activeSequence;
|
|
217
|
+
if (!seq) return __error("No active sequence");
|
|
218
|
+
var qeSeq = qe.project.getActiveSequence();
|
|
219
|
+
|
|
220
|
+
var effectName = "${escapeForExtendScript(args.effect_name)}";
|
|
221
|
+
var qeEffect = qe.project.getVideoEffectByName(effectName);
|
|
222
|
+
var isAudio = false;
|
|
223
|
+
if (!qeEffect) {
|
|
224
|
+
qeEffect = qe.project.getAudioEffectByName(effectName);
|
|
225
|
+
isAudio = true;
|
|
226
|
+
}
|
|
227
|
+
if (!qeEffect) return __error("Effect not found: " + effectName);
|
|
228
|
+
|
|
229
|
+
var applied = 0;
|
|
230
|
+
var target = "${args.target}";
|
|
231
|
+
|
|
232
|
+
function applyToClip(trackIdx, clipIdx, trackType) {
|
|
233
|
+
try {
|
|
234
|
+
var qeTrack = trackType === "video" ? qeSeq.getVideoTrackAt(trackIdx) : qeSeq.getAudioTrackAt(trackIdx);
|
|
235
|
+
var qeClip = qeTrack.getItemAt(clipIdx);
|
|
236
|
+
if (isAudio || trackType === "audio") {
|
|
237
|
+
qeClip.addAudioEffect(qeEffect);
|
|
238
|
+
} else {
|
|
239
|
+
qeClip.addVideoEffect(qeEffect);
|
|
240
|
+
}
|
|
241
|
+
applied++;
|
|
242
|
+
} catch(e) {}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (target === "selected") {
|
|
246
|
+
for (var t = 0; t < seq.videoTracks.numTracks; t++) {
|
|
247
|
+
for (var c = 0; c < seq.videoTracks[t].clips.numItems; c++) {
|
|
248
|
+
if (seq.videoTracks[t].clips[c].isSelected()) applyToClip(t, c, "video");
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
for (var t = 0; t < seq.audioTracks.numTracks; t++) {
|
|
252
|
+
for (var c = 0; c < seq.audioTracks[t].clips.numItems; c++) {
|
|
253
|
+
if (seq.audioTracks[t].clips[c].isSelected()) applyToClip(t, c, "audio");
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
} else if (target === "track") {
|
|
257
|
+
var tt = "${args.track_type || "video"}";
|
|
258
|
+
var ti = ${args.track_index ?? 0};
|
|
259
|
+
var tracks = tt === "video" ? seq.videoTracks : seq.audioTracks;
|
|
260
|
+
if (ti >= tracks.numTracks) return __error("Track index out of range");
|
|
261
|
+
for (var c = 0; c < tracks[ti].clips.numItems; c++) {
|
|
262
|
+
applyToClip(ti, c, tt);
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
for (var t = 0; t < seq.videoTracks.numTracks; t++) {
|
|
266
|
+
for (var c = 0; c < seq.videoTracks[t].clips.numItems; c++) applyToClip(t, c, "video");
|
|
267
|
+
}
|
|
268
|
+
for (var t = 0; t < seq.audioTracks.numTracks; t++) {
|
|
269
|
+
for (var c = 0; c < seq.audioTracks[t].clips.numItems; c++) applyToClip(t, c, "audio");
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return __result({ applied: applied, effect: effectName, target: target });
|
|
274
|
+
`);
|
|
275
|
+
return sendCommand(script, bridgeOptions);
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
remove_effect_by_name: {
|
|
279
|
+
description: "Remove all instances of a specific effect from a clip by display name.",
|
|
280
|
+
parameters: {
|
|
281
|
+
type: "object",
|
|
282
|
+
properties: {
|
|
283
|
+
node_id: {
|
|
284
|
+
type: "string",
|
|
285
|
+
description: "Node ID of the clip",
|
|
286
|
+
},
|
|
287
|
+
effect_name: {
|
|
288
|
+
type: "string",
|
|
289
|
+
description: "Display name of the effect to remove",
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
required: ["node_id", "effect_name"],
|
|
293
|
+
},
|
|
294
|
+
handler: async (args) => {
|
|
295
|
+
const script = buildToolScript(`
|
|
296
|
+
var result = __findClip("${escapeForExtendScript(args.node_id)}");
|
|
297
|
+
if (!result) return __error("Clip not found");
|
|
298
|
+
|
|
299
|
+
var clip = result.clip;
|
|
300
|
+
var removed = 0;
|
|
301
|
+
// Iterate backwards to avoid index issues when removing
|
|
302
|
+
for (var i = clip.components.numItems - 1; i >= 0; i--) {
|
|
303
|
+
if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}") {
|
|
304
|
+
clip.components[i].remove();
|
|
305
|
+
removed++;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (removed === 0) return __error("Effect not found: ${escapeForExtendScript(args.effect_name)}");
|
|
310
|
+
return __result({ removed: removed, effect: "${escapeForExtendScript(args.effect_name)}", clip: clip.name });
|
|
311
|
+
`);
|
|
312
|
+
return sendCommand(script, bridgeOptions);
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
set_blend_mode: {
|
|
316
|
+
description: "Set the blend mode on a video clip. Uses the Opacity effect's Blend Mode property.",
|
|
317
|
+
parameters: {
|
|
318
|
+
type: "object",
|
|
319
|
+
properties: {
|
|
320
|
+
node_id: {
|
|
321
|
+
type: "string",
|
|
322
|
+
description: "Node ID of the video clip",
|
|
323
|
+
},
|
|
324
|
+
blend_mode: {
|
|
325
|
+
type: "string",
|
|
326
|
+
enum: [
|
|
327
|
+
"Normal", "Dissolve", "Darken", "Multiply", "Color Burn", "Linear Burn", "Darker Color",
|
|
328
|
+
"Lighten", "Screen", "Color Dodge", "Linear Dodge", "Lighter Color",
|
|
329
|
+
"Overlay", "Soft Light", "Hard Light", "Vivid Light", "Linear Light", "Pin Light", "Hard Mix",
|
|
330
|
+
"Difference", "Exclusion", "Subtract", "Divide",
|
|
331
|
+
"Hue", "Saturation", "Color", "Luminosity"
|
|
332
|
+
],
|
|
333
|
+
description: "Blend mode name",
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
required: ["node_id", "blend_mode"],
|
|
337
|
+
},
|
|
338
|
+
handler: async (args) => {
|
|
339
|
+
const blendModeMap = {
|
|
340
|
+
"Normal": 1, "Dissolve": 2, "Darken": 3, "Multiply": 4, "Color Burn": 5,
|
|
341
|
+
"Linear Burn": 6, "Darker Color": 7, "Lighten": 8, "Screen": 9, "Color Dodge": 10,
|
|
342
|
+
"Linear Dodge": 11, "Lighter Color": 12, "Overlay": 13, "Soft Light": 14,
|
|
343
|
+
"Hard Light": 15, "Vivid Light": 16, "Linear Light": 17, "Pin Light": 18,
|
|
344
|
+
"Hard Mix": 19, "Difference": 20, "Exclusion": 21, "Subtract": 22, "Divide": 23,
|
|
345
|
+
"Hue": 24, "Saturation": 25, "Color": 26, "Luminosity": 27
|
|
346
|
+
};
|
|
347
|
+
const modeValue = blendModeMap[args.blend_mode] ?? 1;
|
|
348
|
+
const script = buildToolScript(`
|
|
349
|
+
var result = __findClip("${escapeForExtendScript(args.node_id)}");
|
|
350
|
+
if (!result) return __error("Clip not found");
|
|
351
|
+
|
|
352
|
+
var clip = result.clip;
|
|
353
|
+
var comp = __findIntrinsic(clip, "opacity");
|
|
354
|
+
if (!comp) return __error("Could not find Opacity component on clip");
|
|
355
|
+
|
|
356
|
+
var prop = __findProp(comp, ["Blend Mode", "Modo de fusión", "Mischmodus"]);
|
|
357
|
+
if (!prop) return __error("Could not find Blend Mode property on Opacity component");
|
|
358
|
+
|
|
359
|
+
var applied = false;
|
|
360
|
+
var note = "Blend mode enum ordering can vary by Premiere version/locale; if the visual result is wrong, the numeric mapping may differ for this version.";
|
|
361
|
+
try {
|
|
362
|
+
prop.setValue(${modeValue}, true);
|
|
363
|
+
applied = true;
|
|
364
|
+
} catch(e) {
|
|
365
|
+
note = "setValue failed: " + e.toString() + ". " + note;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return __result({
|
|
369
|
+
blendMode: "${escapeForExtendScript(args.blend_mode)}",
|
|
370
|
+
enumValue: ${modeValue},
|
|
371
|
+
applied: applied,
|
|
372
|
+
note: note,
|
|
373
|
+
clip: clip.name
|
|
374
|
+
});
|
|
375
|
+
`);
|
|
376
|
+
return sendCommand(script, bridgeOptions);
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
//# sourceMappingURL=clipboard.js.map
|