premiere-cli 0.2.0__py3-none-any.whl
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.
- premiere_cli/__init__.py +11 -0
- premiere_cli/cli.py +3664 -0
- premiere_cli/log.py +66 -0
- premiere_cli/panel/.debug +8 -0
- premiere_cli/panel/CSXS/manifest.xml +52 -0
- premiere_cli/panel/css/style.css +53 -0
- premiere_cli/panel/host/commands/add-adjustment-layer.jsx +190 -0
- premiere_cli/panel/host/commands/add-audio-keyframes.jsx +176 -0
- premiere_cli/panel/host/commands/add-custom-metadata-field.jsx +63 -0
- premiere_cli/panel/host/commands/add-keyframe.jsx +181 -0
- premiere_cli/panel/host/commands/add-marker-to-project-item.jsx +194 -0
- premiere_cli/panel/host/commands/add-marker.jsx +129 -0
- premiere_cli/panel/host/commands/add-text-overlay.jsx +101 -0
- premiere_cli/panel/host/commands/add-to-render-queue.jsx +120 -0
- premiere_cli/panel/host/commands/add-to-timeline.jsx +300 -0
- premiere_cli/panel/host/commands/add-track.jsx +188 -0
- premiere_cli/panel/host/commands/add-transition.jsx +134 -0
- premiere_cli/panel/host/commands/adjust-audio-levels.jsx +132 -0
- premiere_cli/panel/host/commands/apply-audio-effect.jsx +118 -0
- premiere_cli/panel/host/commands/apply-effect.jsx +122 -0
- premiere_cli/panel/host/commands/apply-lut.jsx +107 -0
- premiere_cli/panel/host/commands/attach-custom-property.jsx +66 -0
- premiere_cli/panel/host/commands/auto-reframe-sequence.jsx +124 -0
- premiere_cli/panel/host/commands/batch-add-transitions.jsx +158 -0
- premiere_cli/panel/host/commands/batch-apply-effect.jsx +182 -0
- premiere_cli/panel/host/commands/batch-rename-clips.jsx +170 -0
- premiere_cli/panel/host/commands/batch-set-clips-enabled.jsx +145 -0
- premiere_cli/panel/host/commands/clear-item-in-out.jsx +117 -0
- premiere_cli/panel/host/commands/clear-sequence-in-out.jsx +100 -0
- premiere_cli/panel/host/commands/close-all-source-clips.jsx +32 -0
- premiere_cli/panel/host/commands/close-sequence.jsx +80 -0
- premiere_cli/panel/host/commands/close-source-monitor.jsx +32 -0
- premiere_cli/panel/host/commands/color-correct.jsx +164 -0
- premiere_cli/panel/host/commands/copy-effect-values.jsx +183 -0
- premiere_cli/panel/host/commands/copy-effects-between-clips.jsx +234 -0
- premiere_cli/panel/host/commands/create-bars-and-tone.jsx +152 -0
- premiere_cli/panel/host/commands/create-bin.jsx +76 -0
- premiere_cli/panel/host/commands/create-caption-track.jsx +159 -0
- premiere_cli/panel/host/commands/create-sequence-from-clips.jsx +170 -0
- premiere_cli/panel/host/commands/create-sequence-from-preset.jsx +90 -0
- premiere_cli/panel/host/commands/create-sequence.jsx +166 -0
- premiere_cli/panel/host/commands/create-smart-bin.jsx +80 -0
- premiere_cli/panel/host/commands/create-subclip.jsx +248 -0
- premiere_cli/panel/host/commands/create-subsequence.jsx +136 -0
- premiere_cli/panel/host/commands/debug-qe-inspect.jsx +248 -0
- premiere_cli/panel/host/commands/debug-qe-try-mutate.jsx +305 -0
- premiere_cli/panel/host/commands/delete-marker.jsx +178 -0
- premiere_cli/panel/host/commands/deselect-all-clips.jsx +98 -0
- premiere_cli/panel/host/commands/detach-proxy.jsx +116 -0
- premiere_cli/panel/host/commands/duplicate-clip.jsx +140 -0
- premiere_cli/panel/host/commands/duplicate-sequence.jsx +150 -0
- premiere_cli/panel/host/commands/encode-file.jsx +86 -0
- premiere_cli/panel/host/commands/encode-project-item.jsx +145 -0
- premiere_cli/panel/host/commands/export-aaf.jsx +77 -0
- premiere_cli/panel/host/commands/export-fcp-xml.jsx +65 -0
- premiere_cli/panel/host/commands/export-frame.jsx +381 -0
- premiere_cli/panel/host/commands/export-omf.jsx +95 -0
- premiere_cli/panel/host/commands/export-sequence-as-project.jsx +65 -0
- premiere_cli/panel/host/commands/export-sequence.jsx +100 -0
- premiere_cli/panel/host/commands/extract-audio-track.jsx +181 -0
- premiere_cli/panel/host/commands/extract-selection.jsx +113 -0
- premiere_cli/panel/host/commands/find-items-by-media-path.jsx +112 -0
- premiere_cli/panel/host/commands/freeze-frame.jsx +215 -0
- premiere_cli/panel/host/commands/get-active-sequence.jsx +103 -0
- premiere_cli/panel/host/commands/get-all-project-paths.jsx +72 -0
- premiere_cli/panel/host/commands/get-bin-contents.jsx +176 -0
- premiere_cli/panel/host/commands/get-clip-adjustment-layer.jsx +83 -0
- premiere_cli/panel/host/commands/get-clip-at-playhead.jsx +99 -0
- premiere_cli/panel/host/commands/get-clip-at-position.jsx +120 -0
- premiere_cli/panel/host/commands/get-clip-links.jsx +135 -0
- premiere_cli/panel/host/commands/get-clip-markers.jsx +144 -0
- premiere_cli/panel/host/commands/get-clip-speed.jsx +69 -0
- premiere_cli/panel/host/commands/get-color-label.jsx +89 -0
- premiere_cli/panel/host/commands/get-color-space.jsx +99 -0
- premiere_cli/panel/host/commands/get-duplicate-media.jsx +78 -0
- premiere_cli/panel/host/commands/get-effect-properties.jsx +129 -0
- premiere_cli/panel/host/commands/get-encoder-presets.jsx +131 -0
- premiere_cli/panel/host/commands/get-export-file-extension.jsx +56 -0
- premiere_cli/panel/host/commands/get-footage-interpretation.jsx +113 -0
- premiere_cli/panel/host/commands/get-full-clip-info.jsx +162 -0
- premiere_cli/panel/host/commands/get-full-project-overview.jsx +193 -0
- premiere_cli/panel/host/commands/get-full-sequence-info.jsx +184 -0
- premiere_cli/panel/host/commands/get-graphics-white-luminance.jsx +31 -0
- premiere_cli/panel/host/commands/get-insertion-bin.jsx +35 -0
- premiere_cli/panel/host/commands/get-item-metadata.jsx +94 -0
- premiere_cli/panel/host/commands/get-keyframes.jsx +158 -0
- premiere_cli/panel/host/commands/get-mogrt-component.jsx +111 -0
- premiere_cli/panel/host/commands/get-next-edit-point.jsx +131 -0
- premiere_cli/panel/host/commands/get-offline-media.jsx +67 -0
- premiere_cli/panel/host/commands/get-open-projects.jsx +50 -0
- premiere_cli/panel/host/commands/get-premiere-state.jsx +164 -0
- premiere_cli/panel/host/commands/get-project-info.jsx +63 -0
- premiere_cli/panel/host/commands/get-project-item-info.jsx +247 -0
- premiere_cli/panel/host/commands/get-project-panel-metadata.jsx +30 -0
- premiere_cli/panel/host/commands/get-qe-clip-info.jsx +198 -0
- premiere_cli/panel/host/commands/get-render-queue-status.jsx +35 -0
- premiere_cli/panel/host/commands/get-sequence-count.jsx +24 -0
- premiere_cli/panel/host/commands/get-sequence-in-out.jsx +76 -0
- premiere_cli/panel/host/commands/get-sequence-markers-by-type.jsx +89 -0
- premiere_cli/panel/host/commands/get-source-monitor-info.jsx +34 -0
- premiere_cli/panel/host/commands/get-source-monitor-position.jsx +30 -0
- premiere_cli/panel/host/commands/get-target-tracks.jsx +76 -0
- premiere_cli/panel/host/commands/get-timeline-gaps.jsx +124 -0
- premiere_cli/panel/host/commands/get-timeline-summary.jsx +154 -0
- premiere_cli/panel/host/commands/get-total-clip-count.jsx +67 -0
- premiere_cli/panel/host/commands/get-track-info.jsx +117 -0
- premiere_cli/panel/host/commands/get-unused-media.jsx +99 -0
- premiere_cli/panel/host/commands/get-used-media-report.jsx +125 -0
- premiere_cli/panel/host/commands/get-value-at-time.jsx +135 -0
- premiere_cli/panel/host/commands/get-version-info.jsx +33 -0
- premiere_cli/panel/host/commands/get-work-area.jsx +52 -0
- premiere_cli/panel/host/commands/get-workspaces.jsx +29 -0
- premiere_cli/panel/host/commands/get-xmp-metadata.jsx +107 -0
- premiere_cli/panel/host/commands/import-ae-comps.jsx +129 -0
- premiere_cli/panel/host/commands/import-fcp-xml.jsx +103 -0
- premiere_cli/panel/host/commands/import-folder.jsx +193 -0
- premiere_cli/panel/host/commands/import-image-sequence.jsx +171 -0
- premiere_cli/panel/host/commands/import-media.jsx +217 -0
- premiere_cli/panel/host/commands/import-mogrt-from-library.jsx +105 -0
- premiere_cli/panel/host/commands/import-mogrt.jsx +111 -0
- premiere_cli/panel/host/commands/import-sequences-from-project.jsx +80 -0
- premiere_cli/panel/host/commands/insert-from-source.jsx +162 -0
- premiere_cli/panel/host/commands/inspect-dom-object.jsx +162 -0
- premiere_cli/panel/host/commands/invert-selection.jsx +114 -0
- premiere_cli/panel/host/commands/is-work-area-enabled.jsx +88 -0
- premiere_cli/panel/host/commands/lift-selection.jsx +106 -0
- premiere_cli/panel/host/commands/link-selection.jsx +111 -0
- premiere_cli/panel/host/commands/list-available-audio-effects.jsx +33 -0
- premiere_cli/panel/host/commands/list-available-audio-transitions.jsx +35 -0
- premiere_cli/panel/host/commands/list-available-effects.jsx +33 -0
- premiere_cli/panel/host/commands/list-available-transitions.jsx +74 -0
- premiere_cli/panel/host/commands/list-markers.jsx +69 -0
- premiere_cli/panel/host/commands/list-project-items.jsx +105 -0
- premiere_cli/panel/host/commands/lock-track.jsx +114 -0
- premiere_cli/panel/host/commands/manage-proxies.jsx +176 -0
- premiere_cli/panel/host/commands/match-frame.jsx +141 -0
- premiere_cli/panel/host/commands/move-clip-to-track.jsx +220 -0
- premiere_cli/panel/host/commands/move-clip.jsx +97 -0
- premiere_cli/panel/host/commands/move-items-to-bin.jsx +194 -0
- premiere_cli/panel/host/commands/move-playhead-to-edit.jsx +174 -0
- premiere_cli/panel/host/commands/move-playhead.jsx +137 -0
- premiere_cli/panel/host/commands/nest-clips.jsx +179 -0
- premiere_cli/panel/host/commands/open-in-source.jsx +117 -0
- premiere_cli/panel/host/commands/open-project.jsx +61 -0
- premiere_cli/panel/host/commands/overwrite-clip-at.jsx +350 -0
- premiere_cli/panel/host/commands/overwrite-from-source.jsx +150 -0
- premiere_cli/panel/host/commands/play-source-monitor.jsx +36 -0
- premiere_cli/panel/host/commands/play-timeline.jsx +24 -0
- premiere_cli/panel/host/commands/razor-all-tracks.jsx +171 -0
- premiere_cli/panel/host/commands/redo.jsx +69 -0
- premiere_cli/panel/host/commands/refresh-media.jsx +101 -0
- premiere_cli/panel/host/commands/relink-media.jsx +132 -0
- premiere_cli/panel/host/commands/remove-all-effects.jsx +114 -0
- premiere_cli/panel/host/commands/remove-effect-by-name.jsx +143 -0
- premiere_cli/panel/host/commands/remove-effect.jsx +122 -0
- premiere_cli/panel/host/commands/remove-from-timeline.jsx +93 -0
- premiere_cli/panel/host/commands/remove-keyframe-range.jsx +173 -0
- premiere_cli/panel/host/commands/remove-keyframe.jsx +192 -0
- premiere_cli/panel/host/commands/remove-selected-clips.jsx +126 -0
- premiere_cli/panel/host/commands/remove-track-intervals.jsx +254 -0
- premiere_cli/panel/host/commands/remove-transition.jsx +164 -0
- premiere_cli/panel/host/commands/rename-bin.jsx +88 -0
- premiere_cli/panel/host/commands/rename-clip.jsx +127 -0
- premiere_cli/panel/host/commands/rename-project-item.jsx +111 -0
- premiere_cli/panel/host/commands/rename-track.jsx +84 -0
- premiere_cli/panel/host/commands/replace-clip-media.jsx +140 -0
- premiere_cli/panel/host/commands/replace-clip.jsx +188 -0
- premiere_cli/panel/host/commands/reverse-clip.jsx +187 -0
- premiere_cli/panel/host/commands/ripple-delete-clip.jsx +156 -0
- premiere_cli/panel/host/commands/roll-edit.jsx +162 -0
- premiere_cli/panel/host/commands/save-project-as.jsx +55 -0
- premiere_cli/panel/host/commands/save-project.jsx +57 -0
- premiere_cli/panel/host/commands/scene-edit-detection.jsx +128 -0
- premiere_cli/panel/host/commands/search-project-items.jsx +180 -0
- premiere_cli/panel/host/commands/select-all-clips.jsx +107 -0
- premiere_cli/panel/host/commands/select-clips-by-color.jsx +142 -0
- premiere_cli/panel/host/commands/select-clips-by-name.jsx +133 -0
- premiere_cli/panel/host/commands/select-clips-in-range.jsx +133 -0
- premiere_cli/panel/host/commands/select-disabled-clips.jsx +127 -0
- premiere_cli/panel/host/commands/select-project-item.jsx +115 -0
- premiere_cli/panel/host/commands/set-active-project.jsx +184 -0
- premiere_cli/panel/host/commands/set-active-sequence.jsx +87 -0
- premiere_cli/panel/host/commands/set-all-tracks-targeted.jsx +112 -0
- premiere_cli/panel/host/commands/set-anti-alias-quality.jsx +125 -0
- premiere_cli/panel/host/commands/set-blend-mode.jsx +111 -0
- premiere_cli/panel/host/commands/set-clip-anchor-point.jsx +102 -0
- premiere_cli/panel/host/commands/set-clip-enabled.jsx +127 -0
- premiere_cli/panel/host/commands/set-clip-opacity.jsx +102 -0
- premiere_cli/panel/host/commands/set-clip-pan.jsx +107 -0
- premiere_cli/panel/host/commands/set-clip-position.jsx +103 -0
- premiere_cli/panel/host/commands/set-clip-properties.jsx +221 -0
- premiere_cli/panel/host/commands/set-clip-rotation.jsx +102 -0
- premiere_cli/panel/host/commands/set-clip-scale.jsx +102 -0
- premiere_cli/panel/host/commands/set-clip-selection.jsx +144 -0
- premiere_cli/panel/host/commands/set-clip-speed.jsx +160 -0
- premiere_cli/panel/host/commands/set-clip-volume.jsx +128 -0
- premiere_cli/panel/host/commands/set-color-label.jsx +123 -0
- premiere_cli/panel/host/commands/set-color-value.jsx +155 -0
- premiere_cli/panel/host/commands/set-effect-property.jsx +124 -0
- premiere_cli/panel/host/commands/set-footage-interpretation.jsx +173 -0
- premiere_cli/panel/host/commands/set-frame-blend.jsx +145 -0
- premiere_cli/panel/host/commands/set-graphics-white-luminance.jsx +73 -0
- premiere_cli/panel/host/commands/set-item-in-out.jsx +180 -0
- premiere_cli/panel/host/commands/set-item-metadata.jsx +134 -0
- premiere_cli/panel/host/commands/set-item-offline.jsx +109 -0
- premiere_cli/panel/host/commands/set-item-start-time.jsx +139 -0
- premiere_cli/panel/host/commands/set-keyframe-interpolation.jsx +186 -0
- premiere_cli/panel/host/commands/set-override-frame-rate.jsx +123 -0
- premiere_cli/panel/host/commands/set-override-pixel-aspect-ratio.jsx +129 -0
- premiere_cli/panel/host/commands/set-poster-frame.jsx +192 -0
- premiere_cli/panel/host/commands/set-project-panel-metadata.jsx +69 -0
- premiere_cli/panel/host/commands/set-scale-to-frame-size.jsx +101 -0
- premiere_cli/panel/host/commands/set-scale-width-height.jsx +140 -0
- premiere_cli/panel/host/commands/set-sequence-in-out.jsx +65 -0
- premiere_cli/panel/host/commands/set-sequence-settings.jsx +184 -0
- premiere_cli/panel/host/commands/set-source-in-out.jsx +98 -0
- premiere_cli/panel/host/commands/set-target-track.jsx +91 -0
- premiere_cli/panel/host/commands/set-time-interpolation.jsx +141 -0
- premiere_cli/panel/host/commands/set-track-mute.jsx +91 -0
- premiere_cli/panel/host/commands/set-track-visibility.jsx +94 -0
- premiere_cli/panel/host/commands/set-transcode-on-ingest.jsx +78 -0
- premiere_cli/panel/host/commands/set-uniform-scale.jsx +104 -0
- premiere_cli/panel/host/commands/set-work-area.jsx +76 -0
- premiere_cli/panel/host/commands/set-workspace.jsx +35 -0
- premiere_cli/panel/host/commands/set-xmp-metadata.jsx +157 -0
- premiere_cli/panel/host/commands/slide-edit.jsx +162 -0
- premiere_cli/panel/host/commands/slip-edit.jsx +167 -0
- premiere_cli/panel/host/commands/split-clip.jsx +144 -0
- premiere_cli/panel/host/commands/stabilize-clip.jsx +139 -0
- premiere_cli/panel/host/commands/stop-playback.jsx +23 -0
- premiere_cli/panel/host/commands/trim-clip.jsx +111 -0
- premiere_cli/panel/host/commands/undo.jsx +114 -0
- premiere_cli/panel/host/commands/unlink-selection.jsx +106 -0
- premiere_cli/panel/host/commands/unnest-sequence.jsx +207 -0
- premiere_cli/panel/host/commands/update-marker.jsx +120 -0
- premiere_cli/panel/host/index.jsx +1227 -0
- premiere_cli/panel/host/presets/default-4k-25fps.sqpreset +63 -0
- premiere_cli/panel/index.html +16 -0
- premiere_cli/panel/js/cs-interface.js +11 -0
- premiere_cli/panel/js/main.js +409 -0
- premiere_cli/panel_install.py +220 -0
- premiere_cli-0.2.0.dist-info/METADATA +127 -0
- premiere_cli-0.2.0.dist-info/RECORD +247 -0
- premiere_cli-0.2.0.dist-info/WHEEL +5 -0
- premiere_cli-0.2.0.dist-info/entry_points.txt +3 -0
- premiere_cli-0.2.0.dist-info/licenses/LICENSE +428 -0
- premiere_cli-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// Command: set-item-metadata → ppb_setItemMetadata
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context.
|
|
4
|
+
//
|
|
5
|
+
// Project-item addressing: at least one of nodeId/name is required (see
|
|
6
|
+
// get-item-metadata.jsx for the shared design note — the resolver is
|
|
7
|
+
// duplicated per-file since command files load independently).
|
|
8
|
+
//
|
|
9
|
+
// WRITE command — this is the write-side counterpart of get-item-metadata.
|
|
10
|
+
// setProjectMetadata(value, [fieldPath]) replaces the value at one field
|
|
11
|
+
// path (e.g. "Column.Intrinsic.Description"); it does NOT touch other
|
|
12
|
+
// fields. Undo is NON-FUNCTIONAL on this build — `previousValue` (the
|
|
13
|
+
// full metadata blob read before mutating) is the only restoration path
|
|
14
|
+
// if a caller needs to revert.
|
|
15
|
+
|
|
16
|
+
function ppbFindItemSetItemMetadata_walk(item, args, depth) {
|
|
17
|
+
if (depth > 32) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
var isBin = false;
|
|
22
|
+
try {
|
|
23
|
+
isBin = typeof ProjectItemType !== "undefined" && item.type === ProjectItemType.BIN;
|
|
24
|
+
} catch (e) {
|
|
25
|
+
isBin = false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var matched = false;
|
|
29
|
+
if (args.nodeId !== null) {
|
|
30
|
+
try { matched = item.nodeId === args.nodeId; } catch (e) { matched = false; }
|
|
31
|
+
} else if (args.name !== null) {
|
|
32
|
+
try { matched = item.name === args.name; } catch (e) { matched = false; }
|
|
33
|
+
}
|
|
34
|
+
if (matched) {
|
|
35
|
+
return item;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (isBin && item.children) {
|
|
39
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
40
|
+
var found = ppbFindItemSetItemMetadata_walk(item.children[i], args, depth + 1);
|
|
41
|
+
if (found) {
|
|
42
|
+
return found;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function ppbFindItemSetItemMetadata_resolve(args) {
|
|
50
|
+
var root = app.project.rootItem;
|
|
51
|
+
for (var i = 0; i < root.children.numItems; i++) {
|
|
52
|
+
var found = ppbFindItemSetItemMetadata_walk(root.children[i], args, 1);
|
|
53
|
+
if (found) {
|
|
54
|
+
return found;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function ppb_setItemMetadata(argsJson) {
|
|
61
|
+
try {
|
|
62
|
+
var args;
|
|
63
|
+
try {
|
|
64
|
+
args = JSON.parse(argsJson);
|
|
65
|
+
} catch (e) {
|
|
66
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
var hasNodeId = typeof args.nodeId === "string" && args.nodeId.length > 0;
|
|
70
|
+
var hasName = typeof args.name === "string" && args.name.length > 0;
|
|
71
|
+
if (!hasNodeId && !hasName) {
|
|
72
|
+
return JSON.stringify({ ok: false, error: "either nodeId or name is required" });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
var hasFieldPath = typeof args.fieldPath === "string" && args.fieldPath.length > 0;
|
|
76
|
+
if (!hasFieldPath) {
|
|
77
|
+
return JSON.stringify({ ok: false, error: "fieldPath is required" });
|
|
78
|
+
}
|
|
79
|
+
if (typeof args.value !== "string") {
|
|
80
|
+
return JSON.stringify({ ok: false, error: "value (string) is required" });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!app.project) {
|
|
84
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
var item = ppbFindItemSetItemMetadata_resolve({
|
|
88
|
+
nodeId: hasNodeId ? args.nodeId : null,
|
|
89
|
+
name: hasNodeId ? null : args.name
|
|
90
|
+
});
|
|
91
|
+
if (!item) {
|
|
92
|
+
return JSON.stringify({ ok: false, error: "no project item found matching the given nodeId/name" });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (typeof item.setProjectMetadata !== "function") {
|
|
96
|
+
return JSON.stringify({ ok: false, error: "setProjectMetadata is not available on this Premiere build" });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
var previousValue = null;
|
|
100
|
+
try { previousValue = item.getProjectMetadata(); } catch (e) { previousValue = null; }
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
item.setProjectMetadata(args.value, [args.fieldPath]);
|
|
104
|
+
} catch (e) {
|
|
105
|
+
return JSON.stringify({ ok: false, error: "setProjectMetadata() failed: " + e.toString() });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
var newValue = null;
|
|
109
|
+
try { newValue = item.getProjectMetadata(); } catch (e) { newValue = null; }
|
|
110
|
+
|
|
111
|
+
var verified = false;
|
|
112
|
+
try {
|
|
113
|
+
verified = typeof newValue === "string" && newValue.indexOf(args.value) !== -1;
|
|
114
|
+
} catch (e) {
|
|
115
|
+
verified = false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
var result = {
|
|
119
|
+
name: null,
|
|
120
|
+
nodeId: null,
|
|
121
|
+
fieldPath: args.fieldPath,
|
|
122
|
+
requestedValue: args.value,
|
|
123
|
+
previousValue: previousValue,
|
|
124
|
+
newValue: newValue,
|
|
125
|
+
verified: verified
|
|
126
|
+
};
|
|
127
|
+
try { result.name = item.name; } catch (e) { result.name = null; }
|
|
128
|
+
try { result.nodeId = item.nodeId; } catch (e) { result.nodeId = null; }
|
|
129
|
+
|
|
130
|
+
return JSON.stringify({ ok: true, result: result });
|
|
131
|
+
} catch (e) {
|
|
132
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Command: set-item-offline → ppb_setItemOffline
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (TICKS_PER_SECOND, ...)
|
|
4
|
+
// are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// Ports the reference project's media.ts set_offline tool. Item resolution
|
|
7
|
+
// by nodeId/name uses children-presence recursion (NOT an isBin() gate),
|
|
8
|
+
// per get-project-item-info.jsx's live-debugged finding. **Destructive-ish**:
|
|
9
|
+
// unlinks the item's media (item.setOffline()); undo is non-functional on
|
|
10
|
+
// this build, so there is no scripted path back — relink-media is the
|
|
11
|
+
// manual recovery path once a new/original file path is known. Verified
|
|
12
|
+
// via an isOffline() read-back.
|
|
13
|
+
|
|
14
|
+
function ppbSetItemOffline_findByNodeId(item, nodeId, depth) {
|
|
15
|
+
if (depth > 32) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
if (item.nodeId === nodeId) {
|
|
20
|
+
return item;
|
|
21
|
+
}
|
|
22
|
+
} catch (e) {
|
|
23
|
+
// fall through
|
|
24
|
+
}
|
|
25
|
+
if (item.children && item.children.numItems > 0) {
|
|
26
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
27
|
+
var found = ppbSetItemOffline_findByNodeId(item.children[i], nodeId, depth + 1);
|
|
28
|
+
if (found) {
|
|
29
|
+
return found;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function ppbSetItemOffline_findByName(item, name, depth) {
|
|
37
|
+
if (depth > 32) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
if (item.name === name) {
|
|
42
|
+
return item;
|
|
43
|
+
}
|
|
44
|
+
} catch (e) {
|
|
45
|
+
// fall through
|
|
46
|
+
}
|
|
47
|
+
if (item.children && item.children.numItems > 0) {
|
|
48
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
49
|
+
var found = ppbSetItemOffline_findByName(item.children[i], name, depth + 1);
|
|
50
|
+
if (found) {
|
|
51
|
+
return found;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function ppb_setItemOffline(argsJson) {
|
|
59
|
+
try {
|
|
60
|
+
var args;
|
|
61
|
+
try {
|
|
62
|
+
args = JSON.parse(argsJson);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
var hasNodeId = typeof args.nodeId === "string" && args.nodeId.length > 0;
|
|
68
|
+
var hasName = typeof args.name === "string" && args.name.length > 0;
|
|
69
|
+
if (!hasNodeId && !hasName) {
|
|
70
|
+
return JSON.stringify({ ok: false, error: "either nodeId or name is required" });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!app.project) {
|
|
74
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
var item = hasNodeId
|
|
78
|
+
? ppbSetItemOffline_findByNodeId(app.project.rootItem, args.nodeId, 0)
|
|
79
|
+
: ppbSetItemOffline_findByName(app.project.rootItem, args.name, 0);
|
|
80
|
+
if (!item) {
|
|
81
|
+
return JSON.stringify({ ok: false, error: "no project item found matching the given nodeId/name" });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
var previousValue = null;
|
|
85
|
+
try { previousValue = item.isOffline(); } catch (e) { previousValue = null; }
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
item.setOffline();
|
|
89
|
+
} catch (e) {
|
|
90
|
+
return JSON.stringify({ ok: false, error: "setOffline() failed: " + e.toString() });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
var newValue = null;
|
|
94
|
+
try { newValue = item.isOffline(); } catch (e) { newValue = null; }
|
|
95
|
+
|
|
96
|
+
return JSON.stringify({
|
|
97
|
+
ok: true,
|
|
98
|
+
result: {
|
|
99
|
+
nodeId: item.nodeId,
|
|
100
|
+
name: item.name,
|
|
101
|
+
previousValue: previousValue,
|
|
102
|
+
newValue: newValue,
|
|
103
|
+
verified: newValue === true
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
} catch (e) {
|
|
107
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Command: set-item-start-time → ppb_setItemStartTime
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (TICKS_PER_SECOND, ...)
|
|
4
|
+
// are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// Ports the reference project's media.ts/track-targeting.ts set_start_time
|
|
7
|
+
// tool (setStartTime — timecode offset for the source media, not a
|
|
8
|
+
// timeline position). Item resolution by nodeId/name uses children-
|
|
9
|
+
// presence recursion (NOT an isBin() gate), per get-project-item-info.jsx's
|
|
10
|
+
// live-debugged finding. Converts seconds to a ticks string (per
|
|
11
|
+
// PREMIERE_API_NOTES.md's item.setStartTime(ticksStr) signature) before
|
|
12
|
+
// calling. No confirmed getter exists for a project item's start time on
|
|
13
|
+
// this build, so a short list of plausible getter names is probed for
|
|
14
|
+
// read-back verification — same defensive pattern as set-poster-frame.
|
|
15
|
+
|
|
16
|
+
function ppbSetItemStartTime_findByNodeId(item, nodeId, depth) {
|
|
17
|
+
if (depth > 32) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
if (item.nodeId === nodeId) {
|
|
22
|
+
return item;
|
|
23
|
+
}
|
|
24
|
+
} catch (e) {
|
|
25
|
+
// fall through
|
|
26
|
+
}
|
|
27
|
+
if (item.children && item.children.numItems > 0) {
|
|
28
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
29
|
+
var found = ppbSetItemStartTime_findByNodeId(item.children[i], nodeId, depth + 1);
|
|
30
|
+
if (found) {
|
|
31
|
+
return found;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function ppbSetItemStartTime_findByName(item, name, depth) {
|
|
39
|
+
if (depth > 32) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
if (item.name === name) {
|
|
44
|
+
return item;
|
|
45
|
+
}
|
|
46
|
+
} catch (e) {
|
|
47
|
+
// fall through
|
|
48
|
+
}
|
|
49
|
+
if (item.children && item.children.numItems > 0) {
|
|
50
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
51
|
+
var found = ppbSetItemStartTime_findByName(item.children[i], name, depth + 1);
|
|
52
|
+
if (found) {
|
|
53
|
+
return found;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Probes a short list of plausible getter names/shapes for a project
|
|
61
|
+
// item's start time — none is documented in PREMIERE_API_NOTES.md, unlike
|
|
62
|
+
// the well-confirmed getInPoint()/getOutPoint() pair. Returns seconds, or
|
|
63
|
+
// null if none of the probed getters exist/succeed.
|
|
64
|
+
function ppbSetItemStartTime_probeGetter(item) {
|
|
65
|
+
var candidates = ["getStartTime", "getStartOffset"];
|
|
66
|
+
for (var i = 0; i < candidates.length; i++) {
|
|
67
|
+
try {
|
|
68
|
+
if (typeof item[candidates[i]] === "function") {
|
|
69
|
+
var raw = item[candidates[i]]();
|
|
70
|
+
if (raw !== null && typeof raw !== "undefined") {
|
|
71
|
+
return { name: candidates[i], seconds: timeValueToSeconds(raw) };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
// try next candidate
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function ppb_setItemStartTime(argsJson) {
|
|
82
|
+
try {
|
|
83
|
+
var args;
|
|
84
|
+
try {
|
|
85
|
+
args = JSON.parse(argsJson);
|
|
86
|
+
} catch (e) {
|
|
87
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
var hasNodeId = typeof args.nodeId === "string" && args.nodeId.length > 0;
|
|
91
|
+
var hasName = typeof args.name === "string" && args.name.length > 0;
|
|
92
|
+
if (!hasNodeId && !hasName) {
|
|
93
|
+
return JSON.stringify({ ok: false, error: "either nodeId or name is required" });
|
|
94
|
+
}
|
|
95
|
+
if (typeof args.seconds !== "number") {
|
|
96
|
+
return JSON.stringify({ ok: false, error: "seconds is required and must be a number" });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!app.project) {
|
|
100
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
var item = hasNodeId
|
|
104
|
+
? ppbSetItemStartTime_findByNodeId(app.project.rootItem, args.nodeId, 0)
|
|
105
|
+
: ppbSetItemStartTime_findByName(app.project.rootItem, args.name, 0);
|
|
106
|
+
if (!item) {
|
|
107
|
+
return JSON.stringify({ ok: false, error: "no project item found matching the given nodeId/name" });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
var before = ppbSetItemStartTime_probeGetter(item);
|
|
111
|
+
var ticksStr = String(Math.round(args.seconds * TICKS_PER_SECOND));
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
item.setStartTime(ticksStr);
|
|
115
|
+
} catch (e) {
|
|
116
|
+
return JSON.stringify({ ok: false, error: "setStartTime() failed: " + e.toString() });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
var after = ppbSetItemStartTime_probeGetter(item);
|
|
120
|
+
|
|
121
|
+
return JSON.stringify({
|
|
122
|
+
ok: true,
|
|
123
|
+
result: {
|
|
124
|
+
nodeId: item.nodeId,
|
|
125
|
+
name: item.name,
|
|
126
|
+
requestedSeconds: args.seconds,
|
|
127
|
+
ticksString: ticksStr,
|
|
128
|
+
previousValue: before ? before.seconds : null,
|
|
129
|
+
newValue: after ? after.seconds : null,
|
|
130
|
+
readBackGetterUsed: after ? after.name : null,
|
|
131
|
+
note: after
|
|
132
|
+
? null
|
|
133
|
+
: "no confirmed getter for a project item's start time exists on this build — only the setter's non-throw result is confirmed"
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
} catch (e) {
|
|
137
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// Command: set-keyframe-interpolation → ppb_setKeyframeInterpolation
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (findSequenceByName,
|
|
4
|
+
// findClipComponent, findComponentProperty, timeValueToSeconds,
|
|
5
|
+
// keyTimeToSeconds, tryTimeForms, getSequenceFps, ...) are already defined
|
|
6
|
+
// there.
|
|
7
|
+
//
|
|
8
|
+
// Standard-DOM mutation. Ported from leancoderkavy's premiere-pro-mcp
|
|
9
|
+
// `set_keyframe_interpolation` tool (keyframes.ts), addressed here by
|
|
10
|
+
// trackType/trackIndex/clipIndex + componentName/propertyName. `seconds`
|
|
11
|
+
// is clip-relative, offset by clip.start to sequence time (same half-frame
|
|
12
|
+
// tolerance existing-key lookup as remove-keyframe).
|
|
13
|
+
//
|
|
14
|
+
// interpolationType IS A RAW INT, and its enum meaning is DISPUTED across
|
|
15
|
+
// Premiere builds per PREMIERE_API_NOTES.md's Property API block:
|
|
16
|
+
// leancoderkavy uses 0=Linear, 4=Hold, 5=Bezier; ayushozha's own docs claim
|
|
17
|
+
// a plain 0/1/2 map instead. This command does NOT translate a name to an
|
|
18
|
+
// int — the caller passes the raw int and gets it back unmodified; treat
|
|
19
|
+
// the actual on-screen result as the source of truth until verified live.
|
|
20
|
+
// There is no confirmed getter to read a keyframe's current interpolation
|
|
21
|
+
// back — `verified` here only means the setInterpolationTypeAtKey() call
|
|
22
|
+
// itself did not throw, NOT that Premiere applied the requested type.
|
|
23
|
+
function ppb_setKeyframeInterpolation(argsJson) {
|
|
24
|
+
try {
|
|
25
|
+
var args;
|
|
26
|
+
try {
|
|
27
|
+
args = JSON.parse(argsJson);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (args.trackType !== "video" && args.trackType !== "audio") {
|
|
33
|
+
return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
|
|
34
|
+
}
|
|
35
|
+
if (typeof args.trackIndex !== "number" || args.trackIndex < 0 || Math.floor(args.trackIndex) !== args.trackIndex) {
|
|
36
|
+
return JSON.stringify({ ok: false, error: "trackIndex must be a non-negative integer" });
|
|
37
|
+
}
|
|
38
|
+
if (typeof args.clipIndex !== "number" || args.clipIndex < 0 || Math.floor(args.clipIndex) !== args.clipIndex) {
|
|
39
|
+
return JSON.stringify({ ok: false, error: "clipIndex must be a non-negative integer" });
|
|
40
|
+
}
|
|
41
|
+
if (typeof args.componentName !== "string" || !args.componentName) {
|
|
42
|
+
return JSON.stringify({ ok: false, error: "componentName is required" });
|
|
43
|
+
}
|
|
44
|
+
if (typeof args.propertyName !== "string" || !args.propertyName) {
|
|
45
|
+
return JSON.stringify({ ok: false, error: "propertyName is required" });
|
|
46
|
+
}
|
|
47
|
+
if (typeof args.seconds !== "number") {
|
|
48
|
+
return JSON.stringify({ ok: false, error: "seconds must be a number (clip-relative)" });
|
|
49
|
+
}
|
|
50
|
+
if (typeof args.interpolationType !== "number" || Math.floor(args.interpolationType) !== args.interpolationType) {
|
|
51
|
+
return JSON.stringify({ ok: false, error: "interpolationType must be an integer (meaning is version-dependent — see docs)" });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!app.project) {
|
|
55
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
var seq = null;
|
|
59
|
+
if (args.sequenceName && typeof args.sequenceName === "string") {
|
|
60
|
+
seq = findSequenceByName(args.sequenceName);
|
|
61
|
+
if (!seq) {
|
|
62
|
+
return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
seq = app.project.activeSequence;
|
|
66
|
+
if (!seq) {
|
|
67
|
+
return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
var trackCollection = args.trackType === "video" ? seq.videoTracks : seq.audioTracks;
|
|
72
|
+
var numTracks = trackCollection.numTracks;
|
|
73
|
+
if (args.trackIndex >= numTracks) {
|
|
74
|
+
return JSON.stringify({
|
|
75
|
+
ok: false,
|
|
76
|
+
error: "trackIndex " + args.trackIndex + " is out of range — sequence has " + numTracks + " " + args.trackType + " track(s)"
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
var track = trackCollection[args.trackIndex];
|
|
81
|
+
var numClips = track.clips.numItems;
|
|
82
|
+
if (args.clipIndex >= numClips) {
|
|
83
|
+
return JSON.stringify({
|
|
84
|
+
ok: false,
|
|
85
|
+
error: "clipIndex " + args.clipIndex + " is out of range — track " + args.trackIndex + " has " + numClips + " clip(s)"
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var clip = track.clips[args.clipIndex];
|
|
90
|
+
var clipName = null;
|
|
91
|
+
try { clipName = clip.name; } catch (e) { clipName = null; }
|
|
92
|
+
|
|
93
|
+
var clipStartSeconds = 0;
|
|
94
|
+
try { clipStartSeconds = timeValueToSeconds(clip.start) || 0; } catch (e) { clipStartSeconds = 0; }
|
|
95
|
+
|
|
96
|
+
var comp = findClipComponent(clip, [args.componentName], [args.componentName]);
|
|
97
|
+
if (!comp) {
|
|
98
|
+
return JSON.stringify({
|
|
99
|
+
ok: false,
|
|
100
|
+
error: "component \"" + args.componentName + "\" not found on clip (matched against matchName and displayName)"
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
var compDisplayName = null;
|
|
104
|
+
try { compDisplayName = comp.displayName; } catch (e) { compDisplayName = null; }
|
|
105
|
+
|
|
106
|
+
var prop = findComponentProperty(comp, [args.propertyName]);
|
|
107
|
+
if (!prop) {
|
|
108
|
+
return JSON.stringify({
|
|
109
|
+
ok: false,
|
|
110
|
+
error: "property \"" + args.propertyName + "\" not found on component \"" + compDisplayName + "\""
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
var fps = 30;
|
|
115
|
+
try { fps = getSequenceFps(seq) || 30; } catch (e) { fps = 30; }
|
|
116
|
+
var toleranceSeconds = 0.5 / fps;
|
|
117
|
+
|
|
118
|
+
var sequenceSeconds = clipStartSeconds + args.seconds;
|
|
119
|
+
|
|
120
|
+
var rawKeys = null;
|
|
121
|
+
try { rawKeys = prop.getKeys(); } catch (e) { rawKeys = null; }
|
|
122
|
+
|
|
123
|
+
var matchedKey = null;
|
|
124
|
+
var matchedSeconds = null;
|
|
125
|
+
if (rawKeys) {
|
|
126
|
+
for (var i = 0; i < rawKeys.length; i++) {
|
|
127
|
+
var ks = null;
|
|
128
|
+
try { ks = keyTimeToSeconds(rawKeys[i]); } catch (e1) { ks = null; }
|
|
129
|
+
if (ks !== null && Math.abs(ks - sequenceSeconds) <= toleranceSeconds) {
|
|
130
|
+
matchedKey = rawKeys[i];
|
|
131
|
+
matchedSeconds = ks;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
var interpolationType = args.interpolationType;
|
|
138
|
+
var setAttempts = [];
|
|
139
|
+
var set = false;
|
|
140
|
+
|
|
141
|
+
if (matchedKey !== null) {
|
|
142
|
+
try {
|
|
143
|
+
prop.setInterpolationTypeAtKey(matchedKey, interpolationType, true);
|
|
144
|
+
setAttempts.push({ form: "existingKeyObject", success: true });
|
|
145
|
+
set = true;
|
|
146
|
+
} catch (e2) {
|
|
147
|
+
setAttempts.push({ form: "existingKeyObject", success: false, error: e2.toString() });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!set) {
|
|
152
|
+
var tf = tryTimeForms(sequenceSeconds, function (t) {
|
|
153
|
+
prop.setInterpolationTypeAtKey(t, interpolationType, true);
|
|
154
|
+
});
|
|
155
|
+
setAttempts = setAttempts.concat(tf.attempts);
|
|
156
|
+
set = tf.success;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return JSON.stringify({
|
|
160
|
+
ok: true,
|
|
161
|
+
result: {
|
|
162
|
+
sequenceName: seq.name,
|
|
163
|
+
trackType: args.trackType,
|
|
164
|
+
trackIndex: args.trackIndex,
|
|
165
|
+
clipIndex: args.clipIndex,
|
|
166
|
+
clipName: clipName,
|
|
167
|
+
componentName: compDisplayName,
|
|
168
|
+
propertyName: args.propertyName,
|
|
169
|
+
seconds: args.seconds,
|
|
170
|
+
sequenceSeconds: sequenceSeconds,
|
|
171
|
+
toleranceSeconds: toleranceSeconds,
|
|
172
|
+
matchedExistingKey: matchedKey !== null,
|
|
173
|
+
matchedSeconds: matchedSeconds,
|
|
174
|
+
interpolationType: interpolationType,
|
|
175
|
+
setAttempts: setAttempts,
|
|
176
|
+
called: set,
|
|
177
|
+
note: "interpolationType is a RAW INT whose enum meaning is DISPUTED across Premiere builds " +
|
|
178
|
+
"(0=Linear/4=Hold/5=Bezier per one reference repo vs. a plain 0/1/2 map per another) — " +
|
|
179
|
+
"no name-mapping is applied here. `called` only confirms the call didn't throw; there is " +
|
|
180
|
+
"no confirmed getter to read a keyframe's interpolation back and verify the result."
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
} catch (e) {
|
|
184
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// Command: set-override-frame-rate → ppb_setOverrideFrameRate
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (TICKS_PER_SECOND, ...)
|
|
4
|
+
// are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// Ports the reference project's media.ts set_override_frame_rate tool.
|
|
7
|
+
// Item resolution by nodeId/name uses children-presence recursion (NOT an
|
|
8
|
+
// isBin() gate), per get-project-item-info.jsx's live-debugged finding.
|
|
9
|
+
// previousValue/newValue are read via item.getFootageInterpretation().
|
|
10
|
+
// frameRate (same field get-footage-interpretation exposes) before/after
|
|
11
|
+
// calling item.setOverrideFrameRate(fps). Undo is non-functional on this
|
|
12
|
+
// build — previousValue is the only restoration path.
|
|
13
|
+
|
|
14
|
+
function ppbSetOverrideFrameRate_findByNodeId(item, nodeId, depth) {
|
|
15
|
+
if (depth > 32) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
if (item.nodeId === nodeId) {
|
|
20
|
+
return item;
|
|
21
|
+
}
|
|
22
|
+
} catch (e) {
|
|
23
|
+
// fall through
|
|
24
|
+
}
|
|
25
|
+
if (item.children && item.children.numItems > 0) {
|
|
26
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
27
|
+
var found = ppbSetOverrideFrameRate_findByNodeId(item.children[i], nodeId, depth + 1);
|
|
28
|
+
if (found) {
|
|
29
|
+
return found;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function ppbSetOverrideFrameRate_findByName(item, name, depth) {
|
|
37
|
+
if (depth > 32) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
if (item.name === name) {
|
|
42
|
+
return item;
|
|
43
|
+
}
|
|
44
|
+
} catch (e) {
|
|
45
|
+
// fall through
|
|
46
|
+
}
|
|
47
|
+
if (item.children && item.children.numItems > 0) {
|
|
48
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
49
|
+
var found = ppbSetOverrideFrameRate_findByName(item.children[i], name, depth + 1);
|
|
50
|
+
if (found) {
|
|
51
|
+
return found;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function ppbSetOverrideFrameRate_readFrameRate(item) {
|
|
59
|
+
try {
|
|
60
|
+
var interp = item.getFootageInterpretation();
|
|
61
|
+
if (interp) {
|
|
62
|
+
return interp.frameRate;
|
|
63
|
+
}
|
|
64
|
+
} catch (e) {
|
|
65
|
+
// fall through
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function ppb_setOverrideFrameRate(argsJson) {
|
|
71
|
+
try {
|
|
72
|
+
var args;
|
|
73
|
+
try {
|
|
74
|
+
args = JSON.parse(argsJson);
|
|
75
|
+
} catch (e) {
|
|
76
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
var hasNodeId = typeof args.nodeId === "string" && args.nodeId.length > 0;
|
|
80
|
+
var hasName = typeof args.name === "string" && args.name.length > 0;
|
|
81
|
+
if (!hasNodeId && !hasName) {
|
|
82
|
+
return JSON.stringify({ ok: false, error: "either nodeId or name is required" });
|
|
83
|
+
}
|
|
84
|
+
if (typeof args.fps !== "number" || args.fps <= 0) {
|
|
85
|
+
return JSON.stringify({ ok: false, error: "fps must be a positive number" });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!app.project) {
|
|
89
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
var item = hasNodeId
|
|
93
|
+
? ppbSetOverrideFrameRate_findByNodeId(app.project.rootItem, args.nodeId, 0)
|
|
94
|
+
: ppbSetOverrideFrameRate_findByName(app.project.rootItem, args.name, 0);
|
|
95
|
+
if (!item) {
|
|
96
|
+
return JSON.stringify({ ok: false, error: "no project item found matching the given nodeId/name" });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
var previousValue = ppbSetOverrideFrameRate_readFrameRate(item);
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
item.setOverrideFrameRate(args.fps);
|
|
103
|
+
} catch (e) {
|
|
104
|
+
return JSON.stringify({ ok: false, error: "setOverrideFrameRate() failed: " + e.toString() });
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
var newValue = ppbSetOverrideFrameRate_readFrameRate(item);
|
|
108
|
+
|
|
109
|
+
return JSON.stringify({
|
|
110
|
+
ok: true,
|
|
111
|
+
result: {
|
|
112
|
+
nodeId: item.nodeId,
|
|
113
|
+
name: item.name,
|
|
114
|
+
previousValue: previousValue,
|
|
115
|
+
requestedValue: args.fps,
|
|
116
|
+
newValue: newValue,
|
|
117
|
+
verified: newValue !== null && Math.abs(newValue - args.fps) < 0.001
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
} catch (e) {
|
|
121
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
122
|
+
}
|
|
123
|
+
}
|