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.
Files changed (247) hide show
  1. premiere_cli/__init__.py +11 -0
  2. premiere_cli/cli.py +3664 -0
  3. premiere_cli/log.py +66 -0
  4. premiere_cli/panel/.debug +8 -0
  5. premiere_cli/panel/CSXS/manifest.xml +52 -0
  6. premiere_cli/panel/css/style.css +53 -0
  7. premiere_cli/panel/host/commands/add-adjustment-layer.jsx +190 -0
  8. premiere_cli/panel/host/commands/add-audio-keyframes.jsx +176 -0
  9. premiere_cli/panel/host/commands/add-custom-metadata-field.jsx +63 -0
  10. premiere_cli/panel/host/commands/add-keyframe.jsx +181 -0
  11. premiere_cli/panel/host/commands/add-marker-to-project-item.jsx +194 -0
  12. premiere_cli/panel/host/commands/add-marker.jsx +129 -0
  13. premiere_cli/panel/host/commands/add-text-overlay.jsx +101 -0
  14. premiere_cli/panel/host/commands/add-to-render-queue.jsx +120 -0
  15. premiere_cli/panel/host/commands/add-to-timeline.jsx +300 -0
  16. premiere_cli/panel/host/commands/add-track.jsx +188 -0
  17. premiere_cli/panel/host/commands/add-transition.jsx +134 -0
  18. premiere_cli/panel/host/commands/adjust-audio-levels.jsx +132 -0
  19. premiere_cli/panel/host/commands/apply-audio-effect.jsx +118 -0
  20. premiere_cli/panel/host/commands/apply-effect.jsx +122 -0
  21. premiere_cli/panel/host/commands/apply-lut.jsx +107 -0
  22. premiere_cli/panel/host/commands/attach-custom-property.jsx +66 -0
  23. premiere_cli/panel/host/commands/auto-reframe-sequence.jsx +124 -0
  24. premiere_cli/panel/host/commands/batch-add-transitions.jsx +158 -0
  25. premiere_cli/panel/host/commands/batch-apply-effect.jsx +182 -0
  26. premiere_cli/panel/host/commands/batch-rename-clips.jsx +170 -0
  27. premiere_cli/panel/host/commands/batch-set-clips-enabled.jsx +145 -0
  28. premiere_cli/panel/host/commands/clear-item-in-out.jsx +117 -0
  29. premiere_cli/panel/host/commands/clear-sequence-in-out.jsx +100 -0
  30. premiere_cli/panel/host/commands/close-all-source-clips.jsx +32 -0
  31. premiere_cli/panel/host/commands/close-sequence.jsx +80 -0
  32. premiere_cli/panel/host/commands/close-source-monitor.jsx +32 -0
  33. premiere_cli/panel/host/commands/color-correct.jsx +164 -0
  34. premiere_cli/panel/host/commands/copy-effect-values.jsx +183 -0
  35. premiere_cli/panel/host/commands/copy-effects-between-clips.jsx +234 -0
  36. premiere_cli/panel/host/commands/create-bars-and-tone.jsx +152 -0
  37. premiere_cli/panel/host/commands/create-bin.jsx +76 -0
  38. premiere_cli/panel/host/commands/create-caption-track.jsx +159 -0
  39. premiere_cli/panel/host/commands/create-sequence-from-clips.jsx +170 -0
  40. premiere_cli/panel/host/commands/create-sequence-from-preset.jsx +90 -0
  41. premiere_cli/panel/host/commands/create-sequence.jsx +166 -0
  42. premiere_cli/panel/host/commands/create-smart-bin.jsx +80 -0
  43. premiere_cli/panel/host/commands/create-subclip.jsx +248 -0
  44. premiere_cli/panel/host/commands/create-subsequence.jsx +136 -0
  45. premiere_cli/panel/host/commands/debug-qe-inspect.jsx +248 -0
  46. premiere_cli/panel/host/commands/debug-qe-try-mutate.jsx +305 -0
  47. premiere_cli/panel/host/commands/delete-marker.jsx +178 -0
  48. premiere_cli/panel/host/commands/deselect-all-clips.jsx +98 -0
  49. premiere_cli/panel/host/commands/detach-proxy.jsx +116 -0
  50. premiere_cli/panel/host/commands/duplicate-clip.jsx +140 -0
  51. premiere_cli/panel/host/commands/duplicate-sequence.jsx +150 -0
  52. premiere_cli/panel/host/commands/encode-file.jsx +86 -0
  53. premiere_cli/panel/host/commands/encode-project-item.jsx +145 -0
  54. premiere_cli/panel/host/commands/export-aaf.jsx +77 -0
  55. premiere_cli/panel/host/commands/export-fcp-xml.jsx +65 -0
  56. premiere_cli/panel/host/commands/export-frame.jsx +381 -0
  57. premiere_cli/panel/host/commands/export-omf.jsx +95 -0
  58. premiere_cli/panel/host/commands/export-sequence-as-project.jsx +65 -0
  59. premiere_cli/panel/host/commands/export-sequence.jsx +100 -0
  60. premiere_cli/panel/host/commands/extract-audio-track.jsx +181 -0
  61. premiere_cli/panel/host/commands/extract-selection.jsx +113 -0
  62. premiere_cli/panel/host/commands/find-items-by-media-path.jsx +112 -0
  63. premiere_cli/panel/host/commands/freeze-frame.jsx +215 -0
  64. premiere_cli/panel/host/commands/get-active-sequence.jsx +103 -0
  65. premiere_cli/panel/host/commands/get-all-project-paths.jsx +72 -0
  66. premiere_cli/panel/host/commands/get-bin-contents.jsx +176 -0
  67. premiere_cli/panel/host/commands/get-clip-adjustment-layer.jsx +83 -0
  68. premiere_cli/panel/host/commands/get-clip-at-playhead.jsx +99 -0
  69. premiere_cli/panel/host/commands/get-clip-at-position.jsx +120 -0
  70. premiere_cli/panel/host/commands/get-clip-links.jsx +135 -0
  71. premiere_cli/panel/host/commands/get-clip-markers.jsx +144 -0
  72. premiere_cli/panel/host/commands/get-clip-speed.jsx +69 -0
  73. premiere_cli/panel/host/commands/get-color-label.jsx +89 -0
  74. premiere_cli/panel/host/commands/get-color-space.jsx +99 -0
  75. premiere_cli/panel/host/commands/get-duplicate-media.jsx +78 -0
  76. premiere_cli/panel/host/commands/get-effect-properties.jsx +129 -0
  77. premiere_cli/panel/host/commands/get-encoder-presets.jsx +131 -0
  78. premiere_cli/panel/host/commands/get-export-file-extension.jsx +56 -0
  79. premiere_cli/panel/host/commands/get-footage-interpretation.jsx +113 -0
  80. premiere_cli/panel/host/commands/get-full-clip-info.jsx +162 -0
  81. premiere_cli/panel/host/commands/get-full-project-overview.jsx +193 -0
  82. premiere_cli/panel/host/commands/get-full-sequence-info.jsx +184 -0
  83. premiere_cli/panel/host/commands/get-graphics-white-luminance.jsx +31 -0
  84. premiere_cli/panel/host/commands/get-insertion-bin.jsx +35 -0
  85. premiere_cli/panel/host/commands/get-item-metadata.jsx +94 -0
  86. premiere_cli/panel/host/commands/get-keyframes.jsx +158 -0
  87. premiere_cli/panel/host/commands/get-mogrt-component.jsx +111 -0
  88. premiere_cli/panel/host/commands/get-next-edit-point.jsx +131 -0
  89. premiere_cli/panel/host/commands/get-offline-media.jsx +67 -0
  90. premiere_cli/panel/host/commands/get-open-projects.jsx +50 -0
  91. premiere_cli/panel/host/commands/get-premiere-state.jsx +164 -0
  92. premiere_cli/panel/host/commands/get-project-info.jsx +63 -0
  93. premiere_cli/panel/host/commands/get-project-item-info.jsx +247 -0
  94. premiere_cli/panel/host/commands/get-project-panel-metadata.jsx +30 -0
  95. premiere_cli/panel/host/commands/get-qe-clip-info.jsx +198 -0
  96. premiere_cli/panel/host/commands/get-render-queue-status.jsx +35 -0
  97. premiere_cli/panel/host/commands/get-sequence-count.jsx +24 -0
  98. premiere_cli/panel/host/commands/get-sequence-in-out.jsx +76 -0
  99. premiere_cli/panel/host/commands/get-sequence-markers-by-type.jsx +89 -0
  100. premiere_cli/panel/host/commands/get-source-monitor-info.jsx +34 -0
  101. premiere_cli/panel/host/commands/get-source-monitor-position.jsx +30 -0
  102. premiere_cli/panel/host/commands/get-target-tracks.jsx +76 -0
  103. premiere_cli/panel/host/commands/get-timeline-gaps.jsx +124 -0
  104. premiere_cli/panel/host/commands/get-timeline-summary.jsx +154 -0
  105. premiere_cli/panel/host/commands/get-total-clip-count.jsx +67 -0
  106. premiere_cli/panel/host/commands/get-track-info.jsx +117 -0
  107. premiere_cli/panel/host/commands/get-unused-media.jsx +99 -0
  108. premiere_cli/panel/host/commands/get-used-media-report.jsx +125 -0
  109. premiere_cli/panel/host/commands/get-value-at-time.jsx +135 -0
  110. premiere_cli/panel/host/commands/get-version-info.jsx +33 -0
  111. premiere_cli/panel/host/commands/get-work-area.jsx +52 -0
  112. premiere_cli/panel/host/commands/get-workspaces.jsx +29 -0
  113. premiere_cli/panel/host/commands/get-xmp-metadata.jsx +107 -0
  114. premiere_cli/panel/host/commands/import-ae-comps.jsx +129 -0
  115. premiere_cli/panel/host/commands/import-fcp-xml.jsx +103 -0
  116. premiere_cli/panel/host/commands/import-folder.jsx +193 -0
  117. premiere_cli/panel/host/commands/import-image-sequence.jsx +171 -0
  118. premiere_cli/panel/host/commands/import-media.jsx +217 -0
  119. premiere_cli/panel/host/commands/import-mogrt-from-library.jsx +105 -0
  120. premiere_cli/panel/host/commands/import-mogrt.jsx +111 -0
  121. premiere_cli/panel/host/commands/import-sequences-from-project.jsx +80 -0
  122. premiere_cli/panel/host/commands/insert-from-source.jsx +162 -0
  123. premiere_cli/panel/host/commands/inspect-dom-object.jsx +162 -0
  124. premiere_cli/panel/host/commands/invert-selection.jsx +114 -0
  125. premiere_cli/panel/host/commands/is-work-area-enabled.jsx +88 -0
  126. premiere_cli/panel/host/commands/lift-selection.jsx +106 -0
  127. premiere_cli/panel/host/commands/link-selection.jsx +111 -0
  128. premiere_cli/panel/host/commands/list-available-audio-effects.jsx +33 -0
  129. premiere_cli/panel/host/commands/list-available-audio-transitions.jsx +35 -0
  130. premiere_cli/panel/host/commands/list-available-effects.jsx +33 -0
  131. premiere_cli/panel/host/commands/list-available-transitions.jsx +74 -0
  132. premiere_cli/panel/host/commands/list-markers.jsx +69 -0
  133. premiere_cli/panel/host/commands/list-project-items.jsx +105 -0
  134. premiere_cli/panel/host/commands/lock-track.jsx +114 -0
  135. premiere_cli/panel/host/commands/manage-proxies.jsx +176 -0
  136. premiere_cli/panel/host/commands/match-frame.jsx +141 -0
  137. premiere_cli/panel/host/commands/move-clip-to-track.jsx +220 -0
  138. premiere_cli/panel/host/commands/move-clip.jsx +97 -0
  139. premiere_cli/panel/host/commands/move-items-to-bin.jsx +194 -0
  140. premiere_cli/panel/host/commands/move-playhead-to-edit.jsx +174 -0
  141. premiere_cli/panel/host/commands/move-playhead.jsx +137 -0
  142. premiere_cli/panel/host/commands/nest-clips.jsx +179 -0
  143. premiere_cli/panel/host/commands/open-in-source.jsx +117 -0
  144. premiere_cli/panel/host/commands/open-project.jsx +61 -0
  145. premiere_cli/panel/host/commands/overwrite-clip-at.jsx +350 -0
  146. premiere_cli/panel/host/commands/overwrite-from-source.jsx +150 -0
  147. premiere_cli/panel/host/commands/play-source-monitor.jsx +36 -0
  148. premiere_cli/panel/host/commands/play-timeline.jsx +24 -0
  149. premiere_cli/panel/host/commands/razor-all-tracks.jsx +171 -0
  150. premiere_cli/panel/host/commands/redo.jsx +69 -0
  151. premiere_cli/panel/host/commands/refresh-media.jsx +101 -0
  152. premiere_cli/panel/host/commands/relink-media.jsx +132 -0
  153. premiere_cli/panel/host/commands/remove-all-effects.jsx +114 -0
  154. premiere_cli/panel/host/commands/remove-effect-by-name.jsx +143 -0
  155. premiere_cli/panel/host/commands/remove-effect.jsx +122 -0
  156. premiere_cli/panel/host/commands/remove-from-timeline.jsx +93 -0
  157. premiere_cli/panel/host/commands/remove-keyframe-range.jsx +173 -0
  158. premiere_cli/panel/host/commands/remove-keyframe.jsx +192 -0
  159. premiere_cli/panel/host/commands/remove-selected-clips.jsx +126 -0
  160. premiere_cli/panel/host/commands/remove-track-intervals.jsx +254 -0
  161. premiere_cli/panel/host/commands/remove-transition.jsx +164 -0
  162. premiere_cli/panel/host/commands/rename-bin.jsx +88 -0
  163. premiere_cli/panel/host/commands/rename-clip.jsx +127 -0
  164. premiere_cli/panel/host/commands/rename-project-item.jsx +111 -0
  165. premiere_cli/panel/host/commands/rename-track.jsx +84 -0
  166. premiere_cli/panel/host/commands/replace-clip-media.jsx +140 -0
  167. premiere_cli/panel/host/commands/replace-clip.jsx +188 -0
  168. premiere_cli/panel/host/commands/reverse-clip.jsx +187 -0
  169. premiere_cli/panel/host/commands/ripple-delete-clip.jsx +156 -0
  170. premiere_cli/panel/host/commands/roll-edit.jsx +162 -0
  171. premiere_cli/panel/host/commands/save-project-as.jsx +55 -0
  172. premiere_cli/panel/host/commands/save-project.jsx +57 -0
  173. premiere_cli/panel/host/commands/scene-edit-detection.jsx +128 -0
  174. premiere_cli/panel/host/commands/search-project-items.jsx +180 -0
  175. premiere_cli/panel/host/commands/select-all-clips.jsx +107 -0
  176. premiere_cli/panel/host/commands/select-clips-by-color.jsx +142 -0
  177. premiere_cli/panel/host/commands/select-clips-by-name.jsx +133 -0
  178. premiere_cli/panel/host/commands/select-clips-in-range.jsx +133 -0
  179. premiere_cli/panel/host/commands/select-disabled-clips.jsx +127 -0
  180. premiere_cli/panel/host/commands/select-project-item.jsx +115 -0
  181. premiere_cli/panel/host/commands/set-active-project.jsx +184 -0
  182. premiere_cli/panel/host/commands/set-active-sequence.jsx +87 -0
  183. premiere_cli/panel/host/commands/set-all-tracks-targeted.jsx +112 -0
  184. premiere_cli/panel/host/commands/set-anti-alias-quality.jsx +125 -0
  185. premiere_cli/panel/host/commands/set-blend-mode.jsx +111 -0
  186. premiere_cli/panel/host/commands/set-clip-anchor-point.jsx +102 -0
  187. premiere_cli/panel/host/commands/set-clip-enabled.jsx +127 -0
  188. premiere_cli/panel/host/commands/set-clip-opacity.jsx +102 -0
  189. premiere_cli/panel/host/commands/set-clip-pan.jsx +107 -0
  190. premiere_cli/panel/host/commands/set-clip-position.jsx +103 -0
  191. premiere_cli/panel/host/commands/set-clip-properties.jsx +221 -0
  192. premiere_cli/panel/host/commands/set-clip-rotation.jsx +102 -0
  193. premiere_cli/panel/host/commands/set-clip-scale.jsx +102 -0
  194. premiere_cli/panel/host/commands/set-clip-selection.jsx +144 -0
  195. premiere_cli/panel/host/commands/set-clip-speed.jsx +160 -0
  196. premiere_cli/panel/host/commands/set-clip-volume.jsx +128 -0
  197. premiere_cli/panel/host/commands/set-color-label.jsx +123 -0
  198. premiere_cli/panel/host/commands/set-color-value.jsx +155 -0
  199. premiere_cli/panel/host/commands/set-effect-property.jsx +124 -0
  200. premiere_cli/panel/host/commands/set-footage-interpretation.jsx +173 -0
  201. premiere_cli/panel/host/commands/set-frame-blend.jsx +145 -0
  202. premiere_cli/panel/host/commands/set-graphics-white-luminance.jsx +73 -0
  203. premiere_cli/panel/host/commands/set-item-in-out.jsx +180 -0
  204. premiere_cli/panel/host/commands/set-item-metadata.jsx +134 -0
  205. premiere_cli/panel/host/commands/set-item-offline.jsx +109 -0
  206. premiere_cli/panel/host/commands/set-item-start-time.jsx +139 -0
  207. premiere_cli/panel/host/commands/set-keyframe-interpolation.jsx +186 -0
  208. premiere_cli/panel/host/commands/set-override-frame-rate.jsx +123 -0
  209. premiere_cli/panel/host/commands/set-override-pixel-aspect-ratio.jsx +129 -0
  210. premiere_cli/panel/host/commands/set-poster-frame.jsx +192 -0
  211. premiere_cli/panel/host/commands/set-project-panel-metadata.jsx +69 -0
  212. premiere_cli/panel/host/commands/set-scale-to-frame-size.jsx +101 -0
  213. premiere_cli/panel/host/commands/set-scale-width-height.jsx +140 -0
  214. premiere_cli/panel/host/commands/set-sequence-in-out.jsx +65 -0
  215. premiere_cli/panel/host/commands/set-sequence-settings.jsx +184 -0
  216. premiere_cli/panel/host/commands/set-source-in-out.jsx +98 -0
  217. premiere_cli/panel/host/commands/set-target-track.jsx +91 -0
  218. premiere_cli/panel/host/commands/set-time-interpolation.jsx +141 -0
  219. premiere_cli/panel/host/commands/set-track-mute.jsx +91 -0
  220. premiere_cli/panel/host/commands/set-track-visibility.jsx +94 -0
  221. premiere_cli/panel/host/commands/set-transcode-on-ingest.jsx +78 -0
  222. premiere_cli/panel/host/commands/set-uniform-scale.jsx +104 -0
  223. premiere_cli/panel/host/commands/set-work-area.jsx +76 -0
  224. premiere_cli/panel/host/commands/set-workspace.jsx +35 -0
  225. premiere_cli/panel/host/commands/set-xmp-metadata.jsx +157 -0
  226. premiere_cli/panel/host/commands/slide-edit.jsx +162 -0
  227. premiere_cli/panel/host/commands/slip-edit.jsx +167 -0
  228. premiere_cli/panel/host/commands/split-clip.jsx +144 -0
  229. premiere_cli/panel/host/commands/stabilize-clip.jsx +139 -0
  230. premiere_cli/panel/host/commands/stop-playback.jsx +23 -0
  231. premiere_cli/panel/host/commands/trim-clip.jsx +111 -0
  232. premiere_cli/panel/host/commands/undo.jsx +114 -0
  233. premiere_cli/panel/host/commands/unlink-selection.jsx +106 -0
  234. premiere_cli/panel/host/commands/unnest-sequence.jsx +207 -0
  235. premiere_cli/panel/host/commands/update-marker.jsx +120 -0
  236. premiere_cli/panel/host/index.jsx +1227 -0
  237. premiere_cli/panel/host/presets/default-4k-25fps.sqpreset +63 -0
  238. premiere_cli/panel/index.html +16 -0
  239. premiere_cli/panel/js/cs-interface.js +11 -0
  240. premiere_cli/panel/js/main.js +409 -0
  241. premiere_cli/panel_install.py +220 -0
  242. premiere_cli-0.2.0.dist-info/METADATA +127 -0
  243. premiere_cli-0.2.0.dist-info/RECORD +247 -0
  244. premiere_cli-0.2.0.dist-info/WHEEL +5 -0
  245. premiere_cli-0.2.0.dist-info/entry_points.txt +3 -0
  246. premiere_cli-0.2.0.dist-info/licenses/LICENSE +428 -0
  247. premiere_cli-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,120 @@
1
+ // Command: add-to-render-queue → ppb_addToRenderQueue
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — shared helpers (findSequenceByName,
4
+ // ...) are already defined there.
5
+ //
6
+ // Queues the given (or active) sequence for export in Adobe Media Encoder
7
+ // via app.encoder.launchEncoder() + encodeSequence() + startBatch()
8
+ // (PREMIERE_API_NOTES.md's "Export via AME" line). **Fire-and-forget**:
9
+ // there is no progress API — encodeSequence() returns as soon as the job
10
+ // is queued, long before AME finishes writing the file, so this command
11
+ // can NEVER verify the output file the way the exportAsMediaDirect-based
12
+ // commands (export-sequence, extract-audio-track) do. Callers must poll
13
+ // the output path themselves (or use get-render-queue-status, itself only
14
+ // an isRunning() probe) — presetPath MUST be an absolute .epr file path;
15
+ // a bare name like "H.264" silently fails with no jobID per
16
+ // PREMIERE_API_NOTES.md.
17
+
18
+ // range → workAreaType, same mapping as export-sequence's
19
+ // ppbExportSequenceRangeToWorkAreaType (duplicated here since each command
20
+ // file loads independently and cannot rely on another command file's
21
+ // helpers).
22
+ function ppbAddToRenderQueueRangeToWorkAreaType(range) {
23
+ if (range === "entire" || range === undefined || range === null) {
24
+ return { value: 0, label: "entire" };
25
+ }
26
+ if (range === "in-to-out") {
27
+ return { value: 1, label: "in-to-out" };
28
+ }
29
+ if (range === "work-area") {
30
+ return { value: 2, label: "work-area" };
31
+ }
32
+ return null;
33
+ }
34
+
35
+ function ppb_addToRenderQueue(argsJson) {
36
+ try {
37
+ var args;
38
+ try {
39
+ args = JSON.parse(argsJson);
40
+ } catch (e) {
41
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
42
+ }
43
+
44
+ if (!args.outputPath || typeof args.outputPath !== "string") {
45
+ return JSON.stringify({ ok: false, error: "outputPath is required" });
46
+ }
47
+ if (!args.presetPath || typeof args.presetPath !== "string") {
48
+ return JSON.stringify({ ok: false, error: "presetPath is required (an absolute .epr file path)" });
49
+ }
50
+
51
+ if (!app.project) {
52
+ return JSON.stringify({ ok: false, error: "no project open" });
53
+ }
54
+
55
+ var seq = null;
56
+ if (args.sequenceName && typeof args.sequenceName === "string") {
57
+ seq = findSequenceByName(args.sequenceName);
58
+ if (!seq) {
59
+ return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
60
+ }
61
+ } else {
62
+ seq = app.project.activeSequence;
63
+ if (!seq) {
64
+ return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
65
+ }
66
+ }
67
+
68
+ var rangeInfo = ppbAddToRenderQueueRangeToWorkAreaType(args.range);
69
+ if (!rangeInfo) {
70
+ return JSON.stringify({ ok: false, error: "range must be one of \"entire\", \"in-to-out\", \"work-area\"" });
71
+ }
72
+
73
+ var presetFile = new File(args.presetPath);
74
+ if (!presetFile.exists) {
75
+ return JSON.stringify({ ok: false, error: "preset file not found: " + args.presetPath });
76
+ }
77
+
78
+ var startBatch = args.startBatch === true;
79
+
80
+ if (!app.encoder) {
81
+ return JSON.stringify({ ok: false, error: "Adobe Media Encoder is not available (app.encoder is undefined)" });
82
+ }
83
+
84
+ try {
85
+ app.encoder.launchEncoder();
86
+ } catch (e) {
87
+ return JSON.stringify({ ok: false, error: "app.encoder.launchEncoder() failed: " + e.toString() });
88
+ }
89
+
90
+ try {
91
+ app.encoder.encodeSequence(seq, args.outputPath, args.presetPath, rangeInfo.value, 1 /* removeOnCompletion */);
92
+ } catch (e) {
93
+ return JSON.stringify({ ok: false, error: "app.encoder.encodeSequence() failed: " + e.toString() });
94
+ }
95
+
96
+ if (startBatch) {
97
+ try {
98
+ app.encoder.startBatch();
99
+ } catch (e) {
100
+ return JSON.stringify({ ok: false, error: "job was queued but app.encoder.startBatch() failed: " + e.toString() });
101
+ }
102
+ }
103
+
104
+ return JSON.stringify({
105
+ ok: true,
106
+ result: {
107
+ sequenceName: seq.name,
108
+ outputPath: args.outputPath,
109
+ presetPath: args.presetPath,
110
+ range: rangeInfo.label,
111
+ startBatch: startBatch,
112
+ note: "fire-and-forget: the job is queued in Adobe Media Encoder, not exported synchronously — " +
113
+ "there is no progress API, so this result does NOT confirm the output file exists yet. " +
114
+ "Poll outputPath yourself, or leave startBatch false and trigger the batch manually in AME."
115
+ }
116
+ });
117
+ } catch (e) {
118
+ return JSON.stringify({ ok: false, error: e.toString() });
119
+ }
120
+ }
@@ -0,0 +1,300 @@
1
+ // Command: add-to-timeline → ppb_addToTimeline
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — shared helpers (findSequenceByName,
4
+ // secondsToTicksString, timeValueToSeconds, serializeTrackItem, ...) are
5
+ // already defined there.
6
+ //
7
+ // Ported from leancoderkavy's premiere-pro-mcp add_to_timeline tool.
8
+ // UPDATED 2026-07-17 after the probe session (see BUILD_FINDINGS.md
9
+ // corrections): placement now goes through the TRACK object's own
10
+ // method — seq.videoTracks[i].insertClip(item, TimeObject) /
11
+ // .overwriteClip(item, TimeObject) — which live-verifiably HONORS the
12
+ // track index, unlike the sequence-level seq.insertClip()/
13
+ // overwriteClip(), which ignore their vIdx argument on this build (the
14
+ // pattern both the antipaster and hetpatel repos converged on). The
15
+ // sequence-level call (-1 as the non-addressed track index) is kept as
16
+ // a fallback if the track method is missing or throws.
17
+ //
18
+ // ⚠️ AUTO-LINKED AUDIO TRAP (PREMIERE_API_NOTES.md): placing a video clip
19
+ // whose source projectItem also has audio can silently place the linked
20
+ // audio on some audio track too, even though we passed audioTrackIndex
21
+ // -1 — and if that lands on top of existing content it can destroy it.
22
+ // Per hetpatel's fix, after any video-track placement we scan every
23
+ // audio track for a clip referencing the SAME projectItem.nodeId within
24
+ // 0.1s of the requested startSeconds and remove it (iterating backwards
25
+ // per track, since removal shifts later indices) — the caller only asked
26
+ // for a video placement, so any such auto-placed audio is unwanted.
27
+ //
28
+ // MUTATION RULE: every mutation here is verified by re-reading the
29
+ // timeline afterward — the target track's clip count before/after, and
30
+ // (best-effort) the newly-placed clip's own serialized state — rather
31
+ // than trusting insertClip()/overwriteClip()'s own (undocumented) return
32
+ // value.
33
+
34
+ function ppbFindItemAddToTimeline_walk(item, args, depth) {
35
+ if (depth > 32) {
36
+ return null;
37
+ }
38
+ var isBin = false;
39
+ try {
40
+ isBin = typeof ProjectItemType !== "undefined" && item.type === ProjectItemType.BIN;
41
+ } catch (e) {
42
+ isBin = false;
43
+ }
44
+ var matched = false;
45
+ if (args.nodeId !== null) {
46
+ try { matched = item.nodeId === args.nodeId; } catch (e) { matched = false; }
47
+ } else if (args.name !== null) {
48
+ try { matched = item.name === args.name; } catch (e) { matched = false; }
49
+ }
50
+ if (matched) {
51
+ return item;
52
+ }
53
+ if (isBin && item.children) {
54
+ for (var i = 0; i < item.children.numItems; i++) {
55
+ var found = ppbFindItemAddToTimeline_walk(item.children[i], args, depth + 1);
56
+ if (found) {
57
+ return found;
58
+ }
59
+ }
60
+ }
61
+ return null;
62
+ }
63
+
64
+ function ppbFindItemAddToTimeline_resolve(args) {
65
+ var root = app.project.rootItem;
66
+ for (var i = 0; i < root.children.numItems; i++) {
67
+ var found = ppbFindItemAddToTimeline_walk(root.children[i], args, 1);
68
+ if (found) {
69
+ return found;
70
+ }
71
+ }
72
+ return null;
73
+ }
74
+
75
+ // Removes every audio clip on ANY audio track whose source projectItem
76
+ // matches nodeId and whose start is within toleranceSeconds of
77
+ // targetStartSeconds — the auto-linked-audio cleanup described above.
78
+ // Iterates each track's clips backwards so index shifts from an earlier
79
+ // removal never skip a later match. Returns an array of
80
+ // {trackIndex, name, startSeconds} for whatever was removed.
81
+ function ppbAddToTimeline_cleanupLinkedAudio(seq, nodeId, targetStartSeconds, toleranceSeconds) {
82
+ var removed = [];
83
+ var numAudioTracks;
84
+ try {
85
+ numAudioTracks = seq.audioTracks.numTracks;
86
+ } catch (e) {
87
+ return removed;
88
+ }
89
+
90
+ for (var t = 0; t < numAudioTracks; t++) {
91
+ var track = seq.audioTracks[t];
92
+ var numClips;
93
+ try {
94
+ numClips = track.clips.numItems;
95
+ } catch (e2) {
96
+ continue;
97
+ }
98
+ for (var c = numClips - 1; c >= 0; c--) {
99
+ var clip = track.clips[c];
100
+ var clipNodeId = null;
101
+ try { clipNodeId = clip.projectItem.nodeId; } catch (e3) { clipNodeId = null; }
102
+ if (clipNodeId !== nodeId) {
103
+ continue;
104
+ }
105
+ var clipStart = null;
106
+ try { clipStart = timeValueToSeconds(clip.start); } catch (e4) { clipStart = null; }
107
+ if (clipStart === null || Math.abs(clipStart - targetStartSeconds) > toleranceSeconds) {
108
+ continue;
109
+ }
110
+ var clipName = null;
111
+ try { clipName = clip.name; } catch (e5) { clipName = null; }
112
+ try {
113
+ clip.remove(false, false);
114
+ removed.push({ trackIndex: t, name: clipName, startSeconds: clipStart });
115
+ } catch (e6) {
116
+ // leave it — best-effort cleanup, don't fail the whole command over it
117
+ }
118
+ }
119
+ }
120
+ return removed;
121
+ }
122
+
123
+ function ppb_addToTimeline(argsJson) {
124
+ try {
125
+ var args;
126
+ try {
127
+ args = JSON.parse(argsJson);
128
+ } catch (e) {
129
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
130
+ }
131
+
132
+ var hasNodeId = typeof args.nodeId === "string" && args.nodeId.length > 0;
133
+ var hasName = typeof args.name === "string" && args.name.length > 0;
134
+ if (!hasNodeId && !hasName) {
135
+ return JSON.stringify({ ok: false, error: "either nodeId or name is required to identify the project item" });
136
+ }
137
+ if (args.trackType !== "video" && args.trackType !== "audio") {
138
+ return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
139
+ }
140
+ if (typeof args.trackIndex !== "number") {
141
+ return JSON.stringify({ ok: false, error: "trackIndex is required" });
142
+ }
143
+ if (typeof args.startSeconds !== "number") {
144
+ return JSON.stringify({ ok: false, error: "startSeconds is required" });
145
+ }
146
+ if (args.mode !== "insert" && args.mode !== "overwrite") {
147
+ return JSON.stringify({ ok: false, error: "mode must be \"insert\" or \"overwrite\"" });
148
+ }
149
+
150
+ if (!app.project) {
151
+ return JSON.stringify({ ok: false, error: "no project open" });
152
+ }
153
+
154
+ var seq = null;
155
+ if (args.sequenceName && typeof args.sequenceName === "string") {
156
+ seq = findSequenceByName(args.sequenceName);
157
+ if (!seq) {
158
+ return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
159
+ }
160
+ } else {
161
+ seq = app.project.activeSequence;
162
+ if (!seq) {
163
+ return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
164
+ }
165
+ }
166
+
167
+ var item = ppbFindItemAddToTimeline_resolve({
168
+ nodeId: hasNodeId ? args.nodeId : null,
169
+ name: hasNodeId ? null : args.name
170
+ });
171
+ if (!item) {
172
+ return JSON.stringify({ ok: false, error: "no project item found matching the given nodeId/name" });
173
+ }
174
+ var itemNodeId = null;
175
+ try { itemNodeId = item.nodeId; } catch (e7) { itemNodeId = null; }
176
+
177
+ var trackCollection = args.trackType === "video" ? seq.videoTracks : seq.audioTracks;
178
+ var numTracks;
179
+ try { numTracks = trackCollection.numTracks; } catch (e8) { numTracks = 0; }
180
+ if (args.trackIndex >= numTracks) {
181
+ return JSON.stringify({ ok: false, error: "trackIndex " + args.trackIndex + " is out of range — sequence has " + numTracks + " " + args.trackType + " track(s)" });
182
+ }
183
+ var targetTrack = trackCollection[args.trackIndex];
184
+ var trackClipCountBefore = null;
185
+ try { trackClipCountBefore = targetTrack.clips.numItems; } catch (e9) { trackClipCountBefore = null; }
186
+
187
+ var vIdx = args.trackType === "video" ? args.trackIndex : -1;
188
+ var aIdx = args.trackType === "audio" ? args.trackIndex : -1;
189
+ var startTicks = secondsToTicksString(args.startSeconds);
190
+ var methodName = args.mode === "insert" ? "insertClip" : "overwriteClip";
191
+
192
+ // Track-object placement first — honors the track (live-verified
193
+ // 2026-07-17 with a Time object on video tracks 1 and 2).
194
+ var placementAttempts = [];
195
+ var placedVia = null;
196
+ if (typeof targetTrack[methodName] === "function") {
197
+ var timeObj = new Time();
198
+ timeObj.seconds = args.startSeconds;
199
+ try {
200
+ targetTrack[methodName](item, timeObj);
201
+ placementAttempts.push({ method: "track." + methodName + "(item, TimeObject)", success: true });
202
+ placedVia = "track." + methodName;
203
+ } catch (e10a) {
204
+ placementAttempts.push({ method: "track." + methodName + "(item, TimeObject)", success: false, error: e10a.toString() });
205
+ }
206
+ } else {
207
+ placementAttempts.push({ method: "track." + methodName, success: false, error: "not a function on this build" });
208
+ }
209
+
210
+ // Fallback: sequence-level call — known on this build to ignore its
211
+ // video-track index (clip lands on a build-chosen track).
212
+ if (placedVia === null) {
213
+ try {
214
+ if (args.mode === "insert") {
215
+ seq.insertClip(item, startTicks, vIdx, aIdx);
216
+ } else {
217
+ seq.overwriteClip(item, startTicks, vIdx, aIdx);
218
+ }
219
+ placementAttempts.push({ method: "seq." + methodName + "(item, ticks, vIdx, aIdx)", success: true });
220
+ placedVia = "seq." + methodName;
221
+ } catch (e10) {
222
+ return JSON.stringify({
223
+ ok: false,
224
+ error: "both track-level and sequence-level " + methodName + "() failed — see attempts",
225
+ attempts: placementAttempts
226
+ });
227
+ }
228
+ }
229
+
230
+ var trackClipCountAfter = null;
231
+ try { trackClipCountAfter = targetTrack.clips.numItems; } catch (e11) { trackClipCountAfter = null; }
232
+
233
+ // Locate the newly-placed clip by matching projectItem + requested
234
+ // start time — scanning ALL tracks of the type, not just the
235
+ // requested one: live-tested 2026-07-17, seq.overwriteClip() IGNORES
236
+ // its vIdx argument on this Premiere 2026 build (clips landed on V1
237
+ // regardless of vIdx 0 or 1, targeting on or off), so where the clip
238
+ // actually went must be discovered, never assumed.
239
+ var toleranceSeconds = 0.1;
240
+ function ppbAddToTimeline_locate() {
241
+ try {
242
+ for (var t2 = 0; t2 < trackCollection.numTracks; t2++) {
243
+ var scanTrack = trackCollection[t2];
244
+ for (var c2 = 0; c2 < scanTrack.clips.numItems; c2++) {
245
+ var candidate = scanTrack.clips[c2];
246
+ var candNodeId = null;
247
+ try { candNodeId = candidate.projectItem.nodeId; } catch (e12) { candNodeId = null; }
248
+ if (candNodeId !== itemNodeId) {
249
+ continue;
250
+ }
251
+ var candStart = null;
252
+ try { candStart = timeValueToSeconds(candidate.start); } catch (e13) { candStart = null; }
253
+ if (candStart !== null && Math.abs(candStart - args.startSeconds) <= toleranceSeconds) {
254
+ return serializeTrackItem(candidate, t2, c2);
255
+ }
256
+ }
257
+ }
258
+ } catch (e14) {
259
+ // fall through
260
+ }
261
+ return null;
262
+ }
263
+
264
+ var placedClip = ppbAddToTimeline_locate();
265
+
266
+ // The track-object path honors the track; the sequence-level
267
+ // fallback doesn't (build bug) — either way, report the ACTUAL track
268
+ // the clip landed on and flag whether the request was honored.
269
+ var trackHonored = placedClip !== null && placedClip.trackIndex === args.trackIndex;
270
+
271
+ var linkedAudioCleanup = { performed: false, removedCount: 0, removed: [] };
272
+ if (args.trackType === "video") {
273
+ var removedList = ppbAddToTimeline_cleanupLinkedAudio(seq, itemNodeId, args.startSeconds, toleranceSeconds);
274
+ linkedAudioCleanup = { performed: true, removedCount: removedList.length, removed: removedList };
275
+ }
276
+
277
+ return JSON.stringify({
278
+ ok: true,
279
+ result: {
280
+ sequenceName: seq.name,
281
+ added: true,
282
+ mode: args.mode,
283
+ placedVia: placedVia,
284
+ placementAttempts: placementAttempts,
285
+ trackType: args.trackType,
286
+ requestedTrackIndex: args.trackIndex,
287
+ actualTrackIndex: placedClip !== null ? placedClip.trackIndex : null,
288
+ trackHonored: trackHonored,
289
+ startSeconds: args.startSeconds,
290
+ item: { name: (function () { try { return item.name; } catch (e) { return null; } })(), nodeId: itemNodeId },
291
+ placedClip: placedClip,
292
+ trackClipCountBefore: trackClipCountBefore,
293
+ trackClipCountAfter: trackClipCountAfter,
294
+ linkedAudioCleanup: linkedAudioCleanup
295
+ }
296
+ });
297
+ } catch (e) {
298
+ return JSON.stringify({ ok: false, error: e.toString() });
299
+ }
300
+ }
@@ -0,0 +1,188 @@
1
+ // Command: add-track → ppb_addTrack
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — shared helpers (ensureQEEnabled,
4
+ // findSequenceByName, ...) are already defined there.
5
+ //
6
+ // Merges leancoderkavy's premiere-pro-mcp `add_track` (tracks.ts, standard
7
+ // DOM insertVideoTrackAt/insertAudioTrackAt) and `add_tracks` (advanced.ts,
8
+ // QE addTracks) into one command — the reference project split these into
9
+ // two near-duplicate tools (single-track-type standard-DOM vs. multi-type
10
+ // QE); here `trackType` picks video-or-audio and `count` picks how many.
11
+ //
12
+ // hetpatel's note in PREMIERE_API_NOTES.md warns that a bulk QE addTracks()
13
+ // call can WEDGE the CEP bridge — so even when the QE fallback path is
14
+ // used, this issues exactly one underlying add call per requested track,
15
+ // in a loop, never a single call with count > 1.
16
+ function ppb_addTrack(argsJson) {
17
+ try {
18
+ var args;
19
+ try {
20
+ args = JSON.parse(argsJson);
21
+ } catch (e) {
22
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
23
+ }
24
+
25
+ if (args.trackType !== "video" && args.trackType !== "audio") {
26
+ return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
27
+ }
28
+
29
+ var count = 1;
30
+ if (args.count !== undefined && args.count !== null) {
31
+ if (typeof args.count !== "number" || Math.floor(args.count) !== args.count || args.count < 1) {
32
+ return JSON.stringify({ ok: false, error: "count must be a positive integer" });
33
+ }
34
+ count = args.count;
35
+ }
36
+ if (count > 8) {
37
+ count = 8; // capped — see task spec; guards against a runaway bulk-insert loop
38
+ }
39
+
40
+ if (!app.project) {
41
+ return JSON.stringify({ ok: false, error: "no project open" });
42
+ }
43
+
44
+ var seq = null;
45
+ if (args.sequenceName && typeof args.sequenceName === "string") {
46
+ seq = findSequenceByName(args.sequenceName);
47
+ if (!seq) {
48
+ return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
49
+ }
50
+ } else {
51
+ seq = app.project.activeSequence;
52
+ if (!seq) {
53
+ return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
54
+ }
55
+ }
56
+
57
+ function getTrackCollection() {
58
+ return args.trackType === "video" ? seq.videoTracks : seq.audioTracks;
59
+ }
60
+
61
+ var index = args.index;
62
+ var hasIndex = typeof index === "number" && Math.floor(index) === index && index >= 0;
63
+
64
+ var attemptsLog = [];
65
+ var addedCount = 0;
66
+ var startingCount = getTrackCollection().numTracks;
67
+
68
+ for (var i = 0; i < count; i++) {
69
+ var before = getTrackCollection().numTracks;
70
+ var insertAt = hasIndex ? index : before; // default: append at the end
71
+ var iterationAttempts = [];
72
+ var succeeded = false;
73
+
74
+ // --- Attempt 1: standard-DOM insertVideoTrackAt/insertAudioTrackAt [leancoderkavy] ---
75
+ try {
76
+ if (args.trackType === "video") {
77
+ seq.insertVideoTrackAt(insertAt, 1);
78
+ } else {
79
+ seq.insertAudioTrackAt(insertAt, 1);
80
+ }
81
+ iterationAttempts.push({ form: "insertTrackAt", success: true });
82
+ succeeded = getTrackCollection().numTracks > before;
83
+ } catch (e) {
84
+ iterationAttempts.push({ form: "insertTrackAt", success: false, error: e.toString() });
85
+ }
86
+
87
+ // --- Attempt 2: seq.addTrack(type[, channelType]) [ayushozha] ---
88
+ if (!succeeded) {
89
+ try {
90
+ if (args.trackType === "video") {
91
+ seq.addTrack("video");
92
+ } else {
93
+ seq.addTrack("audio", 1 /* stereo */);
94
+ }
95
+ iterationAttempts.push({ form: "addTrack", success: true });
96
+ succeeded = getTrackCollection().numTracks > before;
97
+ } catch (e) {
98
+ iterationAttempts.push({ form: "addTrack", success: false, error: e.toString() });
99
+ }
100
+ }
101
+
102
+ // --- Attempt 3: QE addTracks(...), one track per call (never bulk) ---
103
+ if (!succeeded) {
104
+ try {
105
+ ensureQEEnabled();
106
+ if (app.project.activeSequence !== seq) {
107
+ app.project.activeSequence = seq;
108
+ }
109
+ var qeSeq = qe.project.getActiveSequence();
110
+ if (!qeSeq) {
111
+ throw new Error("qe.project.getActiveSequence() returned nothing");
112
+ }
113
+ if (args.trackType === "video") {
114
+ // hetpatel 7-arg form: (videoCount, videoInsertIndex, audioCount, audioInsertIndex, audioMediaType, submixCount, submixInsertIndex)
115
+ qeSeq.addTracks(1, insertAt, 0, 0, 1, 0, 0);
116
+ } else {
117
+ // hetpatel 7-arg form, audio side
118
+ qeSeq.addTracks(0, 0, 1, insertAt, 1, 0, 0);
119
+ }
120
+ iterationAttempts.push({ form: "qeAddTracks7Arg", success: true });
121
+ succeeded = getTrackCollection().numTracks > before;
122
+ } catch (e) {
123
+ iterationAttempts.push({ form: "qeAddTracks7Arg", success: false, error: e.toString() });
124
+ }
125
+ }
126
+
127
+ // --- Attempt 4: QE addTracks(...) leancoderkavy's 4-arg form, one track per call ---
128
+ if (!succeeded) {
129
+ try {
130
+ ensureQEEnabled();
131
+ if (app.project.activeSequence !== seq) {
132
+ app.project.activeSequence = seq;
133
+ }
134
+ var qeSeq2 = qe.project.getActiveSequence();
135
+ if (!qeSeq2) {
136
+ throw new Error("qe.project.getActiveSequence() returned nothing");
137
+ }
138
+ if (args.trackType === "video") {
139
+ qeSeq2.addTracks(1, 0, 0, 0);
140
+ } else {
141
+ qeSeq2.addTracks(0, 1, 0, 0);
142
+ }
143
+ iterationAttempts.push({ form: "qeAddTracks4Arg", success: true });
144
+ succeeded = getTrackCollection().numTracks > before;
145
+ } catch (e) {
146
+ iterationAttempts.push({ form: "qeAddTracks4Arg", success: false, error: e.toString() });
147
+ }
148
+ }
149
+
150
+ attemptsLog.push({ trackNumber: i + 1, attempts: iterationAttempts, succeeded: succeeded });
151
+
152
+ if (succeeded) {
153
+ addedCount++;
154
+ } else {
155
+ // Stop retrying further tracks once one iteration fails outright —
156
+ // no known form worked, so more attempts at the same op would just
157
+ // repeat the same failures.
158
+ break;
159
+ }
160
+ }
161
+
162
+ var finalCount = getTrackCollection().numTracks;
163
+ var result = {
164
+ sequenceName: seq.name,
165
+ trackType: args.trackType,
166
+ requestedCount: count,
167
+ added: addedCount,
168
+ startingTrackCount: startingCount,
169
+ totalTracks: finalCount,
170
+ attempts: attemptsLog
171
+ };
172
+
173
+ if (addedCount === 0) {
174
+ return JSON.stringify({
175
+ ok: false,
176
+ error: "could not add any " + args.trackType + " track with any known form (insertTrackAt, addTrack, QE addTracks 7-arg, QE addTracks 4-arg)",
177
+ attempts: attemptsLog
178
+ });
179
+ }
180
+ if (addedCount < count) {
181
+ result.warning = "only added " + addedCount + " of " + count + " requested tracks before a failure";
182
+ }
183
+
184
+ return JSON.stringify({ ok: true, result: result });
185
+ } catch (e) {
186
+ return JSON.stringify({ ok: false, error: e.toString() });
187
+ }
188
+ }