@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.
- package/CHANGELOG.md +135 -123
- package/LICENSE +21 -21
- package/README.md +242 -242
- package/cep-plugin/.debug +8 -8
- package/cep-plugin/CSInterface.js +92 -92
- package/cep-plugin/host.jsx +7 -7
- package/cep-plugin/index.html +472 -472
- package/cep-plugin/main.js +6 -0
- package/cep-plugin/premiere.jsx +24947 -24947
- package/dist/bridge/script-builder.js +378 -378
- package/dist/index.js +103 -4
- package/dist/license.js +38 -0
- package/dist/server.js +60 -60
- package/dist/tools/advanced.js +357 -357
- package/dist/tools/audio-advanced.js +1049 -1049
- package/dist/tools/audio.js +42 -42
- package/dist/tools/captions.js +27 -27
- package/dist/tools/clipboard.js +214 -214
- package/dist/tools/color-advanced.js +253 -253
- package/dist/tools/discovery.js +291 -291
- package/dist/tools/effects.js +285 -285
- package/dist/tools/export-presets.js +206 -206
- package/dist/tools/export.js +255 -255
- package/dist/tools/health.js +10 -10
- package/dist/tools/inspection.js +885 -885
- package/dist/tools/keyframes.js +369 -369
- package/dist/tools/markers.js +89 -89
- package/dist/tools/media.js +178 -178
- package/dist/tools/metadata.js +94 -94
- package/dist/tools/multicam.js +50 -50
- package/dist/tools/playback.js +15 -15
- package/dist/tools/playhead.js +95 -95
- package/dist/tools/project-manager.js +21 -21
- package/dist/tools/project.js +149 -149
- package/dist/tools/scripting.js +319 -319
- package/dist/tools/selection.js +202 -202
- package/dist/tools/sequence-advanced.js +379 -379
- package/dist/tools/sequence-settings.js +564 -564
- package/dist/tools/sequence.js +167 -167
- package/dist/tools/source-monitor.js +68 -68
- package/dist/tools/text.js +58 -58
- package/dist/tools/timeline.js +312 -312
- package/dist/tools/track-management.js +446 -446
- package/dist/tools/track-targeting.js +635 -635
- package/dist/tools/tracks.js +87 -87
- package/dist/tools/transitions-motion.js +174 -174
- package/dist/tools/transitions.js +111 -111
- package/dist/tools/utility.js +606 -606
- package/dist/tools/workspace.js +29 -29
- package/package.json +66 -66
- package/scripts/build-chat-dmg.sh +210 -210
- package/scripts/build-chat-zip.sh +291 -291
- package/scripts/install-cep-windows.ps1 +99 -99
- package/scripts/install-cep.sh +66 -66
- package/scripts/install-chat-plugin.bat +67 -67
- package/scripts/install-chat-plugin.sh +85 -85
- package/scripts/install-windows.bat +95 -95
- package/scripts/package.mjs +254 -254
package/dist/tools/utility.js
CHANGED
|
@@ -15,13 +15,13 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
15
15
|
required: ["item_id"],
|
|
16
16
|
},
|
|
17
17
|
handler: async (args) => {
|
|
18
|
-
const script = buildToolScript(`
|
|
19
|
-
var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
|
|
20
|
-
if (!item) return __error("Item not found: ${escapeForExtendScript(args.item_id)}");
|
|
21
|
-
|
|
22
|
-
var name = item.name;
|
|
23
|
-
app.project.deleteProjectItem(item);
|
|
24
|
-
return __result({ deleted: true, name: name });
|
|
18
|
+
const script = buildToolScript(`
|
|
19
|
+
var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
|
|
20
|
+
if (!item) return __error("Item not found: ${escapeForExtendScript(args.item_id)}");
|
|
21
|
+
|
|
22
|
+
var name = item.name;
|
|
23
|
+
app.project.deleteProjectItem(item);
|
|
24
|
+
return __result({ deleted: true, name: name });
|
|
25
25
|
`);
|
|
26
26
|
return sendCommand(script, bridgeOptions);
|
|
27
27
|
},
|
|
@@ -40,18 +40,18 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
40
40
|
},
|
|
41
41
|
handler: async (args) => {
|
|
42
42
|
const idsJson = JSON.stringify(args.item_ids);
|
|
43
|
-
const script = buildToolScript(`
|
|
44
|
-
var ids = ${idsJson};
|
|
45
|
-
var deleted = 0;
|
|
46
|
-
var names = [];
|
|
47
|
-
for (var i = 0; i < ids.length; i++) {
|
|
48
|
-
var item = __findProjectItem(ids[i]);
|
|
49
|
-
if (item) {
|
|
50
|
-
names.push(item.name);
|
|
51
|
-
try { app.project.deleteProjectItem(item); deleted++; } catch(e) {}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return __result({ deleted: deleted, total: ids.length, names: names });
|
|
43
|
+
const script = buildToolScript(`
|
|
44
|
+
var ids = ${idsJson};
|
|
45
|
+
var deleted = 0;
|
|
46
|
+
var names = [];
|
|
47
|
+
for (var i = 0; i < ids.length; i++) {
|
|
48
|
+
var item = __findProjectItem(ids[i]);
|
|
49
|
+
if (item) {
|
|
50
|
+
names.push(item.name);
|
|
51
|
+
try { app.project.deleteProjectItem(item); deleted++; } catch(e) {}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return __result({ deleted: deleted, total: ids.length, names: names });
|
|
55
55
|
`);
|
|
56
56
|
return sendCommand(script, bridgeOptions);
|
|
57
57
|
},
|
|
@@ -73,13 +73,13 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
73
73
|
required: ["item_id", "new_name"],
|
|
74
74
|
},
|
|
75
75
|
handler: async (args) => {
|
|
76
|
-
const script = buildToolScript(`
|
|
77
|
-
var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
|
|
78
|
-
if (!item) return __error("Item not found");
|
|
79
|
-
|
|
80
|
-
var oldName = item.name;
|
|
81
|
-
item.name = "${escapeForExtendScript(args.new_name)}";
|
|
82
|
-
return __result({ oldName: oldName, newName: item.name });
|
|
76
|
+
const script = buildToolScript(`
|
|
77
|
+
var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
|
|
78
|
+
if (!item) return __error("Item not found");
|
|
79
|
+
|
|
80
|
+
var oldName = item.name;
|
|
81
|
+
item.name = "${escapeForExtendScript(args.new_name)}";
|
|
82
|
+
return __result({ oldName: oldName, newName: item.name });
|
|
83
83
|
`);
|
|
84
84
|
return sendCommand(script, bridgeOptions);
|
|
85
85
|
},
|
|
@@ -97,22 +97,22 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
97
97
|
},
|
|
98
98
|
handler: async (args) => {
|
|
99
99
|
const track = args.track_index ?? 0;
|
|
100
|
-
const script = buildToolScript(`
|
|
101
|
-
var seq = app.project.activeSequence;
|
|
102
|
-
if (!seq) return __error("No active sequence");
|
|
103
|
-
|
|
104
|
-
app.enableQE();
|
|
105
|
-
try {
|
|
106
|
-
var qeSeq = qe.project.getActiveSequence();
|
|
107
|
-
qeSeq.addAdjustmentLayer(${track});
|
|
108
|
-
|
|
109
|
-
return __result({
|
|
110
|
-
added: true,
|
|
111
|
-
trackIndex: ${track}
|
|
112
|
-
});
|
|
113
|
-
} catch(e) {
|
|
114
|
-
return __error("Failed to add adjustment layer: " + e.message);
|
|
115
|
-
}
|
|
100
|
+
const script = buildToolScript(`
|
|
101
|
+
var seq = app.project.activeSequence;
|
|
102
|
+
if (!seq) return __error("No active sequence");
|
|
103
|
+
|
|
104
|
+
app.enableQE();
|
|
105
|
+
try {
|
|
106
|
+
var qeSeq = qe.project.getActiveSequence();
|
|
107
|
+
qeSeq.addAdjustmentLayer(${track});
|
|
108
|
+
|
|
109
|
+
return __result({
|
|
110
|
+
added: true,
|
|
111
|
+
trackIndex: ${track}
|
|
112
|
+
});
|
|
113
|
+
} catch(e) {
|
|
114
|
+
return __error("Failed to add adjustment layer: " + e.message);
|
|
115
|
+
}
|
|
116
116
|
`);
|
|
117
117
|
return sendCommand(script, bridgeOptions);
|
|
118
118
|
},
|
|
@@ -138,26 +138,26 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
138
138
|
required: ["output_path"],
|
|
139
139
|
},
|
|
140
140
|
handler: async (args) => {
|
|
141
|
-
const script = buildToolScript(`
|
|
142
|
-
var seq = app.project.activeSequence;
|
|
143
|
-
if (!seq) return __error("No active sequence");
|
|
144
|
-
|
|
141
|
+
const script = buildToolScript(`
|
|
142
|
+
var seq = app.project.activeSequence;
|
|
143
|
+
if (!seq) return __error("No active sequence");
|
|
144
|
+
|
|
145
145
|
${args.time_seconds !== undefined
|
|
146
146
|
? `var timeTicks = __secondsToTicks(${args.time_seconds}).toString();`
|
|
147
|
-
: `var timeTicks = seq.getPlayerPosition().ticks;`}
|
|
148
|
-
|
|
149
|
-
// Export frame
|
|
150
|
-
seq.exportFramePNG(timeTicks, "${escapeForExtendScript(args.output_path)}");
|
|
151
|
-
|
|
152
|
-
// Import back
|
|
153
|
-
app.project.importFiles(["${escapeForExtendScript(args.output_path)}"], false, app.project.rootItem, false);
|
|
154
|
-
|
|
155
|
-
return __result({
|
|
156
|
-
exported: true,
|
|
157
|
-
path: "${escapeForExtendScript(args.output_path)}",
|
|
158
|
-
atSeconds: __ticksToSeconds(timeTicks),
|
|
159
|
-
note: "Frame exported and imported. Add to timeline with add_to_timeline."
|
|
160
|
-
});
|
|
147
|
+
: `var timeTicks = seq.getPlayerPosition().ticks;`}
|
|
148
|
+
|
|
149
|
+
// Export frame
|
|
150
|
+
seq.exportFramePNG(timeTicks, "${escapeForExtendScript(args.output_path)}");
|
|
151
|
+
|
|
152
|
+
// Import back
|
|
153
|
+
app.project.importFiles(["${escapeForExtendScript(args.output_path)}"], false, app.project.rootItem, false);
|
|
154
|
+
|
|
155
|
+
return __result({
|
|
156
|
+
exported: true,
|
|
157
|
+
path: "${escapeForExtendScript(args.output_path)}",
|
|
158
|
+
atSeconds: __ticksToSeconds(timeTicks),
|
|
159
|
+
note: "Frame exported and imported. Add to timeline with add_to_timeline."
|
|
160
|
+
});
|
|
161
161
|
`);
|
|
162
162
|
return sendCommand(script, bridgeOptions);
|
|
163
163
|
},
|
|
@@ -175,26 +175,26 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
175
175
|
required: ["frame_rate"],
|
|
176
176
|
},
|
|
177
177
|
handler: async (args) => {
|
|
178
|
-
const script = buildToolScript(`
|
|
179
|
-
var seq = app.project.activeSequence;
|
|
180
|
-
if (!seq) return __error("No active sequence");
|
|
181
|
-
|
|
182
|
-
var settings = seq.getSettings();
|
|
183
|
-
if (!settings) return __error("Could not get sequence settings");
|
|
184
|
-
|
|
185
|
-
var fps = ${args.frame_rate};
|
|
186
|
-
if (!fps || fps <= 0) return __error("Invalid frame rate: " + fps);
|
|
187
|
-
|
|
188
|
-
try {
|
|
189
|
-
var t = new Time();
|
|
190
|
-
t.ticks = Math.round(TICKS_PER_SECOND / fps).toString();
|
|
191
|
-
settings.videoFrameRate = t;
|
|
192
|
-
seq.setSettings(settings);
|
|
193
|
-
} catch(e) {
|
|
194
|
-
return __error("Failed to set frame rate: " + e.message);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return __result({ frameRate: fps, ticksPerFrame: Math.round(TICKS_PER_SECOND / fps), sequence: seq.name });
|
|
178
|
+
const script = buildToolScript(`
|
|
179
|
+
var seq = app.project.activeSequence;
|
|
180
|
+
if (!seq) return __error("No active sequence");
|
|
181
|
+
|
|
182
|
+
var settings = seq.getSettings();
|
|
183
|
+
if (!settings) return __error("Could not get sequence settings");
|
|
184
|
+
|
|
185
|
+
var fps = ${args.frame_rate};
|
|
186
|
+
if (!fps || fps <= 0) return __error("Invalid frame rate: " + fps);
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
var t = new Time();
|
|
190
|
+
t.ticks = Math.round(TICKS_PER_SECOND / fps).toString();
|
|
191
|
+
settings.videoFrameRate = t;
|
|
192
|
+
seq.setSettings(settings);
|
|
193
|
+
} catch(e) {
|
|
194
|
+
return __error("Failed to set frame rate: " + e.message);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return __result({ frameRate: fps, ticksPerFrame: Math.round(TICKS_PER_SECOND / fps), sequence: seq.name });
|
|
198
198
|
`);
|
|
199
199
|
return sendCommand(script, bridgeOptions);
|
|
200
200
|
},
|
|
@@ -216,18 +216,18 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
216
216
|
required: ["width", "height"],
|
|
217
217
|
},
|
|
218
218
|
handler: async (args) => {
|
|
219
|
-
const script = buildToolScript(`
|
|
220
|
-
var seq = app.project.activeSequence;
|
|
221
|
-
if (!seq) return __error("No active sequence");
|
|
222
|
-
|
|
223
|
-
var settings = seq.getSettings();
|
|
224
|
-
if (!settings) return __error("Could not get sequence settings");
|
|
225
|
-
|
|
226
|
-
settings.videoFrameWidth = ${args.width};
|
|
227
|
-
settings.videoFrameHeight = ${args.height};
|
|
228
|
-
seq.setSettings(settings);
|
|
229
|
-
|
|
230
|
-
return __result({ width: ${args.width}, height: ${args.height}, sequence: seq.name });
|
|
219
|
+
const script = buildToolScript(`
|
|
220
|
+
var seq = app.project.activeSequence;
|
|
221
|
+
if (!seq) return __error("No active sequence");
|
|
222
|
+
|
|
223
|
+
var settings = seq.getSettings();
|
|
224
|
+
if (!settings) return __error("Could not get sequence settings");
|
|
225
|
+
|
|
226
|
+
settings.videoFrameWidth = ${args.width};
|
|
227
|
+
settings.videoFrameHeight = ${args.height};
|
|
228
|
+
seq.setSettings(settings);
|
|
229
|
+
|
|
230
|
+
return __result({ width: ${args.width}, height: ${args.height}, sequence: seq.name });
|
|
231
231
|
`);
|
|
232
232
|
return sendCommand(script, bridgeOptions);
|
|
233
233
|
},
|
|
@@ -248,18 +248,18 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
248
248
|
},
|
|
249
249
|
},
|
|
250
250
|
handler: async (args) => {
|
|
251
|
-
const script = buildToolScript(`
|
|
252
|
-
var seq = app.project.activeSequence;
|
|
253
|
-
if (!seq) return __error("No active sequence");
|
|
254
|
-
|
|
255
|
-
var settings = seq.getSettings();
|
|
256
|
-
if (!settings) return __error("Could not get sequence settings");
|
|
257
|
-
|
|
258
|
-
${args.sample_rate !== undefined ? `settings.audioSampleRate = ${args.sample_rate};` : ""}
|
|
259
|
-
${args.channel_type !== undefined ? `settings.audioChannelType = ${args.channel_type};` : ""}
|
|
260
|
-
seq.setSettings(settings);
|
|
261
|
-
|
|
262
|
-
return __result({ sequence: seq.name, sampleRate: settings.audioSampleRate, channelType: settings.audioChannelType });
|
|
251
|
+
const script = buildToolScript(`
|
|
252
|
+
var seq = app.project.activeSequence;
|
|
253
|
+
if (!seq) return __error("No active sequence");
|
|
254
|
+
|
|
255
|
+
var settings = seq.getSettings();
|
|
256
|
+
if (!settings) return __error("Could not get sequence settings");
|
|
257
|
+
|
|
258
|
+
${args.sample_rate !== undefined ? `settings.audioSampleRate = ${args.sample_rate};` : ""}
|
|
259
|
+
${args.channel_type !== undefined ? `settings.audioChannelType = ${args.channel_type};` : ""}
|
|
260
|
+
seq.setSettings(settings);
|
|
261
|
+
|
|
262
|
+
return __result({ sequence: seq.name, sampleRate: settings.audioSampleRate, channelType: settings.audioChannelType });
|
|
263
263
|
`);
|
|
264
264
|
return sendCommand(script, bridgeOptions);
|
|
265
265
|
},
|
|
@@ -277,17 +277,17 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
277
277
|
required: ["ratio"],
|
|
278
278
|
},
|
|
279
279
|
handler: async (args) => {
|
|
280
|
-
const script = buildToolScript(`
|
|
281
|
-
var seq = app.project.activeSequence;
|
|
282
|
-
if (!seq) return __error("No active sequence");
|
|
283
|
-
|
|
284
|
-
var settings = seq.getSettings();
|
|
285
|
-
if (!settings) return __error("Could not get sequence settings");
|
|
286
|
-
|
|
287
|
-
settings.videoPixelAspectRatio = ${args.ratio};
|
|
288
|
-
seq.setSettings(settings);
|
|
289
|
-
|
|
290
|
-
return __result({ ratio: ${args.ratio}, sequence: seq.name });
|
|
280
|
+
const script = buildToolScript(`
|
|
281
|
+
var seq = app.project.activeSequence;
|
|
282
|
+
if (!seq) return __error("No active sequence");
|
|
283
|
+
|
|
284
|
+
var settings = seq.getSettings();
|
|
285
|
+
if (!settings) return __error("Could not get sequence settings");
|
|
286
|
+
|
|
287
|
+
settings.videoPixelAspectRatio = ${args.ratio};
|
|
288
|
+
seq.setSettings(settings);
|
|
289
|
+
|
|
290
|
+
return __result({ ratio: ${args.ratio}, sequence: seq.name });
|
|
291
291
|
`);
|
|
292
292
|
return sendCommand(script, bridgeOptions);
|
|
293
293
|
},
|
|
@@ -305,17 +305,17 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
305
305
|
required: ["field_type"],
|
|
306
306
|
},
|
|
307
307
|
handler: async (args) => {
|
|
308
|
-
const script = buildToolScript(`
|
|
309
|
-
var seq = app.project.activeSequence;
|
|
310
|
-
if (!seq) return __error("No active sequence");
|
|
311
|
-
|
|
312
|
-
var settings = seq.getSettings();
|
|
313
|
-
if (!settings) return __error("Could not get sequence settings");
|
|
314
|
-
|
|
315
|
-
settings.videoFieldType = ${args.field_type};
|
|
316
|
-
seq.setSettings(settings);
|
|
317
|
-
|
|
318
|
-
return __result({ fieldType: ${args.field_type}, sequence: seq.name });
|
|
308
|
+
const script = buildToolScript(`
|
|
309
|
+
var seq = app.project.activeSequence;
|
|
310
|
+
if (!seq) return __error("No active sequence");
|
|
311
|
+
|
|
312
|
+
var settings = seq.getSettings();
|
|
313
|
+
if (!settings) return __error("Could not get sequence settings");
|
|
314
|
+
|
|
315
|
+
settings.videoFieldType = ${args.field_type};
|
|
316
|
+
seq.setSettings(settings);
|
|
317
|
+
|
|
318
|
+
return __result({ fieldType: ${args.field_type}, sequence: seq.name });
|
|
319
319
|
`);
|
|
320
320
|
return sendCommand(script, bridgeOptions);
|
|
321
321
|
},
|
|
@@ -324,33 +324,33 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
324
324
|
description: "Get all unique media file paths used in the project. Useful for asset management and archiving.",
|
|
325
325
|
parameters: {},
|
|
326
326
|
handler: async () => {
|
|
327
|
-
const script = buildToolScript(`
|
|
328
|
-
var paths = {};
|
|
329
|
-
function scan(bin) {
|
|
330
|
-
for (var i = 0; i < bin.children.numItems; i++) {
|
|
331
|
-
var item = bin.children[i];
|
|
332
|
-
try {
|
|
333
|
-
var mp = item.getMediaPath();
|
|
334
|
-
if (mp && !paths[mp]) {
|
|
335
|
-
paths[mp] = {
|
|
336
|
-
path: mp,
|
|
337
|
-
name: item.name,
|
|
338
|
-
nodeId: item.nodeId,
|
|
339
|
-
offline: false
|
|
340
|
-
};
|
|
341
|
-
try { paths[mp].offline = item.isOffline(); } catch(e) {}
|
|
342
|
-
}
|
|
343
|
-
} catch(e) {}
|
|
344
|
-
if (item.type === 2) scan(item);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
scan(app.project.rootItem);
|
|
348
|
-
|
|
349
|
-
var result = [];
|
|
350
|
-
for (var key in paths) {
|
|
351
|
-
if (paths.hasOwnProperty(key)) result.push(paths[key]);
|
|
352
|
-
}
|
|
353
|
-
return __result({ pathCount: result.length, paths: result });
|
|
327
|
+
const script = buildToolScript(`
|
|
328
|
+
var paths = {};
|
|
329
|
+
function scan(bin) {
|
|
330
|
+
for (var i = 0; i < bin.children.numItems; i++) {
|
|
331
|
+
var item = bin.children[i];
|
|
332
|
+
try {
|
|
333
|
+
var mp = item.getMediaPath();
|
|
334
|
+
if (mp && !paths[mp]) {
|
|
335
|
+
paths[mp] = {
|
|
336
|
+
path: mp,
|
|
337
|
+
name: item.name,
|
|
338
|
+
nodeId: item.nodeId,
|
|
339
|
+
offline: false
|
|
340
|
+
};
|
|
341
|
+
try { paths[mp].offline = item.isOffline(); } catch(e) {}
|
|
342
|
+
}
|
|
343
|
+
} catch(e) {}
|
|
344
|
+
if (item.type === 2) scan(item);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
scan(app.project.rootItem);
|
|
348
|
+
|
|
349
|
+
var result = [];
|
|
350
|
+
for (var key in paths) {
|
|
351
|
+
if (paths.hasOwnProperty(key)) result.push(paths[key]);
|
|
352
|
+
}
|
|
353
|
+
return __result({ pathCount: result.length, paths: result });
|
|
354
354
|
`);
|
|
355
355
|
return sendCommand(script, bridgeOptions);
|
|
356
356
|
},
|
|
@@ -359,47 +359,47 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
359
359
|
description: "Find all project items that are NOT used in any sequence. Useful for cleaning up projects.",
|
|
360
360
|
parameters: {},
|
|
361
361
|
handler: async () => {
|
|
362
|
-
const script = buildToolScript(`
|
|
363
|
-
// First, collect all project item nodeIds used in any sequence
|
|
364
|
-
var usedIds = {};
|
|
365
|
-
for (var s = 0; s < app.project.sequences.numSequences; s++) {
|
|
366
|
-
var seq = app.project.sequences[s];
|
|
367
|
-
function scanTracks(tracks) {
|
|
368
|
-
for (var t = 0; t < tracks.numTracks; t++) {
|
|
369
|
-
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
370
|
-
try {
|
|
371
|
-
var src = tracks[t].clips[c].projectItem;
|
|
372
|
-
if (src) usedIds[src.nodeId] = true;
|
|
373
|
-
} catch(e) {}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
scanTracks(seq.videoTracks);
|
|
378
|
-
scanTracks(seq.audioTracks);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// Then find items not in usedIds
|
|
382
|
-
var unused = [];
|
|
383
|
-
function findUnused(bin) {
|
|
384
|
-
for (var i = 0; i < bin.children.numItems; i++) {
|
|
385
|
-
var item = bin.children[i];
|
|
386
|
-
if (item.type === 1 || item.type === 4) { // clips and files
|
|
387
|
-
if (!usedIds[item.nodeId]) {
|
|
388
|
-
var entry = {
|
|
389
|
-
nodeId: item.nodeId,
|
|
390
|
-
name: item.name,
|
|
391
|
-
treePath: item.treePath
|
|
392
|
-
};
|
|
393
|
-
try { entry.mediaPath = item.getMediaPath(); } catch(e) {}
|
|
394
|
-
unused.push(entry);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
if (item.type === 2) findUnused(item);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
findUnused(app.project.rootItem);
|
|
401
|
-
|
|
402
|
-
return __result({ unusedCount: unused.length, items: unused });
|
|
362
|
+
const script = buildToolScript(`
|
|
363
|
+
// First, collect all project item nodeIds used in any sequence
|
|
364
|
+
var usedIds = {};
|
|
365
|
+
for (var s = 0; s < app.project.sequences.numSequences; s++) {
|
|
366
|
+
var seq = app.project.sequences[s];
|
|
367
|
+
function scanTracks(tracks) {
|
|
368
|
+
for (var t = 0; t < tracks.numTracks; t++) {
|
|
369
|
+
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
370
|
+
try {
|
|
371
|
+
var src = tracks[t].clips[c].projectItem;
|
|
372
|
+
if (src) usedIds[src.nodeId] = true;
|
|
373
|
+
} catch(e) {}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
scanTracks(seq.videoTracks);
|
|
378
|
+
scanTracks(seq.audioTracks);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Then find items not in usedIds
|
|
382
|
+
var unused = [];
|
|
383
|
+
function findUnused(bin) {
|
|
384
|
+
for (var i = 0; i < bin.children.numItems; i++) {
|
|
385
|
+
var item = bin.children[i];
|
|
386
|
+
if (item.type === 1 || item.type === 4) { // clips and files
|
|
387
|
+
if (!usedIds[item.nodeId]) {
|
|
388
|
+
var entry = {
|
|
389
|
+
nodeId: item.nodeId,
|
|
390
|
+
name: item.name,
|
|
391
|
+
treePath: item.treePath
|
|
392
|
+
};
|
|
393
|
+
try { entry.mediaPath = item.getMediaPath(); } catch(e) {}
|
|
394
|
+
unused.push(entry);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (item.type === 2) findUnused(item);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
findUnused(app.project.rootItem);
|
|
401
|
+
|
|
402
|
+
return __result({ unusedCount: unused.length, items: unused });
|
|
403
403
|
`);
|
|
404
404
|
return sendCommand(script, bridgeOptions);
|
|
405
405
|
},
|
|
@@ -408,31 +408,31 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
408
408
|
description: "Find project items that reference the same source media file. Useful for consolidation.",
|
|
409
409
|
parameters: {},
|
|
410
410
|
handler: async () => {
|
|
411
|
-
const script = buildToolScript(`
|
|
412
|
-
var pathMap = {};
|
|
413
|
-
function scan(bin) {
|
|
414
|
-
for (var i = 0; i < bin.children.numItems; i++) {
|
|
415
|
-
var item = bin.children[i];
|
|
416
|
-
try {
|
|
417
|
-
var mp = item.getMediaPath();
|
|
418
|
-
if (mp) {
|
|
419
|
-
if (!pathMap[mp]) pathMap[mp] = [];
|
|
420
|
-
pathMap[mp].push({ nodeId: item.nodeId, name: item.name, treePath: item.treePath });
|
|
421
|
-
}
|
|
422
|
-
} catch(e) {}
|
|
423
|
-
if (item.type === 2) scan(item);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
scan(app.project.rootItem);
|
|
427
|
-
|
|
428
|
-
var duplicates = [];
|
|
429
|
-
for (var path in pathMap) {
|
|
430
|
-
if (pathMap.hasOwnProperty(path) && pathMap[path].length > 1) {
|
|
431
|
-
duplicates.push({ mediaPath: path, count: pathMap[path].length, items: pathMap[path] });
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
return __result({ duplicateGroupCount: duplicates.length, duplicates: duplicates });
|
|
411
|
+
const script = buildToolScript(`
|
|
412
|
+
var pathMap = {};
|
|
413
|
+
function scan(bin) {
|
|
414
|
+
for (var i = 0; i < bin.children.numItems; i++) {
|
|
415
|
+
var item = bin.children[i];
|
|
416
|
+
try {
|
|
417
|
+
var mp = item.getMediaPath();
|
|
418
|
+
if (mp) {
|
|
419
|
+
if (!pathMap[mp]) pathMap[mp] = [];
|
|
420
|
+
pathMap[mp].push({ nodeId: item.nodeId, name: item.name, treePath: item.treePath });
|
|
421
|
+
}
|
|
422
|
+
} catch(e) {}
|
|
423
|
+
if (item.type === 2) scan(item);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
scan(app.project.rootItem);
|
|
427
|
+
|
|
428
|
+
var duplicates = [];
|
|
429
|
+
for (var path in pathMap) {
|
|
430
|
+
if (pathMap.hasOwnProperty(path) && pathMap[path].length > 1) {
|
|
431
|
+
duplicates.push({ mediaPath: path, count: pathMap[path].length, items: pathMap[path] });
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return __result({ duplicateGroupCount: duplicates.length, duplicates: duplicates });
|
|
436
436
|
`);
|
|
437
437
|
return sendCommand(script, bridgeOptions);
|
|
438
438
|
},
|
|
@@ -441,18 +441,18 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
441
441
|
description: "Lift (remove without closing gap) the content between sequence in/out points or selected clips.",
|
|
442
442
|
parameters: {},
|
|
443
443
|
handler: async () => {
|
|
444
|
-
const script = buildToolScript(`
|
|
445
|
-
app.enableQE();
|
|
446
|
-
var seq = app.project.activeSequence;
|
|
447
|
-
if (!seq) return __error("No active sequence");
|
|
448
|
-
|
|
449
|
-
try {
|
|
450
|
-
var qeSeq = qe.project.getActiveSequence();
|
|
451
|
-
qeSeq.lift();
|
|
452
|
-
return __result({ lifted: true });
|
|
453
|
-
} catch(e) {
|
|
454
|
-
return __error("Lift failed: " + e.message);
|
|
455
|
-
}
|
|
444
|
+
const script = buildToolScript(`
|
|
445
|
+
app.enableQE();
|
|
446
|
+
var seq = app.project.activeSequence;
|
|
447
|
+
if (!seq) return __error("No active sequence");
|
|
448
|
+
|
|
449
|
+
try {
|
|
450
|
+
var qeSeq = qe.project.getActiveSequence();
|
|
451
|
+
qeSeq.lift();
|
|
452
|
+
return __result({ lifted: true });
|
|
453
|
+
} catch(e) {
|
|
454
|
+
return __error("Lift failed: " + e.message);
|
|
455
|
+
}
|
|
456
456
|
`);
|
|
457
457
|
return sendCommand(script, bridgeOptions);
|
|
458
458
|
},
|
|
@@ -461,18 +461,18 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
461
461
|
description: "Extract (remove and close gap) the content between sequence in/out points.",
|
|
462
462
|
parameters: {},
|
|
463
463
|
handler: async () => {
|
|
464
|
-
const script = buildToolScript(`
|
|
465
|
-
app.enableQE();
|
|
466
|
-
var seq = app.project.activeSequence;
|
|
467
|
-
if (!seq) return __error("No active sequence");
|
|
468
|
-
|
|
469
|
-
try {
|
|
470
|
-
var qeSeq = qe.project.getActiveSequence();
|
|
471
|
-
qeSeq.extract();
|
|
472
|
-
return __result({ extracted: true });
|
|
473
|
-
} catch(e) {
|
|
474
|
-
return __error("Extract failed: " + e.message);
|
|
475
|
-
}
|
|
464
|
+
const script = buildToolScript(`
|
|
465
|
+
app.enableQE();
|
|
466
|
+
var seq = app.project.activeSequence;
|
|
467
|
+
if (!seq) return __error("No active sequence");
|
|
468
|
+
|
|
469
|
+
try {
|
|
470
|
+
var qeSeq = qe.project.getActiveSequence();
|
|
471
|
+
qeSeq.extract();
|
|
472
|
+
return __result({ extracted: true });
|
|
473
|
+
} catch(e) {
|
|
474
|
+
return __error("Extract failed: " + e.message);
|
|
475
|
+
}
|
|
476
476
|
`);
|
|
477
477
|
return sendCommand(script, bridgeOptions);
|
|
478
478
|
},
|
|
@@ -490,56 +490,56 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
490
490
|
required: ["node_id"],
|
|
491
491
|
},
|
|
492
492
|
handler: async (args) => {
|
|
493
|
-
const script = buildToolScript(`
|
|
494
|
-
var result = __findClip("${escapeForExtendScript(args.node_id)}");
|
|
495
|
-
if (!result) return __error("Clip not found");
|
|
496
|
-
|
|
497
|
-
var clip = result.clip;
|
|
498
|
-
var info = {
|
|
499
|
-
nodeId: clip.nodeId,
|
|
500
|
-
name: clip.name,
|
|
501
|
-
trackType: result.trackType,
|
|
502
|
-
trackIndex: result.trackIndex
|
|
503
|
-
};
|
|
504
|
-
|
|
505
|
-
// Find linked clips by matching projectItem and overlapping time
|
|
506
|
-
var linked = [];
|
|
507
|
-
var seq = app.project.activeSequence;
|
|
508
|
-
var clipStart = clip.start.ticks;
|
|
509
|
-
var clipEnd = clip.end.ticks;
|
|
510
|
-
var srcId = null;
|
|
511
|
-
try { srcId = clip.projectItem ? clip.projectItem.nodeId : null; } catch(e) {}
|
|
512
|
-
|
|
513
|
-
function findLinked(tracks, type) {
|
|
514
|
-
for (var t = 0; t < tracks.numTracks; t++) {
|
|
515
|
-
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
516
|
-
var other = tracks[t].clips[c];
|
|
517
|
-
if (other.nodeId === clip.nodeId) continue;
|
|
518
|
-
// Check same source and overlapping time
|
|
519
|
-
try {
|
|
520
|
-
var otherSrcId = other.projectItem ? other.projectItem.nodeId : null;
|
|
521
|
-
if (srcId && otherSrcId === srcId && other.start.ticks === clipStart) {
|
|
522
|
-
linked.push({
|
|
523
|
-
nodeId: other.nodeId,
|
|
524
|
-
name: other.name,
|
|
525
|
-
trackType: type,
|
|
526
|
-
trackIndex: t,
|
|
527
|
-
startSeconds: __ticksToSeconds(other.start.ticks),
|
|
528
|
-
endSeconds: __ticksToSeconds(other.end.ticks)
|
|
529
|
-
});
|
|
530
|
-
}
|
|
531
|
-
} catch(e) {}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
findLinked(seq.videoTracks, "video");
|
|
537
|
-
findLinked(seq.audioTracks, "audio");
|
|
538
|
-
|
|
539
|
-
info.linkedClips = linked;
|
|
540
|
-
info.linkedCount = linked.length;
|
|
541
|
-
|
|
542
|
-
return __result(info);
|
|
493
|
+
const script = buildToolScript(`
|
|
494
|
+
var result = __findClip("${escapeForExtendScript(args.node_id)}");
|
|
495
|
+
if (!result) return __error("Clip not found");
|
|
496
|
+
|
|
497
|
+
var clip = result.clip;
|
|
498
|
+
var info = {
|
|
499
|
+
nodeId: clip.nodeId,
|
|
500
|
+
name: clip.name,
|
|
501
|
+
trackType: result.trackType,
|
|
502
|
+
trackIndex: result.trackIndex
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
// Find linked clips by matching projectItem and overlapping time
|
|
506
|
+
var linked = [];
|
|
507
|
+
var seq = app.project.activeSequence;
|
|
508
|
+
var clipStart = clip.start.ticks;
|
|
509
|
+
var clipEnd = clip.end.ticks;
|
|
510
|
+
var srcId = null;
|
|
511
|
+
try { srcId = clip.projectItem ? clip.projectItem.nodeId : null; } catch(e) {}
|
|
512
|
+
|
|
513
|
+
function findLinked(tracks, type) {
|
|
514
|
+
for (var t = 0; t < tracks.numTracks; t++) {
|
|
515
|
+
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
516
|
+
var other = tracks[t].clips[c];
|
|
517
|
+
if (other.nodeId === clip.nodeId) continue;
|
|
518
|
+
// Check same source and overlapping time
|
|
519
|
+
try {
|
|
520
|
+
var otherSrcId = other.projectItem ? other.projectItem.nodeId : null;
|
|
521
|
+
if (srcId && otherSrcId === srcId && other.start.ticks === clipStart) {
|
|
522
|
+
linked.push({
|
|
523
|
+
nodeId: other.nodeId,
|
|
524
|
+
name: other.name,
|
|
525
|
+
trackType: type,
|
|
526
|
+
trackIndex: t,
|
|
527
|
+
startSeconds: __ticksToSeconds(other.start.ticks),
|
|
528
|
+
endSeconds: __ticksToSeconds(other.end.ticks)
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
} catch(e) {}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
findLinked(seq.videoTracks, "video");
|
|
537
|
+
findLinked(seq.audioTracks, "audio");
|
|
538
|
+
|
|
539
|
+
info.linkedClips = linked;
|
|
540
|
+
info.linkedCount = linked.length;
|
|
541
|
+
|
|
542
|
+
return __result(info);
|
|
543
543
|
`);
|
|
544
544
|
return sendCommand(script, bridgeOptions);
|
|
545
545
|
},
|
|
@@ -565,25 +565,25 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
565
565
|
const seqLookup = args.sequence_id
|
|
566
566
|
? `var seq = __findSequence("${escapeForExtendScript(args.sequence_id)}"); if (!seq) return __error("Sequence not found");`
|
|
567
567
|
: `var seq = app.project.activeSequence; if (!seq) return __error("No active sequence");`;
|
|
568
|
-
const script = buildToolScript(`
|
|
569
|
-
${seqLookup}
|
|
570
|
-
|
|
571
|
-
var markers = [];
|
|
572
|
-
var m = seq.markers.getFirstMarker();
|
|
573
|
-
while (m) {
|
|
574
|
-
if (m.type === "${escapeForExtendScript(args.marker_type)}") {
|
|
575
|
-
markers.push({
|
|
576
|
-
name: m.name,
|
|
577
|
-
comments: m.comments,
|
|
578
|
-
startSeconds: __ticksToSeconds(m.start.ticks),
|
|
579
|
-
endSeconds: __ticksToSeconds(m.end.ticks),
|
|
580
|
-
type: m.type
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
m = seq.markers.getNextMarker(m);
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
return __result({ type: "${escapeForExtendScript(args.marker_type)}", count: markers.length, markers: markers });
|
|
568
|
+
const script = buildToolScript(`
|
|
569
|
+
${seqLookup}
|
|
570
|
+
|
|
571
|
+
var markers = [];
|
|
572
|
+
var m = seq.markers.getFirstMarker();
|
|
573
|
+
while (m) {
|
|
574
|
+
if (m.type === "${escapeForExtendScript(args.marker_type)}") {
|
|
575
|
+
markers.push({
|
|
576
|
+
name: m.name,
|
|
577
|
+
comments: m.comments,
|
|
578
|
+
startSeconds: __ticksToSeconds(m.start.ticks),
|
|
579
|
+
endSeconds: __ticksToSeconds(m.end.ticks),
|
|
580
|
+
type: m.type
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
m = seq.markers.getNextMarker(m);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
return __result({ type: "${escapeForExtendScript(args.marker_type)}", count: markers.length, markers: markers });
|
|
587
587
|
`);
|
|
588
588
|
return sendCommand(script, bridgeOptions);
|
|
589
589
|
},
|
|
@@ -601,29 +601,29 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
601
601
|
required: ["item_id"],
|
|
602
602
|
},
|
|
603
603
|
handler: async (args) => {
|
|
604
|
-
const script = buildToolScript(`
|
|
605
|
-
// Accept project item IDs/names AND timeline clip nodeIds.
|
|
606
|
-
var item = __resolveProjectItemOrTimelineClip("${escapeForExtendScript(args.item_id)}");
|
|
607
|
-
if (!item) return __error("Item not found in project tree or timeline: ${escapeForExtendScript(args.item_id)}");
|
|
608
|
-
|
|
609
|
-
var markers = [];
|
|
610
|
-
try {
|
|
611
|
-
var m = item.getMarkers().getFirstMarker();
|
|
612
|
-
while (m) {
|
|
613
|
-
var mi = {
|
|
614
|
-
name: m.name,
|
|
615
|
-
comments: m.comments,
|
|
616
|
-
startSeconds: __ticksToSeconds(m.start.ticks),
|
|
617
|
-
type: m.type
|
|
618
|
-
};
|
|
619
|
-
try { mi.endSeconds = __ticksToSeconds(m.end.ticks); } catch(e) {}
|
|
620
|
-
try { mi.colorIndex = m.getColorByIndex(); } catch(e) {}
|
|
621
|
-
markers.push(mi);
|
|
622
|
-
m = item.getMarkers().getNextMarker(m);
|
|
623
|
-
}
|
|
624
|
-
} catch(e) {}
|
|
625
|
-
|
|
626
|
-
return __result({ item: item.name, markerCount: markers.length, markers: markers });
|
|
604
|
+
const script = buildToolScript(`
|
|
605
|
+
// Accept project item IDs/names AND timeline clip nodeIds.
|
|
606
|
+
var item = __resolveProjectItemOrTimelineClip("${escapeForExtendScript(args.item_id)}");
|
|
607
|
+
if (!item) return __error("Item not found in project tree or timeline: ${escapeForExtendScript(args.item_id)}");
|
|
608
|
+
|
|
609
|
+
var markers = [];
|
|
610
|
+
try {
|
|
611
|
+
var m = item.getMarkers().getFirstMarker();
|
|
612
|
+
while (m) {
|
|
613
|
+
var mi = {
|
|
614
|
+
name: m.name,
|
|
615
|
+
comments: m.comments,
|
|
616
|
+
startSeconds: __ticksToSeconds(m.start.ticks),
|
|
617
|
+
type: m.type
|
|
618
|
+
};
|
|
619
|
+
try { mi.endSeconds = __ticksToSeconds(m.end.ticks); } catch(e) {}
|
|
620
|
+
try { mi.colorIndex = m.getColorByIndex(); } catch(e) {}
|
|
621
|
+
markers.push(mi);
|
|
622
|
+
m = item.getMarkers().getNextMarker(m);
|
|
623
|
+
}
|
|
624
|
+
} catch(e) {}
|
|
625
|
+
|
|
626
|
+
return __result({ item: item.name, markerCount: markers.length, markers: markers });
|
|
627
627
|
`);
|
|
628
628
|
return sendCommand(script, bridgeOptions);
|
|
629
629
|
},
|
|
@@ -666,24 +666,24 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
666
666
|
required: ["item_id", "time_seconds"],
|
|
667
667
|
},
|
|
668
668
|
handler: async (args) => {
|
|
669
|
-
const script = buildToolScript(`
|
|
670
|
-
var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
|
|
671
|
-
if (!item) return __error("Item not found");
|
|
672
|
-
|
|
673
|
-
var markers = item.getMarkers();
|
|
674
|
-
var marker = markers.createMarker(${args.time_seconds});
|
|
675
|
-
|
|
676
|
-
${args.name ? `marker.name = "${escapeForExtendScript(args.name)}";` : ""}
|
|
677
|
-
${args.comments ? `marker.comments = "${escapeForExtendScript(args.comments)}";` : ""}
|
|
678
|
-
${args.type ? `marker.type = "${escapeForExtendScript(args.type)}";` : ""}
|
|
679
|
-
${args.duration_seconds !== undefined ? `
|
|
680
|
-
var endTime = new Time();
|
|
681
|
-
endTime.seconds = ${args.time_seconds + args.duration_seconds};
|
|
682
|
-
marker.end = endTime;
|
|
683
|
-
` : ""}
|
|
684
|
-
${args.color_index !== undefined ? `marker.setColorByIndex(${args.color_index});` : ""}
|
|
685
|
-
|
|
686
|
-
return __result({ added: true, item: item.name, timeSeconds: ${args.time_seconds} });
|
|
669
|
+
const script = buildToolScript(`
|
|
670
|
+
var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
|
|
671
|
+
if (!item) return __error("Item not found");
|
|
672
|
+
|
|
673
|
+
var markers = item.getMarkers();
|
|
674
|
+
var marker = markers.createMarker(${args.time_seconds});
|
|
675
|
+
|
|
676
|
+
${args.name ? `marker.name = "${escapeForExtendScript(args.name)}";` : ""}
|
|
677
|
+
${args.comments ? `marker.comments = "${escapeForExtendScript(args.comments)}";` : ""}
|
|
678
|
+
${args.type ? `marker.type = "${escapeForExtendScript(args.type)}";` : ""}
|
|
679
|
+
${args.duration_seconds !== undefined ? `
|
|
680
|
+
var endTime = new Time();
|
|
681
|
+
endTime.seconds = ${args.time_seconds + args.duration_seconds};
|
|
682
|
+
marker.end = endTime;
|
|
683
|
+
` : ""}
|
|
684
|
+
${args.color_index !== undefined ? `marker.setColorByIndex(${args.color_index});` : ""}
|
|
685
|
+
|
|
686
|
+
return __result({ added: true, item: item.name, timeSeconds: ${args.time_seconds} });
|
|
687
687
|
`);
|
|
688
688
|
return sendCommand(script, bridgeOptions);
|
|
689
689
|
},
|
|
@@ -704,18 +704,18 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
704
704
|
},
|
|
705
705
|
},
|
|
706
706
|
handler: async (args) => {
|
|
707
|
-
const script = buildToolScript(`
|
|
708
|
-
var seq = app.project.activeSequence;
|
|
709
|
-
if (!seq) return __error("No active sequence");
|
|
710
|
-
|
|
711
|
-
var settings = seq.getSettings();
|
|
712
|
-
if (!settings) return __error("Could not get sequence settings");
|
|
713
|
-
|
|
714
|
-
${args.video_display_format !== undefined ? `settings.videoDisplayFormat = ${args.video_display_format};` : ""}
|
|
715
|
-
${args.audio_display_format !== undefined ? `settings.audioDisplayFormat = ${args.audio_display_format};` : ""}
|
|
716
|
-
seq.setSettings(settings);
|
|
717
|
-
|
|
718
|
-
return __result({ sequence: seq.name, videoDisplayFormat: settings.videoDisplayFormat, audioDisplayFormat: settings.audioDisplayFormat });
|
|
707
|
+
const script = buildToolScript(`
|
|
708
|
+
var seq = app.project.activeSequence;
|
|
709
|
+
if (!seq) return __error("No active sequence");
|
|
710
|
+
|
|
711
|
+
var settings = seq.getSettings();
|
|
712
|
+
if (!settings) return __error("Could not get sequence settings");
|
|
713
|
+
|
|
714
|
+
${args.video_display_format !== undefined ? `settings.videoDisplayFormat = ${args.video_display_format};` : ""}
|
|
715
|
+
${args.audio_display_format !== undefined ? `settings.audioDisplayFormat = ${args.audio_display_format};` : ""}
|
|
716
|
+
seq.setSettings(settings);
|
|
717
|
+
|
|
718
|
+
return __result({ sequence: seq.name, videoDisplayFormat: settings.videoDisplayFormat, audioDisplayFormat: settings.audioDisplayFormat });
|
|
719
719
|
`);
|
|
720
720
|
return sendCommand(script, bridgeOptions);
|
|
721
721
|
},
|
|
@@ -734,45 +734,45 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
734
734
|
},
|
|
735
735
|
handler: async (args) => {
|
|
736
736
|
const trackType = args.track_type || "both";
|
|
737
|
-
const script = buildToolScript(`
|
|
738
|
-
var seq = app.project.activeSequence;
|
|
739
|
-
if (!seq) return __error("No active sequence");
|
|
740
|
-
|
|
741
|
-
var posTicks = parseFloat(seq.getPlayerPosition().ticks);
|
|
742
|
-
var clips = [];
|
|
743
|
-
|
|
744
|
-
function findAtPlayhead(tracks, type) {
|
|
745
|
-
for (var t = 0; t < tracks.numTracks; t++) {
|
|
746
|
-
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
747
|
-
var clip = tracks[t].clips[c];
|
|
748
|
-
var cs = parseFloat(clip.start.ticks);
|
|
749
|
-
var ce = parseFloat(clip.end.ticks);
|
|
750
|
-
if (cs <= posTicks && ce > posTicks) {
|
|
751
|
-
var ci = {
|
|
752
|
-
nodeId: clip.nodeId,
|
|
753
|
-
name: clip.name,
|
|
754
|
-
trackType: type,
|
|
755
|
-
trackIndex: t,
|
|
756
|
-
trackName: tracks[t].name,
|
|
757
|
-
clipIndex: c,
|
|
758
|
-
startSeconds: __ticksToSeconds(clip.start.ticks),
|
|
759
|
-
endSeconds: __ticksToSeconds(clip.end.ticks)
|
|
760
|
-
};
|
|
761
|
-
try { ci.enabled = !clip.isDisabled(); } catch(e) { ci.enabled = true; }
|
|
762
|
-
clips.push(ci);
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
if ("${trackType}" !== "audio") findAtPlayhead(seq.videoTracks, "video");
|
|
769
|
-
if ("${trackType}" !== "video") findAtPlayhead(seq.audioTracks, "audio");
|
|
770
|
-
|
|
771
|
-
return __result({
|
|
772
|
-
playheadSeconds: __ticksToSeconds(seq.getPlayerPosition().ticks),
|
|
773
|
-
clipCount: clips.length,
|
|
774
|
-
clips: clips
|
|
775
|
-
});
|
|
737
|
+
const script = buildToolScript(`
|
|
738
|
+
var seq = app.project.activeSequence;
|
|
739
|
+
if (!seq) return __error("No active sequence");
|
|
740
|
+
|
|
741
|
+
var posTicks = parseFloat(seq.getPlayerPosition().ticks);
|
|
742
|
+
var clips = [];
|
|
743
|
+
|
|
744
|
+
function findAtPlayhead(tracks, type) {
|
|
745
|
+
for (var t = 0; t < tracks.numTracks; t++) {
|
|
746
|
+
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
747
|
+
var clip = tracks[t].clips[c];
|
|
748
|
+
var cs = parseFloat(clip.start.ticks);
|
|
749
|
+
var ce = parseFloat(clip.end.ticks);
|
|
750
|
+
if (cs <= posTicks && ce > posTicks) {
|
|
751
|
+
var ci = {
|
|
752
|
+
nodeId: clip.nodeId,
|
|
753
|
+
name: clip.name,
|
|
754
|
+
trackType: type,
|
|
755
|
+
trackIndex: t,
|
|
756
|
+
trackName: tracks[t].name,
|
|
757
|
+
clipIndex: c,
|
|
758
|
+
startSeconds: __ticksToSeconds(clip.start.ticks),
|
|
759
|
+
endSeconds: __ticksToSeconds(clip.end.ticks)
|
|
760
|
+
};
|
|
761
|
+
try { ci.enabled = !clip.isDisabled(); } catch(e) { ci.enabled = true; }
|
|
762
|
+
clips.push(ci);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
if ("${trackType}" !== "audio") findAtPlayhead(seq.videoTracks, "video");
|
|
769
|
+
if ("${trackType}" !== "video") findAtPlayhead(seq.audioTracks, "audio");
|
|
770
|
+
|
|
771
|
+
return __result({
|
|
772
|
+
playheadSeconds: __ticksToSeconds(seq.getPlayerPosition().ticks),
|
|
773
|
+
clipCount: clips.length,
|
|
774
|
+
clips: clips
|
|
775
|
+
});
|
|
776
776
|
`);
|
|
777
777
|
return sendCommand(script, bridgeOptions);
|
|
778
778
|
},
|
|
@@ -797,54 +797,54 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
797
797
|
handler: async (args) => {
|
|
798
798
|
const direction = args.direction || "next";
|
|
799
799
|
const trackType = args.track_type || "both";
|
|
800
|
-
const script = buildToolScript(`
|
|
801
|
-
var seq = app.project.activeSequence;
|
|
802
|
-
if (!seq) return __error("No active sequence");
|
|
803
|
-
|
|
804
|
-
var posTicks = parseFloat(seq.getPlayerPosition().ticks);
|
|
805
|
-
var editPoints = [];
|
|
806
|
-
|
|
807
|
-
function collectPoints(tracks, type) {
|
|
808
|
-
for (var t = 0; t < tracks.numTracks; t++) {
|
|
809
|
-
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
810
|
-
var clip = tracks[t].clips[c];
|
|
811
|
-
editPoints.push(parseFloat(clip.start.ticks));
|
|
812
|
-
editPoints.push(parseFloat(clip.end.ticks));
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
if ("${trackType}" !== "audio") collectPoints(seq.videoTracks, "video");
|
|
818
|
-
if ("${trackType}" !== "video") collectPoints(seq.audioTracks, "audio");
|
|
819
|
-
|
|
820
|
-
// Sort and deduplicate
|
|
821
|
-
editPoints.sort(function(a, b) { return a - b; });
|
|
822
|
-
var unique = [];
|
|
823
|
-
for (var i = 0; i < editPoints.length; i++) {
|
|
824
|
-
if (unique.length === 0 || editPoints[i] !== unique[unique.length - 1]) {
|
|
825
|
-
unique.push(editPoints[i]);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
var found = null;
|
|
830
|
-
if ("${direction}" === "next") {
|
|
831
|
-
for (var i = 0; i < unique.length; i++) {
|
|
832
|
-
if (unique[i] > posTicks + 1) { found = unique[i]; break; }
|
|
833
|
-
}
|
|
834
|
-
} else {
|
|
835
|
-
for (var i = unique.length - 1; i >= 0; i--) {
|
|
836
|
-
if (unique[i] < posTicks - 1) { found = unique[i]; break; }
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
if (found === null) return __result({ found: false, direction: "${direction}" });
|
|
841
|
-
|
|
842
|
-
return __result({
|
|
843
|
-
found: true,
|
|
844
|
-
direction: "${direction}",
|
|
845
|
-
editPointSeconds: __ticksToSeconds("" + found),
|
|
846
|
-
playheadSeconds: __ticksToSeconds("" + posTicks)
|
|
847
|
-
});
|
|
800
|
+
const script = buildToolScript(`
|
|
801
|
+
var seq = app.project.activeSequence;
|
|
802
|
+
if (!seq) return __error("No active sequence");
|
|
803
|
+
|
|
804
|
+
var posTicks = parseFloat(seq.getPlayerPosition().ticks);
|
|
805
|
+
var editPoints = [];
|
|
806
|
+
|
|
807
|
+
function collectPoints(tracks, type) {
|
|
808
|
+
for (var t = 0; t < tracks.numTracks; t++) {
|
|
809
|
+
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
810
|
+
var clip = tracks[t].clips[c];
|
|
811
|
+
editPoints.push(parseFloat(clip.start.ticks));
|
|
812
|
+
editPoints.push(parseFloat(clip.end.ticks));
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
if ("${trackType}" !== "audio") collectPoints(seq.videoTracks, "video");
|
|
818
|
+
if ("${trackType}" !== "video") collectPoints(seq.audioTracks, "audio");
|
|
819
|
+
|
|
820
|
+
// Sort and deduplicate
|
|
821
|
+
editPoints.sort(function(a, b) { return a - b; });
|
|
822
|
+
var unique = [];
|
|
823
|
+
for (var i = 0; i < editPoints.length; i++) {
|
|
824
|
+
if (unique.length === 0 || editPoints[i] !== unique[unique.length - 1]) {
|
|
825
|
+
unique.push(editPoints[i]);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
var found = null;
|
|
830
|
+
if ("${direction}" === "next") {
|
|
831
|
+
for (var i = 0; i < unique.length; i++) {
|
|
832
|
+
if (unique[i] > posTicks + 1) { found = unique[i]; break; }
|
|
833
|
+
}
|
|
834
|
+
} else {
|
|
835
|
+
for (var i = unique.length - 1; i >= 0; i--) {
|
|
836
|
+
if (unique[i] < posTicks - 1) { found = unique[i]; break; }
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (found === null) return __result({ found: false, direction: "${direction}" });
|
|
841
|
+
|
|
842
|
+
return __result({
|
|
843
|
+
found: true,
|
|
844
|
+
direction: "${direction}",
|
|
845
|
+
editPointSeconds: __ticksToSeconds("" + found),
|
|
846
|
+
playheadSeconds: __ticksToSeconds("" + posTicks)
|
|
847
|
+
});
|
|
848
848
|
`);
|
|
849
849
|
return sendCommand(script, bridgeOptions);
|
|
850
850
|
},
|
|
@@ -863,47 +863,47 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
863
863
|
},
|
|
864
864
|
handler: async (args) => {
|
|
865
865
|
const direction = args.direction || "next";
|
|
866
|
-
const script = buildToolScript(`
|
|
867
|
-
var seq = app.project.activeSequence;
|
|
868
|
-
if (!seq) return __error("No active sequence");
|
|
869
|
-
|
|
870
|
-
var posTicks = parseFloat(seq.getPlayerPosition().ticks);
|
|
871
|
-
var editPoints = [];
|
|
872
|
-
|
|
873
|
-
function collectPoints(tracks) {
|
|
874
|
-
for (var t = 0; t < tracks.numTracks; t++) {
|
|
875
|
-
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
876
|
-
editPoints.push(parseFloat(tracks[t].clips[c].start.ticks));
|
|
877
|
-
editPoints.push(parseFloat(tracks[t].clips[c].end.ticks));
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
collectPoints(seq.videoTracks);
|
|
883
|
-
collectPoints(seq.audioTracks);
|
|
884
|
-
|
|
885
|
-
editPoints.sort(function(a, b) { return a - b; });
|
|
886
|
-
var unique = [];
|
|
887
|
-
for (var i = 0; i < editPoints.length; i++) {
|
|
888
|
-
if (unique.length === 0 || editPoints[i] !== unique[unique.length - 1]) unique.push(editPoints[i]);
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
var found = null;
|
|
892
|
-
if ("${direction}" === "next") {
|
|
893
|
-
for (var i = 0; i < unique.length; i++) {
|
|
894
|
-
if (unique[i] > posTicks + 1) { found = unique[i]; break; }
|
|
895
|
-
}
|
|
896
|
-
} else {
|
|
897
|
-
for (var i = unique.length - 1; i >= 0; i--) {
|
|
898
|
-
if (unique[i] < posTicks - 1) { found = unique[i]; break; }
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
if (found === null) return __error("No " + "${direction}" + " edit point found");
|
|
903
|
-
|
|
904
|
-
seq.setPlayerPosition("" + found);
|
|
905
|
-
|
|
906
|
-
return __result({ movedTo: __ticksToSeconds("" + found), direction: "${direction}" });
|
|
866
|
+
const script = buildToolScript(`
|
|
867
|
+
var seq = app.project.activeSequence;
|
|
868
|
+
if (!seq) return __error("No active sequence");
|
|
869
|
+
|
|
870
|
+
var posTicks = parseFloat(seq.getPlayerPosition().ticks);
|
|
871
|
+
var editPoints = [];
|
|
872
|
+
|
|
873
|
+
function collectPoints(tracks) {
|
|
874
|
+
for (var t = 0; t < tracks.numTracks; t++) {
|
|
875
|
+
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
876
|
+
editPoints.push(parseFloat(tracks[t].clips[c].start.ticks));
|
|
877
|
+
editPoints.push(parseFloat(tracks[t].clips[c].end.ticks));
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
collectPoints(seq.videoTracks);
|
|
883
|
+
collectPoints(seq.audioTracks);
|
|
884
|
+
|
|
885
|
+
editPoints.sort(function(a, b) { return a - b; });
|
|
886
|
+
var unique = [];
|
|
887
|
+
for (var i = 0; i < editPoints.length; i++) {
|
|
888
|
+
if (unique.length === 0 || editPoints[i] !== unique[unique.length - 1]) unique.push(editPoints[i]);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
var found = null;
|
|
892
|
+
if ("${direction}" === "next") {
|
|
893
|
+
for (var i = 0; i < unique.length; i++) {
|
|
894
|
+
if (unique[i] > posTicks + 1) { found = unique[i]; break; }
|
|
895
|
+
}
|
|
896
|
+
} else {
|
|
897
|
+
for (var i = unique.length - 1; i >= 0; i--) {
|
|
898
|
+
if (unique[i] < posTicks - 1) { found = unique[i]; break; }
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if (found === null) return __error("No " + "${direction}" + " edit point found");
|
|
903
|
+
|
|
904
|
+
seq.setPlayerPosition("" + found);
|
|
905
|
+
|
|
906
|
+
return __result({ movedTo: __ticksToSeconds("" + found), direction: "${direction}" });
|
|
907
907
|
`);
|
|
908
908
|
return sendCommand(script, bridgeOptions);
|
|
909
909
|
},
|
|
@@ -932,21 +932,21 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
932
932
|
},
|
|
933
933
|
},
|
|
934
934
|
handler: async (args) => {
|
|
935
|
-
const script = buildToolScript(`
|
|
936
|
-
var project = app.project;
|
|
937
|
-
if (!project) return __error("No project open");
|
|
938
|
-
|
|
939
|
-
var set = {};
|
|
940
|
-
${args.captured_video ? `
|
|
941
|
-
try { project.setScratchDiskPath("${escapeForExtendScript(args.captured_video)}", 0); set.capturedVideo = "${escapeForExtendScript(args.captured_video)}"; } catch(e) {}` : ""}
|
|
942
|
-
${args.captured_audio ? `
|
|
943
|
-
try { project.setScratchDiskPath("${escapeForExtendScript(args.captured_audio)}", 1); set.capturedAudio = "${escapeForExtendScript(args.captured_audio)}"; } catch(e) {}` : ""}
|
|
944
|
-
${args.video_previews ? `
|
|
945
|
-
try { project.setScratchDiskPath("${escapeForExtendScript(args.video_previews)}", 2); set.videoPreviews = "${escapeForExtendScript(args.video_previews)}"; } catch(e) {}` : ""}
|
|
946
|
-
${args.audio_previews ? `
|
|
947
|
-
try { project.setScratchDiskPath("${escapeForExtendScript(args.audio_previews)}", 3); set.audioPreviews = "${escapeForExtendScript(args.audio_previews)}"; } catch(e) {}` : ""}
|
|
948
|
-
|
|
949
|
-
return __result(set);
|
|
935
|
+
const script = buildToolScript(`
|
|
936
|
+
var project = app.project;
|
|
937
|
+
if (!project) return __error("No project open");
|
|
938
|
+
|
|
939
|
+
var set = {};
|
|
940
|
+
${args.captured_video ? `
|
|
941
|
+
try { project.setScratchDiskPath("${escapeForExtendScript(args.captured_video)}", 0); set.capturedVideo = "${escapeForExtendScript(args.captured_video)}"; } catch(e) {}` : ""}
|
|
942
|
+
${args.captured_audio ? `
|
|
943
|
+
try { project.setScratchDiskPath("${escapeForExtendScript(args.captured_audio)}", 1); set.capturedAudio = "${escapeForExtendScript(args.captured_audio)}"; } catch(e) {}` : ""}
|
|
944
|
+
${args.video_previews ? `
|
|
945
|
+
try { project.setScratchDiskPath("${escapeForExtendScript(args.video_previews)}", 2); set.videoPreviews = "${escapeForExtendScript(args.video_previews)}"; } catch(e) {}` : ""}
|
|
946
|
+
${args.audio_previews ? `
|
|
947
|
+
try { project.setScratchDiskPath("${escapeForExtendScript(args.audio_previews)}", 3); set.audioPreviews = "${escapeForExtendScript(args.audio_previews)}"; } catch(e) {}` : ""}
|
|
948
|
+
|
|
949
|
+
return __result(set);
|
|
950
950
|
`);
|
|
951
951
|
return sendCommand(script, bridgeOptions);
|
|
952
952
|
},
|
|
@@ -955,17 +955,17 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
955
955
|
description: "Get the current scratch disk paths for the project.",
|
|
956
956
|
parameters: {},
|
|
957
957
|
handler: async () => {
|
|
958
|
-
const script = buildToolScript(`
|
|
959
|
-
var project = app.project;
|
|
960
|
-
if (!project) return __error("No project open");
|
|
961
|
-
|
|
962
|
-
var disks = {};
|
|
963
|
-
try { disks.capturedVideo = project.getScratchDiskPath(0); } catch(e) {}
|
|
964
|
-
try { disks.capturedAudio = project.getScratchDiskPath(1); } catch(e) {}
|
|
965
|
-
try { disks.videoPreviews = project.getScratchDiskPath(2); } catch(e) {}
|
|
966
|
-
try { disks.audioPreviews = project.getScratchDiskPath(3); } catch(e) {}
|
|
967
|
-
|
|
968
|
-
return __result(disks);
|
|
958
|
+
const script = buildToolScript(`
|
|
959
|
+
var project = app.project;
|
|
960
|
+
if (!project) return __error("No project open");
|
|
961
|
+
|
|
962
|
+
var disks = {};
|
|
963
|
+
try { disks.capturedVideo = project.getScratchDiskPath(0); } catch(e) {}
|
|
964
|
+
try { disks.capturedAudio = project.getScratchDiskPath(1); } catch(e) {}
|
|
965
|
+
try { disks.videoPreviews = project.getScratchDiskPath(2); } catch(e) {}
|
|
966
|
+
try { disks.audioPreviews = project.getScratchDiskPath(3); } catch(e) {}
|
|
967
|
+
|
|
968
|
+
return __result(disks);
|
|
969
969
|
`);
|
|
970
970
|
return sendCommand(script, bridgeOptions);
|
|
971
971
|
},
|
|
@@ -983,40 +983,40 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
983
983
|
required: ["name"],
|
|
984
984
|
},
|
|
985
985
|
handler: async (args) => {
|
|
986
|
-
const script = buildToolScript(`
|
|
987
|
-
var seq = app.project.activeSequence;
|
|
988
|
-
if (!seq) return __error("No active sequence");
|
|
989
|
-
|
|
990
|
-
// Get selected clips
|
|
991
|
-
var selected = [];
|
|
992
|
-
function getSelected(tracks) {
|
|
993
|
-
for (var t = 0; t < tracks.numTracks; t++) {
|
|
994
|
-
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
995
|
-
if (tracks[t].clips[c].isSelected()) selected.push(tracks[t].clips[c]);
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
getSelected(seq.videoTracks);
|
|
1000
|
-
getSelected(seq.audioTracks);
|
|
1001
|
-
|
|
1002
|
-
if (selected.length === 0) return __error("No clips selected. Select clips first.");
|
|
1003
|
-
|
|
1004
|
-
try {
|
|
1005
|
-
var sub = seq.createSubsequence(true);
|
|
1006
|
-
var appliedName = null;
|
|
1007
|
-
if (sub) {
|
|
1008
|
-
try { sub.name = "${escapeForExtendScript(args.name)}"; appliedName = sub.name; } catch(e) {}
|
|
1009
|
-
}
|
|
1010
|
-
var res = {
|
|
1011
|
-
nested: true,
|
|
1012
|
-
clipCount: selected.length,
|
|
1013
|
-
note: "createSubsequence nests the sequence in/out range, not the clip selection."
|
|
1014
|
-
};
|
|
1015
|
-
if (appliedName !== null) res.name = appliedName;
|
|
1016
|
-
return __result(res);
|
|
1017
|
-
} catch(e) {
|
|
1018
|
-
return __error("Nesting failed: " + e.message);
|
|
1019
|
-
}
|
|
986
|
+
const script = buildToolScript(`
|
|
987
|
+
var seq = app.project.activeSequence;
|
|
988
|
+
if (!seq) return __error("No active sequence");
|
|
989
|
+
|
|
990
|
+
// Get selected clips
|
|
991
|
+
var selected = [];
|
|
992
|
+
function getSelected(tracks) {
|
|
993
|
+
for (var t = 0; t < tracks.numTracks; t++) {
|
|
994
|
+
for (var c = 0; c < tracks[t].clips.numItems; c++) {
|
|
995
|
+
if (tracks[t].clips[c].isSelected()) selected.push(tracks[t].clips[c]);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
getSelected(seq.videoTracks);
|
|
1000
|
+
getSelected(seq.audioTracks);
|
|
1001
|
+
|
|
1002
|
+
if (selected.length === 0) return __error("No clips selected. Select clips first.");
|
|
1003
|
+
|
|
1004
|
+
try {
|
|
1005
|
+
var sub = seq.createSubsequence(true);
|
|
1006
|
+
var appliedName = null;
|
|
1007
|
+
if (sub) {
|
|
1008
|
+
try { sub.name = "${escapeForExtendScript(args.name)}"; appliedName = sub.name; } catch(e) {}
|
|
1009
|
+
}
|
|
1010
|
+
var res = {
|
|
1011
|
+
nested: true,
|
|
1012
|
+
clipCount: selected.length,
|
|
1013
|
+
note: "createSubsequence nests the sequence in/out range, not the clip selection."
|
|
1014
|
+
};
|
|
1015
|
+
if (appliedName !== null) res.name = appliedName;
|
|
1016
|
+
return __result(res);
|
|
1017
|
+
} catch(e) {
|
|
1018
|
+
return __error("Nesting failed: " + e.message);
|
|
1019
|
+
}
|
|
1020
1020
|
`);
|
|
1021
1021
|
return sendCommand(script, bridgeOptions);
|
|
1022
1022
|
},
|
|
@@ -1025,10 +1025,10 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
1025
1025
|
description: "Get the total number of sequences in the project.",
|
|
1026
1026
|
parameters: {},
|
|
1027
1027
|
handler: async () => {
|
|
1028
|
-
const script = buildToolScript(`
|
|
1029
|
-
var project = app.project;
|
|
1030
|
-
if (!project) return __error("No project open");
|
|
1031
|
-
return __result({ count: project.sequences.numSequences });
|
|
1028
|
+
const script = buildToolScript(`
|
|
1029
|
+
var project = app.project;
|
|
1030
|
+
if (!project) return __error("No project open");
|
|
1031
|
+
return __result({ count: project.sequences.numSequences });
|
|
1032
1032
|
`);
|
|
1033
1033
|
return sendCommand(script, bridgeOptions);
|
|
1034
1034
|
},
|
|
@@ -1037,15 +1037,15 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
1037
1037
|
description: "Get the total number of clips across all tracks in the active sequence.",
|
|
1038
1038
|
parameters: {},
|
|
1039
1039
|
handler: async () => {
|
|
1040
|
-
const script = buildToolScript(`
|
|
1041
|
-
var seq = app.project.activeSequence;
|
|
1042
|
-
if (!seq) return __error("No active sequence");
|
|
1043
|
-
|
|
1044
|
-
var video = 0, audio = 0;
|
|
1045
|
-
for (var t = 0; t < seq.videoTracks.numTracks; t++) video += seq.videoTracks[t].clips.numItems;
|
|
1046
|
-
for (var t = 0; t < seq.audioTracks.numTracks; t++) audio += seq.audioTracks[t].clips.numItems;
|
|
1047
|
-
|
|
1048
|
-
return __result({ videoClips: video, audioClips: audio, total: video + audio });
|
|
1040
|
+
const script = buildToolScript(`
|
|
1041
|
+
var seq = app.project.activeSequence;
|
|
1042
|
+
if (!seq) return __error("No active sequence");
|
|
1043
|
+
|
|
1044
|
+
var video = 0, audio = 0;
|
|
1045
|
+
for (var t = 0; t < seq.videoTracks.numTracks; t++) video += seq.videoTracks[t].clips.numItems;
|
|
1046
|
+
for (var t = 0; t < seq.audioTracks.numTracks; t++) audio += seq.audioTracks[t].clips.numItems;
|
|
1047
|
+
|
|
1048
|
+
return __result({ videoClips: video, audioClips: audio, total: video + audio });
|
|
1049
1049
|
`);
|
|
1050
1050
|
return sendCommand(script, bridgeOptions);
|
|
1051
1051
|
},
|
|
@@ -1069,46 +1069,46 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
1069
1069
|
handler: async (args) => {
|
|
1070
1070
|
const trackType = args.track_type || "video";
|
|
1071
1071
|
const trackIndex = args.track_index ?? 0;
|
|
1072
|
-
const script = buildToolScript(`
|
|
1073
|
-
var seq = app.project.activeSequence;
|
|
1074
|
-
if (!seq) return __error("No active sequence");
|
|
1075
|
-
|
|
1076
|
-
var tracks = ${trackType === "video" ? "seq.videoTracks" : "seq.audioTracks"};
|
|
1077
|
-
if (${trackIndex} >= tracks.numTracks) return __error("Track index out of range");
|
|
1078
|
-
|
|
1079
|
-
var posTicks = parseFloat(seq.getPlayerPosition().ticks);
|
|
1080
|
-
var track = tracks[${trackIndex}];
|
|
1081
|
-
var found = null;
|
|
1082
|
-
|
|
1083
|
-
for (var c = 0; c < track.clips.numItems; c++) {
|
|
1084
|
-
var clip = track.clips[c];
|
|
1085
|
-
if (parseFloat(clip.start.ticks) <= posTicks && parseFloat(clip.end.ticks) > posTicks) {
|
|
1086
|
-
found = clip;
|
|
1087
|
-
break;
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
if (!found) return __error("No clip at playhead on ${trackType} track ${trackIndex}");
|
|
1092
|
-
|
|
1093
|
-
var offsetTicks = posTicks - parseFloat(found.start.ticks) + parseFloat(found.inPoint.ticks);
|
|
1094
|
-
|
|
1095
|
-
var result = {
|
|
1096
|
-
clipName: found.name,
|
|
1097
|
-
clipNodeId: found.nodeId,
|
|
1098
|
-
timelineSeconds: __ticksToSeconds("" + posTicks),
|
|
1099
|
-
sourceSeconds: __ticksToSeconds("" + offsetTicks)
|
|
1100
|
-
};
|
|
1101
|
-
|
|
1102
|
-
try {
|
|
1103
|
-
var src = found.projectItem;
|
|
1104
|
-
if (src) {
|
|
1105
|
-
result.sourceNodeId = src.nodeId;
|
|
1106
|
-
result.sourceName = src.name;
|
|
1107
|
-
try { result.sourceMediaPath = src.getMediaPath(); } catch(e) {}
|
|
1108
|
-
}
|
|
1109
|
-
} catch(e) {}
|
|
1110
|
-
|
|
1111
|
-
return __result(result);
|
|
1072
|
+
const script = buildToolScript(`
|
|
1073
|
+
var seq = app.project.activeSequence;
|
|
1074
|
+
if (!seq) return __error("No active sequence");
|
|
1075
|
+
|
|
1076
|
+
var tracks = ${trackType === "video" ? "seq.videoTracks" : "seq.audioTracks"};
|
|
1077
|
+
if (${trackIndex} >= tracks.numTracks) return __error("Track index out of range");
|
|
1078
|
+
|
|
1079
|
+
var posTicks = parseFloat(seq.getPlayerPosition().ticks);
|
|
1080
|
+
var track = tracks[${trackIndex}];
|
|
1081
|
+
var found = null;
|
|
1082
|
+
|
|
1083
|
+
for (var c = 0; c < track.clips.numItems; c++) {
|
|
1084
|
+
var clip = track.clips[c];
|
|
1085
|
+
if (parseFloat(clip.start.ticks) <= posTicks && parseFloat(clip.end.ticks) > posTicks) {
|
|
1086
|
+
found = clip;
|
|
1087
|
+
break;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
if (!found) return __error("No clip at playhead on ${trackType} track ${trackIndex}");
|
|
1092
|
+
|
|
1093
|
+
var offsetTicks = posTicks - parseFloat(found.start.ticks) + parseFloat(found.inPoint.ticks);
|
|
1094
|
+
|
|
1095
|
+
var result = {
|
|
1096
|
+
clipName: found.name,
|
|
1097
|
+
clipNodeId: found.nodeId,
|
|
1098
|
+
timelineSeconds: __ticksToSeconds("" + posTicks),
|
|
1099
|
+
sourceSeconds: __ticksToSeconds("" + offsetTicks)
|
|
1100
|
+
};
|
|
1101
|
+
|
|
1102
|
+
try {
|
|
1103
|
+
var src = found.projectItem;
|
|
1104
|
+
if (src) {
|
|
1105
|
+
result.sourceNodeId = src.nodeId;
|
|
1106
|
+
result.sourceName = src.name;
|
|
1107
|
+
try { result.sourceMediaPath = src.getMediaPath(); } catch(e) {}
|
|
1108
|
+
}
|
|
1109
|
+
} catch(e) {}
|
|
1110
|
+
|
|
1111
|
+
return __result(result);
|
|
1112
1112
|
`);
|
|
1113
1113
|
return sendCommand(script, bridgeOptions);
|
|
1114
1114
|
},
|