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,140 @@
1
+ // Command: duplicate-clip → ppb_duplicateClip
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — shared helpers (findSequenceByName,
4
+ // resolveTimelineClip, serializeTrackItem, secondsToTicksString,
5
+ // timeValueToSeconds, ...) are already defined there.
6
+ //
7
+ // Inserts a NEW instance of the addressed clip's own projectItem onto
8
+ // the SAME track, via the standard-DOM seq.insertClip() (ripple) —
9
+ // PREMIERE_API_NOTES.md's "Clips / TrackItems" insert form, same as
10
+ // add-to-timeline. Ported from leancoderkavy's premiere-pro-mcp
11
+ // duplicate_clip tool, adapted: the reference places the duplicate on
12
+ // trackIndex+1 (a DIFFERENT track) with no position argument; this
13
+ // command instead keeps it on the SAME track (no second track is implied
14
+ // by this panel's clip-addressing convention) and accepts an explicit
15
+ // targetStartSeconds, defaulting to right after the original clip's own
16
+ // end (clip.endSeconds) so it never collides with the original — insert
17
+ // ripples, so there's no destructive overwrite risk either way.
18
+ //
19
+ // MUTATION RULE: verified via the track's clips.numItems increasing by
20
+ // exactly one, plus a best-effort lookup of the newly-inserted clip by
21
+ // matching projectItem + requested start time (serialized the same way
22
+ // as get-full-clip-info).
23
+
24
+ function ppb_duplicateClip(argsJson) {
25
+ try {
26
+ var args;
27
+ try {
28
+ args = JSON.parse(argsJson);
29
+ } catch (e) {
30
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
31
+ }
32
+
33
+ if (args.trackType !== "video" && args.trackType !== "audio") {
34
+ return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
35
+ }
36
+ if (typeof args.trackIndex !== "number" || typeof args.clipIndex !== "number") {
37
+ return JSON.stringify({ ok: false, error: "trackIndex and clipIndex are required" });
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
+ var resolved = resolveTimelineClip(seq, args.trackType, args.trackIndex, args.clipIndex);
58
+ if (resolved.error) {
59
+ return JSON.stringify({ ok: false, error: resolved.error });
60
+ }
61
+ var clip = resolved.clip;
62
+
63
+ var projectItem = null;
64
+ try { projectItem = clip.projectItem; } catch (e2) { projectItem = null; }
65
+ if (!projectItem) {
66
+ return JSON.stringify({ ok: false, error: "could not read the source projectItem for this clip" });
67
+ }
68
+ var itemNodeId = null;
69
+ try { itemNodeId = projectItem.nodeId; } catch (e3) { itemNodeId = null; }
70
+
71
+ var originalBefore = serializeTrackItem(clip, args.trackIndex, args.clipIndex);
72
+
73
+ var targetStartSeconds;
74
+ if (typeof args.targetStartSeconds === "number") {
75
+ targetStartSeconds = args.targetStartSeconds;
76
+ } else if (originalBefore.endSeconds !== null) {
77
+ targetStartSeconds = originalBefore.endSeconds;
78
+ } else {
79
+ return JSON.stringify({ ok: false, error: "targetStartSeconds was not given and the original clip's endSeconds could not be read to default it" });
80
+ }
81
+
82
+ var trackCollection = args.trackType === "video" ? seq.videoTracks : seq.audioTracks;
83
+ var track = trackCollection[args.trackIndex];
84
+ var clipCountBefore = null;
85
+ try { clipCountBefore = track.clips.numItems; } catch (e4) { clipCountBefore = null; }
86
+
87
+ var vIdx = args.trackType === "video" ? args.trackIndex : -1;
88
+ var aIdx = args.trackType === "audio" ? args.trackIndex : -1;
89
+ var startTicks = secondsToTicksString(targetStartSeconds);
90
+
91
+ try {
92
+ seq.insertClip(projectItem, startTicks, vIdx, aIdx);
93
+ } catch (e5) {
94
+ return JSON.stringify({ ok: false, error: "seq.insertClip() failed: " + e5.toString() });
95
+ }
96
+
97
+ var clipCountAfter = null;
98
+ try { clipCountAfter = track.clips.numItems; } catch (e6) { clipCountAfter = null; }
99
+ var verified = clipCountBefore !== null && clipCountAfter !== null && clipCountAfter === clipCountBefore + 1;
100
+
101
+ var newClip = null;
102
+ var toleranceSeconds = 0.1;
103
+ try {
104
+ for (var c = 0; c < track.clips.numItems; c++) {
105
+ var candidate = track.clips[c];
106
+ var candNodeId = null;
107
+ try { candNodeId = candidate.projectItem.nodeId; } catch (e7) { candNodeId = null; }
108
+ if (candNodeId !== itemNodeId) {
109
+ continue;
110
+ }
111
+ var candStart = null;
112
+ try { candStart = timeValueToSeconds(candidate.start); } catch (e8) { candStart = null; }
113
+ if (candStart !== null && Math.abs(candStart - targetStartSeconds) <= toleranceSeconds) {
114
+ newClip = serializeTrackItem(candidate, args.trackIndex, c);
115
+ break;
116
+ }
117
+ }
118
+ } catch (e9) {
119
+ newClip = null;
120
+ }
121
+
122
+ return JSON.stringify({
123
+ ok: true,
124
+ result: {
125
+ sequenceName: seq.name,
126
+ trackType: args.trackType,
127
+ trackIndex: args.trackIndex,
128
+ sourceClipIndex: args.clipIndex,
129
+ targetStartSeconds: targetStartSeconds,
130
+ originalClip: originalBefore,
131
+ newClip: newClip,
132
+ clipCountBefore: clipCountBefore,
133
+ clipCountAfter: clipCountAfter,
134
+ verified: verified
135
+ }
136
+ });
137
+ } catch (e) {
138
+ return JSON.stringify({ ok: false, error: e.toString() });
139
+ }
140
+ }
@@ -0,0 +1,150 @@
1
+ // Command: duplicate-sequence → ppb_duplicateSequence
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
+ // Ported from leancoderkavy/premiere-pro-mcp's sequence.ts duplicate_sequence
7
+ // tool. Duplicates a sequence via `seq.clone()` per PREMIERE_API_NOTES.md's
8
+ // Sequences table. clone() gives the copy a Premiere-generated default name
9
+ // (there is no confirmed API to pass a name directly to it) — this command
10
+ // renames the resulting sequence (and its Project-panel item, per the
11
+ // "renaming gotcha" documented alongside seq.clone() in
12
+ // PREMIERE_API_NOTES.md — seq.name = x does NOT propagate to the panel)
13
+ // afterward, same pattern as nest-clips.jsx.
14
+ //
15
+ // Verification: the sequence count increases by exactly one, and the new
16
+ // sequence is identified as whichever sequence appeared that wasn't in the
17
+ // "before" snapshot (clone()'s own return value is not trusted, matching
18
+ // every other QE/structural command in this panel).
19
+ function ppbDupSeq_snapshotIds(project) {
20
+ var ids = {};
21
+ for (var i = 0; i < project.sequences.numSequences; i++) {
22
+ var s = project.sequences[i];
23
+ var id = null;
24
+ try { id = s.sequenceID; } catch (e) { id = null; }
25
+ ids[id !== null ? id : ("idx" + i)] = true;
26
+ }
27
+ return ids;
28
+ }
29
+
30
+ function ppb_duplicateSequence(argsJson) {
31
+ try {
32
+ var args;
33
+ try {
34
+ args = JSON.parse(argsJson);
35
+ } catch (e) {
36
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
37
+ }
38
+
39
+ if (!app.project) {
40
+ return JSON.stringify({ ok: false, error: "no project open" });
41
+ }
42
+ if (!args.newName || typeof args.newName !== "string") {
43
+ return JSON.stringify({ ok: false, error: "newName is required" });
44
+ }
45
+
46
+ var seq;
47
+ if (args.sequenceName && typeof args.sequenceName === "string") {
48
+ seq = findSequenceByName(args.sequenceName);
49
+ if (!seq) {
50
+ return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
51
+ }
52
+ } else {
53
+ seq = app.project.activeSequence;
54
+ if (!seq) {
55
+ return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
56
+ }
57
+ }
58
+
59
+ var numSequencesBefore = app.project.sequences.numSequences;
60
+ var idsBefore = ppbDupSeq_snapshotIds(app.project);
61
+
62
+ var cloneError = null;
63
+ try {
64
+ seq.clone();
65
+ } catch (e) {
66
+ cloneError = e.toString();
67
+ }
68
+
69
+ var numSequencesAfter = app.project.sequences.numSequences;
70
+
71
+ if (cloneError !== null || numSequencesAfter <= numSequencesBefore) {
72
+ return JSON.stringify({
73
+ ok: false,
74
+ error: cloneError !== null
75
+ ? ("seq.clone() failed: " + cloneError)
76
+ : "clone() did not throw, but the project's sequence count did not increase",
77
+ numSequencesBefore: numSequencesBefore,
78
+ numSequencesAfter: numSequencesAfter
79
+ });
80
+ }
81
+
82
+ var newSeq = null;
83
+ for (var i = 0; i < app.project.sequences.numSequences; i++) {
84
+ var candidate = app.project.sequences[i];
85
+ var candidateId = null;
86
+ try { candidateId = candidate.sequenceID; } catch (e) { candidateId = null; }
87
+ var key = candidateId !== null ? candidateId : ("idx" + i);
88
+ if (!idsBefore[key]) {
89
+ newSeq = candidate;
90
+ break;
91
+ }
92
+ }
93
+
94
+ if (!newSeq) {
95
+ return JSON.stringify({
96
+ ok: false,
97
+ error: "sequence count increased but the cloned sequence could not be identified",
98
+ numSequencesBefore: numSequencesBefore,
99
+ numSequencesAfter: numSequencesAfter
100
+ });
101
+ }
102
+
103
+ var previousName = null;
104
+ try { previousName = newSeq.name; } catch (e) { previousName = null; }
105
+
106
+ var renameNote = null;
107
+ try {
108
+ newSeq.name = args.newName;
109
+ } catch (e) {
110
+ renameNote = "renaming the sequence object failed: " + e.toString();
111
+ }
112
+ // "renaming gotcha" per PREMIERE_API_NOTES.md: seq.name = x does not
113
+ // propagate to the Project panel item — find and rename it too.
114
+ try {
115
+ var rootChildren = app.project.rootItem.children;
116
+ for (var ri = 0; ri < rootChildren.numItems; ri++) {
117
+ var it = rootChildren[ri];
118
+ var itSeq = null;
119
+ try { itSeq = it.getSequence ? it.getSequence() : null; } catch (e2) { itSeq = null; }
120
+ if (itSeq && itSeq.sequenceID === newSeq.sequenceID) {
121
+ it.name = args.newName;
122
+ break;
123
+ }
124
+ }
125
+ } catch (e3) {
126
+ // best-effort — panel-item rename is a bonus, not required for success
127
+ }
128
+
129
+ var readBackName = null;
130
+ try { readBackName = newSeq.name; } catch (e4) { readBackName = null; }
131
+ var renamed = readBackName === args.newName;
132
+
133
+ return JSON.stringify({
134
+ ok: true,
135
+ result: {
136
+ sourceSequenceName: seq.name,
137
+ numSequencesBefore: numSequencesBefore,
138
+ numSequencesAfter: numSequencesAfter,
139
+ previousDefaultName: previousName,
140
+ newSequenceName: newSeq.name,
141
+ newSequenceID: newSeq.sequenceID,
142
+ requestedName: args.newName,
143
+ renamed: renamed,
144
+ renameNote: renameNote
145
+ }
146
+ });
147
+ } catch (e) {
148
+ return JSON.stringify({ ok: false, error: e.toString() });
149
+ }
150
+ }
@@ -0,0 +1,86 @@
1
+ // Command: encode-file → ppb_encodeFile
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context.
4
+ //
5
+ // Queues an EXTERNAL file (not a project item, not a sequence — a path on
6
+ // disk not necessarily imported into this project at all) for export in
7
+ // Adobe Media Encoder via app.encoder.launchEncoder() + encodeFile() +
8
+ // startBatch(), mirroring the reference tool this ports (leancoderkavy's
9
+ // premiere-pro-mcp encode_file). **Fire-and-forget** — same no-progress-API
10
+ // caveat as add-to-render-queue/encode-project-item: encodeFile() returns
11
+ // as soon as the job is queued, so this command cannot verify the output
12
+ // file exists.
13
+
14
+ function ppb_encodeFile(argsJson) {
15
+ try {
16
+ var args;
17
+ try {
18
+ args = JSON.parse(argsJson);
19
+ } catch (e) {
20
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
21
+ }
22
+
23
+ if (!args.inputPath || typeof args.inputPath !== "string") {
24
+ return JSON.stringify({ ok: false, error: "inputPath is required" });
25
+ }
26
+ if (!args.outputPath || typeof args.outputPath !== "string") {
27
+ return JSON.stringify({ ok: false, error: "outputPath is required" });
28
+ }
29
+ if (!args.presetPath || typeof args.presetPath !== "string") {
30
+ return JSON.stringify({ ok: false, error: "presetPath is required (an absolute .epr file path)" });
31
+ }
32
+
33
+ var inputFile = new File(args.inputPath);
34
+ if (!inputFile.exists) {
35
+ return JSON.stringify({ ok: false, error: "input file not found: " + args.inputPath });
36
+ }
37
+ var presetFile = new File(args.presetPath);
38
+ if (!presetFile.exists) {
39
+ return JSON.stringify({ ok: false, error: "preset file not found: " + args.presetPath });
40
+ }
41
+
42
+ var startBatch = args.startBatch === true;
43
+
44
+ if (!app.encoder) {
45
+ return JSON.stringify({ ok: false, error: "Adobe Media Encoder is not available (app.encoder is undefined)" });
46
+ }
47
+
48
+ try {
49
+ app.encoder.launchEncoder();
50
+ } catch (e) {
51
+ return JSON.stringify({ ok: false, error: "app.encoder.launchEncoder() failed: " + e.toString() });
52
+ }
53
+
54
+ try {
55
+ // Matches the reference tool's own call shape: encodeFile(input,
56
+ // output, preset, removeOnCompletion01, srcIn, srcOut) — srcIn/srcOut
57
+ // are left undefined here (this command takes no in/out-point args
58
+ // per spec), encoding the entire input file.
59
+ app.encoder.encodeFile(args.inputPath, args.outputPath, args.presetPath, 1 /* removeOnCompletion */);
60
+ } catch (e) {
61
+ return JSON.stringify({ ok: false, error: "app.encoder.encodeFile() failed: " + e.toString() });
62
+ }
63
+
64
+ if (startBatch) {
65
+ try {
66
+ app.encoder.startBatch();
67
+ } catch (e) {
68
+ return JSON.stringify({ ok: false, error: "job was queued but app.encoder.startBatch() failed: " + e.toString() });
69
+ }
70
+ }
71
+
72
+ return JSON.stringify({
73
+ ok: true,
74
+ result: {
75
+ inputPath: args.inputPath,
76
+ outputPath: args.outputPath,
77
+ presetPath: args.presetPath,
78
+ startBatch: startBatch,
79
+ note: "fire-and-forget: the job is queued in Adobe Media Encoder, not exported synchronously — " +
80
+ "there is no progress API, so this result does NOT confirm the output file exists yet."
81
+ }
82
+ });
83
+ } catch (e) {
84
+ return JSON.stringify({ ok: false, error: e.toString() });
85
+ }
86
+ }
@@ -0,0 +1,145 @@
1
+ // Command: encode-project-item → ppb_encodeProjectItem
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context.
4
+ //
5
+ // Queues a PROJECT ITEM (not a sequence) for export in Adobe Media Encoder
6
+ // via app.encoder.launchEncoder() + encodeProjectItem() + startBatch(),
7
+ // mirroring the reference tool this ports (leancoderkavy's
8
+ // premiere-pro-mcp encode_project_item). **Fire-and-forget** — same no-
9
+ // progress-API caveat as add-to-render-queue: encodeProjectItem() returns
10
+ // as soon as the job is queued, so this command cannot verify the output
11
+ // file exists.
12
+
13
+ // Project-item addressing (nodeId or name) — duplicated per command file
14
+ // since each loads independently; same walk as get-item-metadata.jsx's
15
+ // ppbFindItemGetItemMetadata_* helpers, prefixed for this file.
16
+ function ppbFindItemEncodeProjectItem_walk(item, args, depth) {
17
+ if (depth > 32) {
18
+ return null;
19
+ }
20
+ var isBin = false;
21
+ try {
22
+ isBin = typeof ProjectItemType !== "undefined" && item.type === ProjectItemType.BIN;
23
+ } catch (e) {
24
+ isBin = false;
25
+ }
26
+ var matched = false;
27
+ if (args.nodeId !== null) {
28
+ try { matched = item.nodeId === args.nodeId; } catch (e) { matched = false; }
29
+ } else if (args.name !== null) {
30
+ try { matched = item.name === args.name; } catch (e) { matched = false; }
31
+ }
32
+ if (matched) {
33
+ return item;
34
+ }
35
+ if (isBin && item.children) {
36
+ for (var i = 0; i < item.children.numItems; i++) {
37
+ var found = ppbFindItemEncodeProjectItem_walk(item.children[i], args, depth + 1);
38
+ if (found) {
39
+ return found;
40
+ }
41
+ }
42
+ }
43
+ return null;
44
+ }
45
+
46
+ function ppbFindItemEncodeProjectItem_resolve(args) {
47
+ var root = app.project.rootItem;
48
+ for (var i = 0; i < root.children.numItems; i++) {
49
+ var found = ppbFindItemEncodeProjectItem_walk(root.children[i], args, 1);
50
+ if (found) {
51
+ return found;
52
+ }
53
+ }
54
+ return null;
55
+ }
56
+
57
+ function ppb_encodeProjectItem(argsJson) {
58
+ try {
59
+ var args;
60
+ try {
61
+ args = JSON.parse(argsJson);
62
+ } catch (e) {
63
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
64
+ }
65
+
66
+ var hasNodeId = typeof args.nodeId === "string" && args.nodeId.length > 0;
67
+ var hasName = typeof args.name === "string" && args.name.length > 0;
68
+ if (!hasNodeId && !hasName) {
69
+ return JSON.stringify({ ok: false, error: "either nodeId or name is required to address the project item" });
70
+ }
71
+ if (!args.outputPath || typeof args.outputPath !== "string") {
72
+ return JSON.stringify({ ok: false, error: "outputPath is required" });
73
+ }
74
+ if (!args.presetPath || typeof args.presetPath !== "string") {
75
+ return JSON.stringify({ ok: false, error: "presetPath is required (an absolute .epr file path)" });
76
+ }
77
+
78
+ if (!app.project) {
79
+ return JSON.stringify({ ok: false, error: "no project open" });
80
+ }
81
+
82
+ var item = ppbFindItemEncodeProjectItem_resolve({
83
+ nodeId: hasNodeId ? args.nodeId : null,
84
+ name: hasNodeId ? null : args.name
85
+ });
86
+ if (!item) {
87
+ return JSON.stringify({ ok: false, error: "no project item found matching the given nodeId/name" });
88
+ }
89
+
90
+ var presetFile = new File(args.presetPath);
91
+ if (!presetFile.exists) {
92
+ return JSON.stringify({ ok: false, error: "preset file not found: " + args.presetPath });
93
+ }
94
+
95
+ var startBatch = args.startBatch === true;
96
+
97
+ if (!app.encoder) {
98
+ return JSON.stringify({ ok: false, error: "Adobe Media Encoder is not available (app.encoder is undefined)" });
99
+ }
100
+
101
+ try {
102
+ app.encoder.launchEncoder();
103
+ } catch (e) {
104
+ return JSON.stringify({ ok: false, error: "app.encoder.launchEncoder() failed: " + e.toString() });
105
+ }
106
+
107
+ var itemName = null;
108
+ try { itemName = item.name; } catch (e) { itemName = null; }
109
+
110
+ try {
111
+ app.encoder.encodeProjectItem(
112
+ item,
113
+ args.outputPath,
114
+ args.presetPath,
115
+ typeof app.encoder.ENCODE_IN_TO_OUT !== "undefined" ? app.encoder.ENCODE_IN_TO_OUT : 1,
116
+ 1 /* removeOnCompletion */
117
+ );
118
+ } catch (e) {
119
+ return JSON.stringify({ ok: false, error: "app.encoder.encodeProjectItem() failed: " + e.toString() });
120
+ }
121
+
122
+ if (startBatch) {
123
+ try {
124
+ app.encoder.startBatch();
125
+ } catch (e) {
126
+ return JSON.stringify({ ok: false, error: "job was queued but app.encoder.startBatch() failed: " + e.toString() });
127
+ }
128
+ }
129
+
130
+ return JSON.stringify({
131
+ ok: true,
132
+ result: {
133
+ item: itemName,
134
+ nodeId: hasNodeId ? args.nodeId : (item.nodeId || null),
135
+ outputPath: args.outputPath,
136
+ presetPath: args.presetPath,
137
+ startBatch: startBatch,
138
+ note: "fire-and-forget: the job is queued in Adobe Media Encoder, not exported synchronously — " +
139
+ "there is no progress API, so this result does NOT confirm the output file exists yet."
140
+ }
141
+ });
142
+ } catch (e) {
143
+ return JSON.stringify({ ok: false, error: e.toString() });
144
+ }
145
+ }
@@ -0,0 +1,77 @@
1
+ // Command: export-aaf → ppb_exportAaf
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
+ // Exports the given (or active) sequence as an AAF file via
7
+ // seq.exportAsAAF(path, mixdown01, mono01, rate, bits)
8
+ // (PREMIERE_API_NOTES.md's "FCP XML / AAF / OMF / EDL" line) — synchronous,
9
+ // no AME dependency. Defaults mirror the reference tool this ports
10
+ // (leancoderkavy's premiere-pro-mcp export_aaf): mixdown=true,
11
+ // explodeToMono=false, sampleRate=48000, bitsPerSample=16.
12
+
13
+ function ppb_exportAaf(argsJson) {
14
+ try {
15
+ var args;
16
+ try {
17
+ args = JSON.parse(argsJson);
18
+ } catch (e) {
19
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
20
+ }
21
+
22
+ if (!args.outputPath || typeof args.outputPath !== "string") {
23
+ return JSON.stringify({ ok: false, error: "outputPath is required" });
24
+ }
25
+
26
+ if (!app.project) {
27
+ return JSON.stringify({ ok: false, error: "no project open" });
28
+ }
29
+
30
+ var seq = null;
31
+ if (args.sequenceName && typeof args.sequenceName === "string") {
32
+ seq = findSequenceByName(args.sequenceName);
33
+ if (!seq) {
34
+ return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
35
+ }
36
+ } else {
37
+ seq = app.project.activeSequence;
38
+ if (!seq) {
39
+ return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
40
+ }
41
+ }
42
+
43
+ var mixdown = args.mixdown !== false; // default true
44
+ var mono = args.mono === true; // default false
45
+ var rate = typeof args.rate === "number" ? args.rate : 48000;
46
+ var bits = typeof args.bits === "number" ? args.bits : 16;
47
+
48
+ var result = {
49
+ sequenceName: seq.name,
50
+ outputPath: args.outputPath,
51
+ mixdown: mixdown,
52
+ mono: mono,
53
+ rate: rate,
54
+ bits: bits
55
+ };
56
+
57
+ try {
58
+ seq.exportAsAAF(args.outputPath, mixdown ? 1 : 0, mono ? 1 : 0, rate, bits);
59
+ } catch (e) {
60
+ return JSON.stringify({ ok: false, error: "exportAsAAF failed: " + e.toString() });
61
+ }
62
+
63
+ var outFile = new File(args.outputPath);
64
+ if (!outFile.exists) {
65
+ return JSON.stringify({
66
+ ok: false,
67
+ error: "exportAsAAF ran but no file was written to " + args.outputPath
68
+ });
69
+ }
70
+
71
+ result.fileSizeBytes = outFile.length;
72
+
73
+ return JSON.stringify({ ok: true, result: result });
74
+ } catch (e) {
75
+ return JSON.stringify({ ok: false, error: e.toString() });
76
+ }
77
+ }
@@ -0,0 +1,65 @@
1
+ // Command: export-fcp-xml → ppb_exportFcpXml
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
+ // Exports the given (or active) sequence as a Final Cut Pro XML file via
7
+ // seq.exportAsFinalCutProXML(path) (PREMIERE_API_NOTES.md's "FCP XML / AAF
8
+ // / OMF / EDL" line) — synchronous, no AME dependency.
9
+
10
+ function ppb_exportFcpXml(argsJson) {
11
+ try {
12
+ var args;
13
+ try {
14
+ args = JSON.parse(argsJson);
15
+ } catch (e) {
16
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
17
+ }
18
+
19
+ if (!args.outputPath || typeof args.outputPath !== "string") {
20
+ return JSON.stringify({ ok: false, error: "outputPath is required" });
21
+ }
22
+
23
+ if (!app.project) {
24
+ return JSON.stringify({ ok: false, error: "no project open" });
25
+ }
26
+
27
+ var seq = null;
28
+ if (args.sequenceName && typeof args.sequenceName === "string") {
29
+ seq = findSequenceByName(args.sequenceName);
30
+ if (!seq) {
31
+ return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
32
+ }
33
+ } else {
34
+ seq = app.project.activeSequence;
35
+ if (!seq) {
36
+ return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
37
+ }
38
+ }
39
+
40
+ var result = {
41
+ sequenceName: seq.name,
42
+ outputPath: args.outputPath
43
+ };
44
+
45
+ try {
46
+ seq.exportAsFinalCutProXML(args.outputPath);
47
+ } catch (e) {
48
+ return JSON.stringify({ ok: false, error: "exportAsFinalCutProXML failed: " + e.toString() });
49
+ }
50
+
51
+ var outFile = new File(args.outputPath);
52
+ if (!outFile.exists) {
53
+ return JSON.stringify({
54
+ ok: false,
55
+ error: "exportAsFinalCutProXML ran but no file was written to " + args.outputPath
56
+ });
57
+ }
58
+
59
+ result.fileSizeBytes = outFile.length;
60
+
61
+ return JSON.stringify({ ok: true, result: result });
62
+ } catch (e) {
63
+ return JSON.stringify({ ok: false, error: e.toString() });
64
+ }
65
+ }