blitzreels 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +25 -0
- package/README.md +73 -5
- package/dist/cli-errors.d.ts.map +1 -1
- package/dist/cli-runtime.d.ts +1 -1
- package/dist/cli-runtime.d.ts.map +1 -1
- package/dist/cli-runtime.js +1 -1
- package/dist/cli-runtime.js.map +1 -1
- package/dist/command-metadata.d.ts.map +1 -1
- package/dist/command-metadata.js +2 -0
- package/dist/command-metadata.js.map +1 -1
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +2 -0
- package/dist/command-registry.js.map +1 -1
- package/dist/commands/auth-runtime.js +1 -1
- package/dist/commands/auth-runtime.js.map +1 -1
- package/dist/commands/bulk-delete-runtime.d.ts +12 -0
- package/dist/commands/bulk-delete-runtime.d.ts.map +1 -0
- package/dist/commands/bulk-delete-runtime.js +21 -0
- package/dist/commands/bulk-delete-runtime.js.map +1 -0
- package/dist/commands/caption-dry-run.d.ts +1 -0
- package/dist/commands/caption-dry-run.d.ts.map +1 -1
- package/dist/commands/caption-dry-run.js +32 -0
- package/dist/commands/caption-dry-run.js.map +1 -1
- package/dist/commands/caption-overrides.d.ts +13 -1
- package/dist/commands/caption-overrides.d.ts.map +1 -1
- package/dist/commands/caption-overrides.js +35 -2
- package/dist/commands/caption-overrides.js.map +1 -1
- package/dist/commands/caption-style-commands.d.ts.map +1 -1
- package/dist/commands/caption-style-commands.js +13 -3
- package/dist/commands/caption-style-commands.js.map +1 -1
- package/dist/commands/captions-specs.d.ts.map +1 -1
- package/dist/commands/captions-specs.js +18 -2
- package/dist/commands/captions-specs.js.map +1 -1
- package/dist/commands/captions.js +32 -0
- package/dist/commands/captions.js.map +1 -1
- package/dist/commands/clips.d.ts +4 -0
- package/dist/commands/clips.d.ts.map +1 -1
- package/dist/commands/clips.js +775 -7
- package/dist/commands/clips.js.map +1 -1
- package/dist/commands/command-operation.d.ts +2 -2
- package/dist/commands/command-operation.d.ts.map +1 -1
- package/dist/commands/command-operation.js +1 -1
- package/dist/commands/command-operation.js.map +1 -1
- package/dist/commands/editing-workflows.d.ts.map +1 -1
- package/dist/commands/editing-workflows.js +24 -6
- package/dist/commands/editing-workflows.js.map +1 -1
- package/dist/commands/faceless.d.ts.map +1 -1
- package/dist/commands/faceless.js +1 -0
- package/dist/commands/faceless.js.map +1 -1
- package/dist/commands/jobs.d.ts.map +1 -1
- package/dist/commands/jobs.js +2 -0
- package/dist/commands/jobs.js.map +1 -1
- package/dist/commands/media-assets.d.ts +5 -7
- package/dist/commands/media-assets.d.ts.map +1 -1
- package/dist/commands/media-assets.js +481 -21
- package/dist/commands/media-assets.js.map +1 -1
- package/dist/commands/media-overlays.d.ts.map +1 -1
- package/dist/commands/media-overlays.js +20 -2
- package/dist/commands/media-overlays.js.map +1 -1
- package/dist/commands/media-runtime.d.ts +4 -7
- package/dist/commands/media-runtime.d.ts.map +1 -1
- package/dist/commands/media-runtime.js +39 -7
- package/dist/commands/media-runtime.js.map +1 -1
- package/dist/commands/project-read.d.ts +30 -0
- package/dist/commands/project-read.d.ts.map +1 -1
- package/dist/commands/project-read.js +183 -6
- package/dist/commands/project-read.js.map +1 -1
- package/dist/commands/projects.d.ts.map +1 -1
- package/dist/commands/projects.js +125 -2
- package/dist/commands/projects.js.map +1 -1
- package/dist/commands/recording-sets.d.ts +44 -0
- package/dist/commands/recording-sets.d.ts.map +1 -0
- package/dist/commands/recording-sets.js +385 -0
- package/dist/commands/recording-sets.js.map +1 -0
- package/dist/commands/system.js +1 -1
- package/dist/commands/system.js.map +1 -1
- package/dist/commands/text-overlay-spec.js +62 -2
- package/dist/commands/text-overlay-spec.js.map +1 -1
- package/dist/commands/timeline-runtime.d.ts +30 -0
- package/dist/commands/timeline-runtime.d.ts.map +1 -1
- package/dist/commands/timeline-runtime.js +181 -42
- package/dist/commands/timeline-runtime.js.map +1 -1
- package/dist/commands/timeline.d.ts.map +1 -1
- package/dist/commands/timeline.js +158 -3
- package/dist/commands/timeline.js.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/preview-first-edit.d.ts.map +1 -1
- package/dist/update-notifier.d.ts.map +1 -1
- package/dist/update-notifier.js +7 -3
- package/dist/update-notifier.js.map +1 -1
- package/package.json +6 -3
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
import { CliUsageError } from "../cli-errors.js";
|
|
1
2
|
import { commandSpec } from "../command-metadata.js";
|
|
2
3
|
import { requireDeleteConfirmation, } from "../preview-first-edit.js";
|
|
4
|
+
import { assertBulkDeleteSucceeded, requireExactlyOneDeleteSelector, } from "./bulk-delete-runtime.js";
|
|
3
5
|
export const MEDIA_ASSET_COMMAND_SPECS = [
|
|
4
6
|
commandSpec({
|
|
5
7
|
command: ["media", "list"],
|
|
6
|
-
usage: "blitzreels media list [--folder-id ID] [--asset-type video|audio|image|document] [--search QUERY] [--limit 100] [--offset 0] [--json]",
|
|
7
|
-
flags: [
|
|
8
|
+
usage: "blitzreels media list [--folder-id ID] [--asset-type video|audio|image|document] [--search QUERY] [--min-duration 1] [--orientation landscape|portrait|square] [--limit 100] [--offset 0] [--json]",
|
|
9
|
+
flags: [
|
|
10
|
+
"folder-id",
|
|
11
|
+
"asset-type",
|
|
12
|
+
"search",
|
|
13
|
+
"min-duration",
|
|
14
|
+
"orientation",
|
|
15
|
+
"limit",
|
|
16
|
+
"offset",
|
|
17
|
+
],
|
|
8
18
|
}),
|
|
9
19
|
commandSpec({
|
|
10
20
|
command: ["media", "get"],
|
|
@@ -13,8 +23,18 @@ export const MEDIA_ASSET_COMMAND_SPECS = [
|
|
|
13
23
|
}),
|
|
14
24
|
commandSpec({
|
|
15
25
|
command: ["media", "delete"],
|
|
16
|
-
usage: "blitzreels media delete --asset-id ID --confirm-delete",
|
|
17
|
-
flags: [
|
|
26
|
+
usage: "blitzreels media delete (--asset-id ID|--asset-ids ID1,ID2|--search QUERY|--name-prefix PREFIX) --confirm-delete --reason TEXT --idempotency-key KEY [--delete-generated-clips true] [--delete-linked-projects true]",
|
|
27
|
+
flags: [
|
|
28
|
+
"asset-id",
|
|
29
|
+
"asset-ids",
|
|
30
|
+
"search",
|
|
31
|
+
"name-prefix",
|
|
32
|
+
"confirm-delete",
|
|
33
|
+
"reason",
|
|
34
|
+
"idempotency-key",
|
|
35
|
+
"delete-generated-clips",
|
|
36
|
+
"delete-linked-projects",
|
|
37
|
+
],
|
|
18
38
|
}),
|
|
19
39
|
commandSpec({
|
|
20
40
|
command: ["media", "upload"],
|
|
@@ -83,11 +103,24 @@ export const MEDIA_ASSET_COMMAND_SPECS = [
|
|
|
83
103
|
}),
|
|
84
104
|
commandSpec({
|
|
85
105
|
command: ["media", "shorts", "generate"],
|
|
86
|
-
usage: "blitzreels media shorts generate --asset-id ID [--content-profile auto|podcast|tutorial|generic] [--auto-trim-silence true]",
|
|
87
|
-
flags: [
|
|
106
|
+
usage: "blitzreels media shorts generate --asset-id ID --idempotency-key KEY [--content-profile auto|podcast|tutorial|generic] [--auto-trim-silence true]",
|
|
107
|
+
flags: [
|
|
108
|
+
"asset-id",
|
|
109
|
+
"idempotency-key",
|
|
110
|
+
"content-profile",
|
|
111
|
+
"auto-trim-silence",
|
|
112
|
+
],
|
|
88
113
|
description: "Start short suggestion generation for a media asset.",
|
|
89
114
|
dryRunSupported: false,
|
|
90
115
|
}),
|
|
116
|
+
commandSpec({
|
|
117
|
+
command: ["media", "shorts", "refresh-thumbnail"],
|
|
118
|
+
usage: "blitzreels media shorts refresh-thumbnail --asset-id ID --suggestion-id ID --idempotency-key KEY [--dry-run] [--json]",
|
|
119
|
+
flags: ["asset-id", "suggestion-id", "idempotency-key"],
|
|
120
|
+
description: "Queue thumbnail regeneration for one short suggestion.",
|
|
121
|
+
mutates: true,
|
|
122
|
+
dryRunSupported: true,
|
|
123
|
+
}),
|
|
91
124
|
commandSpec({
|
|
92
125
|
command: ["media", "shorts", "apply"],
|
|
93
126
|
usage: "blitzreels media shorts apply --asset-id ID --suggestion-id ID --project-id ID [--caption-style-id ID|null] [--mark-saved true] [--automatic-layout-json JSON]",
|
|
@@ -102,6 +135,59 @@ export const MEDIA_ASSET_COMMAND_SPECS = [
|
|
|
102
135
|
description: "Apply a short suggestion to a project timeline.",
|
|
103
136
|
dryRunSupported: false,
|
|
104
137
|
}),
|
|
138
|
+
commandSpec({
|
|
139
|
+
command: ["media", "reframe", "status"],
|
|
140
|
+
usage: "blitzreels media reframe status --asset-id ID [--json]",
|
|
141
|
+
flags: ["asset-id"],
|
|
142
|
+
description: "Inspect automatic layout analysis for a media asset.",
|
|
143
|
+
}),
|
|
144
|
+
commandSpec({
|
|
145
|
+
command: ["media", "reframe", "analyze"],
|
|
146
|
+
usage: "blitzreels media reframe analyze --asset-id ID --idempotency-key KEY [--json]",
|
|
147
|
+
flags: ["asset-id", "idempotency-key"],
|
|
148
|
+
description: "Queue or reuse automatic layout analysis for a media asset.",
|
|
149
|
+
mutates: true,
|
|
150
|
+
dryRunSupported: false,
|
|
151
|
+
}),
|
|
152
|
+
commandSpec({
|
|
153
|
+
command: ["media", "reframe", "apply"],
|
|
154
|
+
usage: "blitzreels media reframe apply --asset-id ID --project-id ID --idempotency-key KEY [--replace-timeline-item-id ID|null] [--trim-start 0 --trim-end 60] [--aspect-ratio 9:16|null] [--content-type-hint auto|podcast|tutorial|generic] [--layout-strategy auto|demo|letterbox|split|focus|speaker_grid|webinar|webinar_stack|gameplay] [--dry-run] [--json]",
|
|
155
|
+
flags: [
|
|
156
|
+
"asset-id",
|
|
157
|
+
"project-id",
|
|
158
|
+
{ name: "trim-start", type: "number" },
|
|
159
|
+
{ name: "trim-end", type: "number" },
|
|
160
|
+
"idempotency-key",
|
|
161
|
+
"replace-timeline-item-id",
|
|
162
|
+
{
|
|
163
|
+
name: "aspect-ratio",
|
|
164
|
+
enum: ["9:16", "16:9", "1:1", "4:5", "null"],
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: "content-type-hint",
|
|
168
|
+
enum: ["auto", "podcast", "tutorial", "generic"],
|
|
169
|
+
default: "auto",
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: "layout-strategy",
|
|
173
|
+
enum: [
|
|
174
|
+
"auto",
|
|
175
|
+
"demo",
|
|
176
|
+
"letterbox",
|
|
177
|
+
"split",
|
|
178
|
+
"focus",
|
|
179
|
+
"speaker_grid",
|
|
180
|
+
"webinar",
|
|
181
|
+
"webinar_stack",
|
|
182
|
+
"gameplay",
|
|
183
|
+
],
|
|
184
|
+
default: "auto",
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
description: "Apply the managed automatic layout plan to a project.",
|
|
188
|
+
mutates: true,
|
|
189
|
+
dryRunSupported: true,
|
|
190
|
+
}),
|
|
105
191
|
commandSpec({
|
|
106
192
|
command: ["media", "folders", "list"],
|
|
107
193
|
usage: "blitzreels media folders list [--parent-folder-id ID] [--json]",
|
|
@@ -133,6 +219,14 @@ export const MEDIA_ASSET_COMMAND_SPECS = [
|
|
|
133
219
|
usage: "blitzreels media folders delete --folder-id ID --confirm-delete [--cascade true]",
|
|
134
220
|
flags: ["folder-id", "confirm-delete", "cascade"],
|
|
135
221
|
}),
|
|
222
|
+
commandSpec({
|
|
223
|
+
command: ["media", "folders", "empty"],
|
|
224
|
+
usage: "blitzreels media folders empty --folder-id ID --confirm-delete --reason TEXT --idempotency-key KEY [--dry-run] [--json]",
|
|
225
|
+
flags: ["folder-id", "confirm-delete", "reason", "idempotency-key"],
|
|
226
|
+
description: "Delete media inside a folder while retaining the folder.",
|
|
227
|
+
mutates: true,
|
|
228
|
+
dryRunSupported: true,
|
|
229
|
+
}),
|
|
136
230
|
];
|
|
137
231
|
export function createMediaAssetCommandOperation({ helpers, }) {
|
|
138
232
|
return {
|
|
@@ -155,6 +249,13 @@ async function handleMediaAssetCommand({ context, helpers, }) {
|
|
|
155
249
|
value: helpers.getStringFlag({ flags, name: "asset-type" }),
|
|
156
250
|
}),
|
|
157
251
|
search: helpers.getStringFlag({ flags, name: "search" }),
|
|
252
|
+
minDurationSeconds: helpers.getNumberFlag({
|
|
253
|
+
flags,
|
|
254
|
+
name: "min-duration",
|
|
255
|
+
}),
|
|
256
|
+
orientation: parseMediaOrientation({
|
|
257
|
+
value: helpers.getStringFlag({ flags, name: "orientation" }),
|
|
258
|
+
}),
|
|
158
259
|
limit: helpers.getNumberFlag({ flags, name: "limit" }),
|
|
159
260
|
offset: helpers.getNumberFlag({ flags, name: "offset" }),
|
|
160
261
|
});
|
|
@@ -201,15 +302,61 @@ async function handleMediaAssetCommand({ context, helpers, }) {
|
|
|
201
302
|
requireDeleteConfirmation({
|
|
202
303
|
confirmed: helpers.getBooleanFlag({ flags, name: "confirm-delete" }),
|
|
203
304
|
});
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
305
|
+
const assetIdsFlag = helpers.getStringFlag({ flags, name: "asset-ids" });
|
|
306
|
+
const search = helpers.getStringFlag({ flags, name: "search" });
|
|
307
|
+
const namePrefix = helpers.getStringFlag({ flags, name: "name-prefix" });
|
|
308
|
+
requireExactlyOneDeleteSelector({
|
|
309
|
+
selectors: [
|
|
310
|
+
helpers.getStringFlag({ flags, name: "asset-id" }),
|
|
311
|
+
assetIdsFlag,
|
|
312
|
+
search,
|
|
313
|
+
namePrefix,
|
|
314
|
+
],
|
|
211
315
|
});
|
|
212
|
-
|
|
316
|
+
{
|
|
317
|
+
const singleAssetId = helpers.getStringFlag({
|
|
318
|
+
flags,
|
|
319
|
+
name: "asset-id",
|
|
320
|
+
});
|
|
321
|
+
const result = await context.client.media.deleteMany({
|
|
322
|
+
ids: singleAssetId === undefined
|
|
323
|
+
? parseCommaSeparatedAssetIds({ value: assetIdsFlag })
|
|
324
|
+
: [singleAssetId],
|
|
325
|
+
search: search ?? null,
|
|
326
|
+
namePrefix: namePrefix ?? null,
|
|
327
|
+
confirmDelete: true,
|
|
328
|
+
dryRun: false,
|
|
329
|
+
reason: helpers.requireStringFlag({ flags, name: "reason" }),
|
|
330
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
331
|
+
flags,
|
|
332
|
+
name: "idempotency-key",
|
|
333
|
+
}),
|
|
334
|
+
deleteGeneratedClips: helpers.getBooleanFlag({
|
|
335
|
+
flags,
|
|
336
|
+
name: "delete-generated-clips",
|
|
337
|
+
}),
|
|
338
|
+
deleteLinkedProjects: helpers.getBooleanFlag({
|
|
339
|
+
flags,
|
|
340
|
+
name: "delete-linked-projects",
|
|
341
|
+
}),
|
|
342
|
+
});
|
|
343
|
+
helpers.printResult({
|
|
344
|
+
json: context.json,
|
|
345
|
+
value: result,
|
|
346
|
+
human: [
|
|
347
|
+
`Deleted ${result.deleted_count}/${result.selected_count} media assets.`,
|
|
348
|
+
...(result.failed_count > 0
|
|
349
|
+
? [`Failed: ${result.failed_count}.`]
|
|
350
|
+
: []),
|
|
351
|
+
],
|
|
352
|
+
});
|
|
353
|
+
assertBulkDeleteSucceeded({
|
|
354
|
+
failedCount: result.failed_count,
|
|
355
|
+
failedItems: result.failed_items,
|
|
356
|
+
resourceLabel: "media assets",
|
|
357
|
+
});
|
|
358
|
+
return true;
|
|
359
|
+
}
|
|
213
360
|
}
|
|
214
361
|
if (action === "upload") {
|
|
215
362
|
const result = await helpers.uploadMediaFile({ context });
|
|
@@ -218,6 +365,8 @@ async function handleMediaAssetCommand({ context, helpers, }) {
|
|
|
218
365
|
value: result,
|
|
219
366
|
human: [
|
|
220
367
|
`Media uploaded: ${result.id} ${result.name} (${result.asset_type}, ${result.processing_status})`,
|
|
368
|
+
`Processing run: ${result.processing_run_id ?? "none"}`,
|
|
369
|
+
`Follow-ups: transcription=${result.follow_up.transcription_requested ? "yes" : "no"}, description=${result.follow_up.description_requested ? "yes" : "no"}, short suggestions=${result.follow_up.short_suggestions_requested ? "yes" : "no"}`,
|
|
221
370
|
],
|
|
222
371
|
});
|
|
223
372
|
return true;
|
|
@@ -316,6 +465,11 @@ async function handleMediaAssetCommand({ context, helpers, }) {
|
|
|
316
465
|
...(result.asset.processingError
|
|
317
466
|
? [`Processing error: ${result.asset.processingError}`]
|
|
318
467
|
: []),
|
|
468
|
+
...(result.short_suggestions_outcome?.no_clip_reason
|
|
469
|
+
? [
|
|
470
|
+
`Short suggestions: ${String(result.short_suggestions_outcome.no_clip_reason)}`,
|
|
471
|
+
]
|
|
472
|
+
: []),
|
|
319
473
|
],
|
|
320
474
|
});
|
|
321
475
|
return true;
|
|
@@ -323,11 +477,149 @@ async function handleMediaAssetCommand({ context, helpers, }) {
|
|
|
323
477
|
if (action === "shorts") {
|
|
324
478
|
return handleMediaShortsCommand({ context, helpers, subaction });
|
|
325
479
|
}
|
|
480
|
+
if (action === "reframe" && subaction === "status") {
|
|
481
|
+
const result = await context.client.media.reframe.status({
|
|
482
|
+
assetId: helpers.requireStringFlag({ flags, name: "asset-id" }),
|
|
483
|
+
});
|
|
484
|
+
helpers.printResult({
|
|
485
|
+
json: context.json,
|
|
486
|
+
value: result,
|
|
487
|
+
human: [
|
|
488
|
+
`Reframe analysis: ${result.status}${result.analysis_version === null ? "" : ` v${result.analysis_version}`}.`,
|
|
489
|
+
],
|
|
490
|
+
});
|
|
491
|
+
return true;
|
|
492
|
+
}
|
|
493
|
+
if (action === "reframe" && subaction === "analyze") {
|
|
494
|
+
const result = await context.client.media.reframe.analyze({
|
|
495
|
+
assetId: helpers.requireStringFlag({ flags, name: "asset-id" }),
|
|
496
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
497
|
+
flags,
|
|
498
|
+
name: "idempotency-key",
|
|
499
|
+
}),
|
|
500
|
+
});
|
|
501
|
+
helpers.printResult({
|
|
502
|
+
json: context.json,
|
|
503
|
+
value: result,
|
|
504
|
+
human: [
|
|
505
|
+
`Reframe analysis: ${result.status}${result.triggered ? " queued" : " reused"}.`,
|
|
506
|
+
],
|
|
507
|
+
});
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
if (action === "reframe" && subaction === "apply") {
|
|
511
|
+
const result = await context.client.media.reframe.apply({
|
|
512
|
+
assetId: helpers.requireStringFlag({ flags, name: "asset-id" }),
|
|
513
|
+
projectId: helpers.requireStringFlag({ flags, name: "project-id" }),
|
|
514
|
+
replaceTimelineItemId: helpers.parseNullableStringFlag({
|
|
515
|
+
flags,
|
|
516
|
+
name: "replace-timeline-item-id",
|
|
517
|
+
}) ?? null,
|
|
518
|
+
aspectRatio: parseReframeAspectRatio({
|
|
519
|
+
value: helpers.parseNullableStringFlag({
|
|
520
|
+
flags,
|
|
521
|
+
name: "aspect-ratio",
|
|
522
|
+
}),
|
|
523
|
+
}),
|
|
524
|
+
trimStartSeconds: helpers.getNumberFlag({ flags, name: "trim-start" }) ?? null,
|
|
525
|
+
trimEndSeconds: helpers.getNumberFlag({ flags, name: "trim-end" }) ?? null,
|
|
526
|
+
contentTypeHint: parseReframeContentTypeHint({
|
|
527
|
+
value: helpers.getStringFlag({ flags, name: "content-type-hint" }),
|
|
528
|
+
}),
|
|
529
|
+
layoutStrategy: parseReframeLayoutStrategy({
|
|
530
|
+
value: helpers.getStringFlag({ flags, name: "layout-strategy" }),
|
|
531
|
+
}),
|
|
532
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
533
|
+
flags,
|
|
534
|
+
name: "idempotency-key",
|
|
535
|
+
}),
|
|
536
|
+
});
|
|
537
|
+
helpers.printResult({
|
|
538
|
+
json: context.json,
|
|
539
|
+
value: result,
|
|
540
|
+
human: [
|
|
541
|
+
`Reframe applied: ${result.timeline_item_ids.length} timeline item(s) in ${result.project_id}.`,
|
|
542
|
+
],
|
|
543
|
+
});
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
326
546
|
if (action === "folders") {
|
|
327
547
|
return handleMediaFoldersCommand({ context, helpers, subaction });
|
|
328
548
|
}
|
|
329
549
|
return false;
|
|
330
550
|
}
|
|
551
|
+
function parseMediaOrientation({ value, }) {
|
|
552
|
+
if (value === undefined)
|
|
553
|
+
return undefined;
|
|
554
|
+
if (value === "landscape" || value === "portrait" || value === "square") {
|
|
555
|
+
return value;
|
|
556
|
+
}
|
|
557
|
+
throw new CliUsageError({
|
|
558
|
+
code: "invalid_arguments",
|
|
559
|
+
message: "--orientation must be landscape, portrait, or square.",
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
function parseReframeContentTypeHint({ value, }) {
|
|
563
|
+
if (value === undefined ||
|
|
564
|
+
value === "auto" ||
|
|
565
|
+
value === "podcast" ||
|
|
566
|
+
value === "tutorial" ||
|
|
567
|
+
value === "generic") {
|
|
568
|
+
return value ?? "auto";
|
|
569
|
+
}
|
|
570
|
+
throw new CliUsageError({
|
|
571
|
+
code: "invalid_arguments",
|
|
572
|
+
message: "--content-type-hint must be auto, podcast, tutorial, or generic.",
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
function parseReframeLayoutStrategy({ value, }) {
|
|
576
|
+
const resolved = value ?? "auto";
|
|
577
|
+
if (resolved === "auto" ||
|
|
578
|
+
resolved === "demo" ||
|
|
579
|
+
resolved === "letterbox" ||
|
|
580
|
+
resolved === "split" ||
|
|
581
|
+
resolved === "focus" ||
|
|
582
|
+
resolved === "speaker_grid" ||
|
|
583
|
+
resolved === "webinar" ||
|
|
584
|
+
resolved === "webinar_stack" ||
|
|
585
|
+
resolved === "gameplay") {
|
|
586
|
+
return resolved;
|
|
587
|
+
}
|
|
588
|
+
throw new CliUsageError({
|
|
589
|
+
code: "invalid_arguments",
|
|
590
|
+
message: "Unsupported --layout-strategy value.",
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
function parseReframeAspectRatio({ value, }) {
|
|
594
|
+
if (value === null || value === undefined) {
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
if (value === "9:16" ||
|
|
598
|
+
value === "16:9" ||
|
|
599
|
+
value === "1:1" ||
|
|
600
|
+
value === "4:5") {
|
|
601
|
+
return value;
|
|
602
|
+
}
|
|
603
|
+
throw new CliUsageError({
|
|
604
|
+
code: "invalid_arguments",
|
|
605
|
+
message: "--aspect-ratio must be 9:16, 16:9, 1:1, 4:5, or null.",
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
function parseCommaSeparatedAssetIds({ value, }) {
|
|
609
|
+
if (value === undefined)
|
|
610
|
+
return [];
|
|
611
|
+
const ids = value
|
|
612
|
+
.split(",")
|
|
613
|
+
.map((id) => id.trim())
|
|
614
|
+
.filter(Boolean);
|
|
615
|
+
if (ids.length === 0) {
|
|
616
|
+
throw new CliUsageError({
|
|
617
|
+
code: "invalid_arguments",
|
|
618
|
+
message: "--asset-ids must contain at least one ID.",
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
return Array.from(new Set(ids));
|
|
622
|
+
}
|
|
331
623
|
async function handleMediaShortsCommand({ context, helpers, subaction, }) {
|
|
332
624
|
const flags = context.args.flags;
|
|
333
625
|
if (subaction === "list") {
|
|
@@ -362,6 +654,10 @@ async function handleMediaShortsCommand({ context, helpers, subaction, }) {
|
|
|
362
654
|
flags,
|
|
363
655
|
name: "auto-trim-silence",
|
|
364
656
|
}),
|
|
657
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
658
|
+
flags,
|
|
659
|
+
name: "idempotency-key",
|
|
660
|
+
}),
|
|
365
661
|
});
|
|
366
662
|
helpers.printResult({
|
|
367
663
|
json: context.json,
|
|
@@ -370,6 +666,25 @@ async function handleMediaShortsCommand({ context, helpers, subaction, }) {
|
|
|
370
666
|
});
|
|
371
667
|
return true;
|
|
372
668
|
}
|
|
669
|
+
if (subaction === "refresh-thumbnail") {
|
|
670
|
+
const result = await context.client.media.shorts.refreshThumbnail({
|
|
671
|
+
assetId: helpers.requireStringFlag({ flags, name: "asset-id" }),
|
|
672
|
+
suggestionId: helpers.requireStringFlag({
|
|
673
|
+
flags,
|
|
674
|
+
name: "suggestion-id",
|
|
675
|
+
}),
|
|
676
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
677
|
+
flags,
|
|
678
|
+
name: "idempotency-key",
|
|
679
|
+
}),
|
|
680
|
+
});
|
|
681
|
+
helpers.printResult({
|
|
682
|
+
json: context.json,
|
|
683
|
+
value: result,
|
|
684
|
+
human: [`Thumbnail regeneration queued: ${result.run_id}`],
|
|
685
|
+
});
|
|
686
|
+
return true;
|
|
687
|
+
}
|
|
373
688
|
if (subaction === "apply") {
|
|
374
689
|
const result = await context.client.media.shorts.apply({
|
|
375
690
|
assetId: helpers.requireStringFlag({ flags, name: "asset-id" }),
|
|
@@ -497,6 +812,34 @@ async function handleMediaFoldersCommand({ context, helpers, subaction, }) {
|
|
|
497
812
|
});
|
|
498
813
|
return true;
|
|
499
814
|
}
|
|
815
|
+
if (subaction === "empty") {
|
|
816
|
+
requireDeleteConfirmation({
|
|
817
|
+
confirmed: helpers.getBooleanFlag({ flags, name: "confirm-delete" }),
|
|
818
|
+
});
|
|
819
|
+
const result = await context.client.media.folders.empty({
|
|
820
|
+
folderId: helpers.requireStringFlag({ flags, name: "folder-id" }),
|
|
821
|
+
confirmDelete: true,
|
|
822
|
+
dryRun: false,
|
|
823
|
+
reason: helpers.requireStringFlag({ flags, name: "reason" }),
|
|
824
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
825
|
+
flags,
|
|
826
|
+
name: "idempotency-key",
|
|
827
|
+
}),
|
|
828
|
+
});
|
|
829
|
+
helpers.printResult({
|
|
830
|
+
json: context.json,
|
|
831
|
+
value: result,
|
|
832
|
+
human: [
|
|
833
|
+
`Deleted ${result.deleted_count}/${result.selected_count} media assets; folder retained.`,
|
|
834
|
+
],
|
|
835
|
+
});
|
|
836
|
+
assertBulkDeleteSucceeded({
|
|
837
|
+
failedCount: result.failed_count,
|
|
838
|
+
failedItems: result.failed_items,
|
|
839
|
+
resourceLabel: "media assets",
|
|
840
|
+
});
|
|
841
|
+
return true;
|
|
842
|
+
}
|
|
500
843
|
return false;
|
|
501
844
|
}
|
|
502
845
|
function buildMediaAssetDryRun({ context, spec, helpers, }) {
|
|
@@ -509,12 +852,46 @@ function buildMediaAssetDryRun({ context, spec, helpers, }) {
|
|
|
509
852
|
requireDeleteConfirmation({
|
|
510
853
|
confirmed: helpers.getBooleanFlag({ flags, name: "confirm-delete" }),
|
|
511
854
|
});
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
855
|
+
const assetIdsFlag = helpers.getStringFlag({ flags, name: "asset-ids" });
|
|
856
|
+
const search = helpers.getStringFlag({ flags, name: "search" });
|
|
857
|
+
const namePrefix = helpers.getStringFlag({ flags, name: "name-prefix" });
|
|
858
|
+
requireExactlyOneDeleteSelector({
|
|
859
|
+
selectors: [
|
|
860
|
+
helpers.getStringFlag({ flags, name: "asset-id" }),
|
|
861
|
+
assetIdsFlag,
|
|
862
|
+
search,
|
|
863
|
+
namePrefix,
|
|
864
|
+
],
|
|
517
865
|
});
|
|
866
|
+
{
|
|
867
|
+
const singleAssetId = helpers.getStringFlag({
|
|
868
|
+
flags,
|
|
869
|
+
name: "asset-id",
|
|
870
|
+
});
|
|
871
|
+
return helpers.dryRunRequest({
|
|
872
|
+
spec,
|
|
873
|
+
method: "POST",
|
|
874
|
+
path: "/workspace/media/assets/batch-delete",
|
|
875
|
+
body: {
|
|
876
|
+
ids: singleAssetId === undefined
|
|
877
|
+
? parseCommaSeparatedAssetIds({ value: assetIdsFlag })
|
|
878
|
+
: [singleAssetId],
|
|
879
|
+
search: search ?? null,
|
|
880
|
+
name_prefix: namePrefix ?? null,
|
|
881
|
+
confirm_delete: false,
|
|
882
|
+
dry_run: true,
|
|
883
|
+
reason: helpers.requireStringFlag({ flags, name: "reason" }),
|
|
884
|
+
delete_generated_clips: helpers.getBooleanFlag({
|
|
885
|
+
flags,
|
|
886
|
+
name: "delete-generated-clips",
|
|
887
|
+
}),
|
|
888
|
+
delete_linked_projects: helpers.getBooleanFlag({
|
|
889
|
+
flags,
|
|
890
|
+
name: "delete-linked-projects",
|
|
891
|
+
}),
|
|
892
|
+
},
|
|
893
|
+
});
|
|
894
|
+
}
|
|
518
895
|
}
|
|
519
896
|
if (action === "update" || action === "rename") {
|
|
520
897
|
return helpers.dryRunRequest({
|
|
@@ -570,6 +947,60 @@ function buildMediaAssetDryRun({ context, spec, helpers, }) {
|
|
|
570
947
|
},
|
|
571
948
|
});
|
|
572
949
|
}
|
|
950
|
+
if (action === "shorts" && subaction === "refresh-thumbnail") {
|
|
951
|
+
const assetId = helpers.requireStringFlag({ flags, name: "asset-id" });
|
|
952
|
+
const suggestionId = helpers.requireStringFlag({
|
|
953
|
+
flags,
|
|
954
|
+
name: "suggestion-id",
|
|
955
|
+
});
|
|
956
|
+
return helpers.dryRunRequest({
|
|
957
|
+
spec,
|
|
958
|
+
method: "POST",
|
|
959
|
+
path: `/workspace/media/assets/${encodeURIComponent(assetId)}/short-suggestions/${encodeURIComponent(suggestionId)}/thumbnail`,
|
|
960
|
+
headers: {
|
|
961
|
+
"Idempotency-Key": helpers.requireStringFlag({
|
|
962
|
+
flags,
|
|
963
|
+
name: "idempotency-key",
|
|
964
|
+
}),
|
|
965
|
+
},
|
|
966
|
+
body: {},
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
if (action === "reframe" && subaction === "apply") {
|
|
970
|
+
const assetId = helpers.requireStringFlag({ flags, name: "asset-id" });
|
|
971
|
+
return helpers.dryRunRequest({
|
|
972
|
+
spec,
|
|
973
|
+
method: "POST",
|
|
974
|
+
path: `/workspace/media/assets/${encodeURIComponent(assetId)}/reframe-plan/apply`,
|
|
975
|
+
headers: {
|
|
976
|
+
"Idempotency-Key": helpers.requireStringFlag({
|
|
977
|
+
flags,
|
|
978
|
+
name: "idempotency-key",
|
|
979
|
+
}),
|
|
980
|
+
},
|
|
981
|
+
body: {
|
|
982
|
+
project_id: helpers.requireStringFlag({ flags, name: "project-id" }),
|
|
983
|
+
replace_timeline_item_id: helpers.parseNullableStringFlag({
|
|
984
|
+
flags,
|
|
985
|
+
name: "replace-timeline-item-id",
|
|
986
|
+
}) ?? null,
|
|
987
|
+
aspect_ratio: parseReframeAspectRatio({
|
|
988
|
+
value: helpers.parseNullableStringFlag({
|
|
989
|
+
flags,
|
|
990
|
+
name: "aspect-ratio",
|
|
991
|
+
}),
|
|
992
|
+
}),
|
|
993
|
+
trim_start_seconds: helpers.getNumberFlag({ flags, name: "trim-start" }) ?? null,
|
|
994
|
+
trim_end_seconds: helpers.getNumberFlag({ flags, name: "trim-end" }) ?? null,
|
|
995
|
+
content_type_hint: parseReframeContentTypeHint({
|
|
996
|
+
value: helpers.getStringFlag({ flags, name: "content-type-hint" }),
|
|
997
|
+
}),
|
|
998
|
+
layout_strategy: parseReframeLayoutStrategy({
|
|
999
|
+
value: helpers.getStringFlag({ flags, name: "layout-strategy" }),
|
|
1000
|
+
}),
|
|
1001
|
+
},
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
573
1004
|
if (action === "folders" &&
|
|
574
1005
|
(subaction === "rename" || subaction === "update")) {
|
|
575
1006
|
const folderId = helpers.requireStringFlag({ flags, name: "folder-id" });
|
|
@@ -608,6 +1039,28 @@ function buildMediaAssetDryRun({ context, spec, helpers, }) {
|
|
|
608
1039
|
body: undefined,
|
|
609
1040
|
});
|
|
610
1041
|
}
|
|
1042
|
+
if (action === "folders" && subaction === "empty") {
|
|
1043
|
+
requireDeleteConfirmation({
|
|
1044
|
+
confirmed: helpers.getBooleanFlag({ flags, name: "confirm-delete" }),
|
|
1045
|
+
});
|
|
1046
|
+
const folderId = helpers.requireStringFlag({ flags, name: "folder-id" });
|
|
1047
|
+
return helpers.dryRunRequest({
|
|
1048
|
+
spec,
|
|
1049
|
+
method: "POST",
|
|
1050
|
+
path: `/workspace/media/folders/${encodeURIComponent(folderId)}/empty`,
|
|
1051
|
+
headers: {
|
|
1052
|
+
"Idempotency-Key": helpers.requireStringFlag({
|
|
1053
|
+
flags,
|
|
1054
|
+
name: "idempotency-key",
|
|
1055
|
+
}),
|
|
1056
|
+
},
|
|
1057
|
+
body: {
|
|
1058
|
+
confirm_delete: false,
|
|
1059
|
+
dry_run: true,
|
|
1060
|
+
reason: helpers.requireStringFlag({ flags, name: "reason" }),
|
|
1061
|
+
},
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
611
1064
|
return undefined;
|
|
612
1065
|
}
|
|
613
1066
|
function matchesMediaAssetCommand({ command }) {
|
|
@@ -619,14 +1072,21 @@ function matchesMediaAssetCommand({ command }) {
|
|
|
619
1072
|
return false;
|
|
620
1073
|
}
|
|
621
1074
|
if (action === "shorts") {
|
|
622
|
-
return (subaction === "list" ||
|
|
1075
|
+
return (subaction === "list" ||
|
|
1076
|
+
subaction === "generate" ||
|
|
1077
|
+
subaction === "apply" ||
|
|
1078
|
+
subaction === "refresh-thumbnail");
|
|
1079
|
+
}
|
|
1080
|
+
if (action === "reframe") {
|
|
1081
|
+
return (subaction === "status" || subaction === "analyze" || subaction === "apply");
|
|
623
1082
|
}
|
|
624
1083
|
if (action === "folders") {
|
|
625
1084
|
return (subaction === "list" ||
|
|
626
1085
|
subaction === "create" ||
|
|
627
1086
|
subaction === "rename" ||
|
|
628
1087
|
subaction === "update" ||
|
|
629
|
-
subaction === "delete"
|
|
1088
|
+
subaction === "delete" ||
|
|
1089
|
+
subaction === "empty");
|
|
630
1090
|
}
|
|
631
1091
|
return [
|
|
632
1092
|
"list",
|