blitzreels 0.1.8 → 0.1.10
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 +1 -1
- package/README.md +55 -3
- 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 +14 -1
- package/dist/cli-runtime.js.map +1 -1
- package/dist/command-metadata.d.ts.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/caption-dry-run.d.ts.map +1 -1
- package/dist/commands/caption-dry-run.js +16 -0
- package/dist/commands/caption-dry-run.js.map +1 -1
- package/dist/commands/captions-specs.d.ts.map +1 -1
- package/dist/commands/captions-specs.js +8 -0
- package/dist/commands/captions-specs.js.map +1 -1
- package/dist/commands/captions.js +16 -0
- package/dist/commands/captions.js.map +1 -1
- package/dist/commands/clips.d.ts +3 -0
- package/dist/commands/clips.d.ts.map +1 -1
- package/dist/commands/clips.js +743 -9
- package/dist/commands/clips.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/media-assets.d.ts +11 -7
- package/dist/commands/media-assets.d.ts.map +1 -1
- package/dist/commands/media-assets.js +269 -4
- package/dist/commands/media-assets.js.map +1 -1
- package/dist/commands/media-runtime.d.ts +8 -5
- package/dist/commands/media-runtime.d.ts.map +1 -1
- package/dist/commands/media-runtime.js +209 -18
- package/dist/commands/media-runtime.js.map +1 -1
- package/dist/commands/projects.js +3 -0
- 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 +482 -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.map +1 -1
- package/dist/index.js +14 -0
- 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 +2 -2
package/dist/commands/clips.js
CHANGED
|
@@ -1,7 +1,71 @@
|
|
|
1
1
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
|
+
import { CliOperationError, CliUsageError } from "../cli-errors.js";
|
|
3
4
|
import { commandSpec } from "../command-metadata.js";
|
|
4
5
|
export const CLIPS_COMMAND_SPECS = [
|
|
6
|
+
commandSpec({
|
|
7
|
+
command: ["clip-share-pages", "get"],
|
|
8
|
+
usage: "blitzreels clip-share-pages get --asset-id ID [--json]",
|
|
9
|
+
flags: ["asset-id"],
|
|
10
|
+
description: "Inspect the public clip share page and its hidden clip ids.",
|
|
11
|
+
}),
|
|
12
|
+
commandSpec({
|
|
13
|
+
command: ["clip-share-pages", "publish"],
|
|
14
|
+
usage: "blitzreels clip-share-pages publish --asset-id ID --idempotency-key KEY [--allow-downloads true|false] [--dry-run] [--json]",
|
|
15
|
+
flags: [
|
|
16
|
+
"asset-id",
|
|
17
|
+
{ name: "allow-downloads", type: "boolean" },
|
|
18
|
+
{ name: "idempotency-key", required: true },
|
|
19
|
+
],
|
|
20
|
+
description: "Publish the clip share page for a source asset.",
|
|
21
|
+
mutates: true,
|
|
22
|
+
dryRunSupported: true,
|
|
23
|
+
}),
|
|
24
|
+
commandSpec({
|
|
25
|
+
command: ["clip-share-pages", "unpublish"],
|
|
26
|
+
usage: "blitzreels clip-share-pages unpublish --asset-id ID --idempotency-key KEY [--dry-run] [--json]",
|
|
27
|
+
flags: ["asset-id", { name: "idempotency-key", required: true }],
|
|
28
|
+
description: "Disable the public clip share page for a source asset.",
|
|
29
|
+
mutates: true,
|
|
30
|
+
dryRunSupported: true,
|
|
31
|
+
}),
|
|
32
|
+
commandSpec({
|
|
33
|
+
command: ["clip-share-pages", "set-clip-visibility"],
|
|
34
|
+
usage: "blitzreels clip-share-pages set-clip-visibility --asset-id ID --clip-id ID --visibility visible|hidden --idempotency-key KEY [--dry-run] [--json]",
|
|
35
|
+
flags: [
|
|
36
|
+
"asset-id",
|
|
37
|
+
"clip-id",
|
|
38
|
+
{ name: "visibility", enum: ["visible", "hidden"], required: true },
|
|
39
|
+
{ name: "idempotency-key", required: true },
|
|
40
|
+
],
|
|
41
|
+
description: "Show or hide one clip on its source asset share page.",
|
|
42
|
+
mutates: true,
|
|
43
|
+
dryRunSupported: true,
|
|
44
|
+
}),
|
|
45
|
+
commandSpec({
|
|
46
|
+
command: ["clip-batches", "get"],
|
|
47
|
+
usage: "blitzreels clip-batches get --batch-id ID [--json]",
|
|
48
|
+
flags: ["batch-id"],
|
|
49
|
+
description: "Inspect clip batch progress, Studio Sound status, and terminal errors.",
|
|
50
|
+
}),
|
|
51
|
+
commandSpec({
|
|
52
|
+
command: ["clip-batches", "wait"],
|
|
53
|
+
usage: "blitzreels clip-batches wait --batch-id ID [--interval-ms 3000] [--timeout-ms 1200000] [--json]",
|
|
54
|
+
flags: ["batch-id", "interval-ms", "timeout-ms"],
|
|
55
|
+
description: "Wait for a clip batch to complete or fail, including asynchronous Studio Sound.",
|
|
56
|
+
}),
|
|
57
|
+
commandSpec({
|
|
58
|
+
command: ["clip-batches", "recover"],
|
|
59
|
+
usage: "blitzreels clip-batches recover --batch-id ID [--target-count 10] --idempotency-key KEY [--dry-run] [--json]",
|
|
60
|
+
flags: [
|
|
61
|
+
"batch-id",
|
|
62
|
+
{ name: "target-count", type: "number" },
|
|
63
|
+
{ name: "idempotency-key", required: true },
|
|
64
|
+
],
|
|
65
|
+
description: "Preserve accepted clips and refill a terminal batch in its existing project folder.",
|
|
66
|
+
mutates: true,
|
|
67
|
+
dryRunSupported: true,
|
|
68
|
+
}),
|
|
5
69
|
commandSpec({
|
|
6
70
|
command: ["clip-batches", "delete"],
|
|
7
71
|
usage: "blitzreels clip-batches delete --batch-id ID --retention retain_projects_and_exports|delete_projects_and_exports --idempotency-key KEY --confirm-delete [--dry-run] [--json]",
|
|
@@ -42,14 +106,46 @@ export const CLIPS_COMMAND_SPECS = [
|
|
|
42
106
|
"failed",
|
|
43
107
|
],
|
|
44
108
|
},
|
|
45
|
-
|
|
109
|
+
{
|
|
110
|
+
name: "limit",
|
|
111
|
+
type: "number",
|
|
112
|
+
description: "Maximum 50 clips per page.",
|
|
113
|
+
},
|
|
46
114
|
"offset",
|
|
47
115
|
],
|
|
48
116
|
description: "List managed clip runs with bounded output.",
|
|
49
117
|
}),
|
|
118
|
+
commandSpec({
|
|
119
|
+
command: ["clips", "attach-export"],
|
|
120
|
+
usage: "blitzreels clips attach-export --asset-id ID --project-id ID --export-id ID --confirm-visual-qa --idempotency-key KEY [--dry-run] [--json]",
|
|
121
|
+
flags: [
|
|
122
|
+
"asset-id",
|
|
123
|
+
"project-id",
|
|
124
|
+
"export-id",
|
|
125
|
+
{ name: "confirm-visual-qa", required: true },
|
|
126
|
+
{ name: "idempotency-key", required: true },
|
|
127
|
+
],
|
|
128
|
+
description: "Attach one visually accepted completed project export to managed clips.",
|
|
129
|
+
mutates: true,
|
|
130
|
+
destructive: true,
|
|
131
|
+
dryRunSupported: true,
|
|
132
|
+
}),
|
|
133
|
+
commandSpec({
|
|
134
|
+
command: ["clips", "promote-export"],
|
|
135
|
+
usage: "blitzreels clips promote-export --clip-id ID --export-id ID --confirm-visual-qa --idempotency-key KEY [--dry-run] [--json]",
|
|
136
|
+
flags: [
|
|
137
|
+
"clip-id",
|
|
138
|
+
"export-id",
|
|
139
|
+
{ name: "confirm-visual-qa", required: true },
|
|
140
|
+
{ name: "idempotency-key", required: true },
|
|
141
|
+
],
|
|
142
|
+
description: "Promote one visually accepted completed export as the managed clip delivery.",
|
|
143
|
+
mutates: true,
|
|
144
|
+
dryRunSupported: true,
|
|
145
|
+
}),
|
|
50
146
|
commandSpec({
|
|
51
147
|
command: ["clips", "create"],
|
|
52
|
-
usage: "blitzreels clips create [--asset-id ID|--youtube-url URL] [--output ./clips] [--count 5] [--idempotency-key KEY]",
|
|
148
|
+
usage: "blitzreels clips create [--asset-id ID|--youtube-url URL] [--output ./clips] [--count 5] [--studio-sound] [--layout-mode people_first] [--content-type-hint podcast] [--idempotency-key KEY]",
|
|
53
149
|
flags: [
|
|
54
150
|
{ name: "asset-id", enum: [] },
|
|
55
151
|
"youtube-url",
|
|
@@ -62,7 +158,7 @@ export const CLIPS_COMMAND_SPECS = [
|
|
|
62
158
|
name: "count",
|
|
63
159
|
type: "number",
|
|
64
160
|
default: 5,
|
|
65
|
-
description: "Maximum
|
|
161
|
+
description: "Maximum clips created by the batch.",
|
|
66
162
|
},
|
|
67
163
|
{
|
|
68
164
|
name: "preset",
|
|
@@ -79,6 +175,28 @@ export const CLIPS_COMMAND_SPECS = [
|
|
|
79
175
|
hidden: false,
|
|
80
176
|
},
|
|
81
177
|
{ name: "caption-theme-id" },
|
|
178
|
+
{
|
|
179
|
+
name: "studio-sound",
|
|
180
|
+
type: "boolean",
|
|
181
|
+
description: "Clean the source audio once before rendering clips.",
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: "layout-mode",
|
|
185
|
+
enum: [
|
|
186
|
+
"auto",
|
|
187
|
+
"people_first",
|
|
188
|
+
"screen_first",
|
|
189
|
+
"preserve_full_source",
|
|
190
|
+
"prefer_split",
|
|
191
|
+
"prefer_focus",
|
|
192
|
+
"prefer_tutorial",
|
|
193
|
+
"prefer_demo",
|
|
194
|
+
],
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: "content-type-hint",
|
|
198
|
+
enum: ["auto", "podcast", "tutorial", "demo", "generic"],
|
|
199
|
+
},
|
|
82
200
|
{
|
|
83
201
|
name: "idempotency-key",
|
|
84
202
|
description: "Stable retry key; reuse only with identical inputs.",
|
|
@@ -90,6 +208,7 @@ export const CLIPS_COMMAND_SPECS = [
|
|
|
90
208
|
examples: [
|
|
91
209
|
"blitzreels clips create --asset-id ID --output ./clips",
|
|
92
210
|
"blitzreels clips create --asset-id ID --logo-asset-id LOGO_ID --output ./clips --count 5",
|
|
211
|
+
"blitzreels clips create --asset-id ID --layout-mode people_first --content-type-hint podcast",
|
|
93
212
|
"blitzreels clips create --youtube-url https://youtube.com/watch?v=...",
|
|
94
213
|
],
|
|
95
214
|
}),
|
|
@@ -107,7 +226,7 @@ export const CLIPS_COMMAND_SPECS = [
|
|
|
107
226
|
}),
|
|
108
227
|
commandSpec({
|
|
109
228
|
command: ["clips", "reselect"],
|
|
110
|
-
usage: "blitzreels clips reselect --clip-id ID [--suggestion-id ID | --start-seconds 52 --end-seconds 64]",
|
|
229
|
+
usage: "blitzreels clips reselect --clip-id ID [--suggestion-id ID | --start-seconds 52 --end-seconds 64] [--layout-mode people_first] [--content-type-hint podcast] [--caption-style-id cinematic-film] [--caption-word-reveal-animation fade] [--caption-max-lines 2] [--caption-words-per-line 8] [--caption-page-combine-ms 3000]",
|
|
111
230
|
flags: [
|
|
112
231
|
"clip-id",
|
|
113
232
|
"suggestion-id",
|
|
@@ -120,8 +239,54 @@ export const CLIPS_COMMAND_SPECS = [
|
|
|
120
239
|
},
|
|
121
240
|
{ name: "min-duration", hidden: true },
|
|
122
241
|
{ name: "max-duration", hidden: true },
|
|
242
|
+
{
|
|
243
|
+
name: "layout-mode",
|
|
244
|
+
enum: [
|
|
245
|
+
"auto",
|
|
246
|
+
"people_first",
|
|
247
|
+
"screen_first",
|
|
248
|
+
"preserve_full_source",
|
|
249
|
+
"prefer_split",
|
|
250
|
+
"prefer_focus",
|
|
251
|
+
"prefer_tutorial",
|
|
252
|
+
"prefer_demo",
|
|
253
|
+
],
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
name: "content-type-hint",
|
|
257
|
+
enum: ["auto", "podcast", "tutorial", "demo", "generic"],
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: "tutorial-stack-ratio",
|
|
261
|
+
enum: ["screen_70_face_30", "screen_50_face_50"],
|
|
262
|
+
hidden: true,
|
|
263
|
+
},
|
|
264
|
+
"captions-enabled",
|
|
265
|
+
"caption-style-id",
|
|
266
|
+
{
|
|
267
|
+
name: "caption-word-reveal-animation",
|
|
268
|
+
enum: [
|
|
269
|
+
"none",
|
|
270
|
+
"fade",
|
|
271
|
+
"scale",
|
|
272
|
+
"slide-up",
|
|
273
|
+
"slide-left",
|
|
274
|
+
"slide-mix",
|
|
275
|
+
"pop",
|
|
276
|
+
"drop",
|
|
277
|
+
"slam",
|
|
278
|
+
"typewriter",
|
|
279
|
+
"glitch",
|
|
280
|
+
"mask-reveal",
|
|
281
|
+
"bounce-up",
|
|
282
|
+
"split-reveal",
|
|
283
|
+
],
|
|
284
|
+
},
|
|
285
|
+
"caption-max-lines",
|
|
286
|
+
"caption-words-per-line",
|
|
287
|
+
"caption-page-combine-ms",
|
|
123
288
|
],
|
|
124
|
-
description: "
|
|
289
|
+
description: "Regenerate a clip from a suggestion or time range with optional layout and caption settings.",
|
|
125
290
|
mutates: true,
|
|
126
291
|
}),
|
|
127
292
|
commandSpec({
|
|
@@ -163,10 +328,111 @@ export const CLIPS_COMMAND_SPECS = [
|
|
|
163
328
|
mutates: true,
|
|
164
329
|
}),
|
|
165
330
|
];
|
|
331
|
+
function parseClipShareVisibility({ value, }) {
|
|
332
|
+
if (value === "visible" || value === "hidden") {
|
|
333
|
+
return value;
|
|
334
|
+
}
|
|
335
|
+
throw new CliUsageError({
|
|
336
|
+
code: "invalid_flag_value",
|
|
337
|
+
message: "--visibility must be visible or hidden.",
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
function parseClipListLimit({ value, }) {
|
|
341
|
+
if (value === undefined)
|
|
342
|
+
return undefined;
|
|
343
|
+
if (Number.isInteger(value) && value >= 1 && value <= 50)
|
|
344
|
+
return value;
|
|
345
|
+
throw new CliUsageError({
|
|
346
|
+
code: "invalid_flag_value",
|
|
347
|
+
message: "--limit must be an integer between 1 and 50.",
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
function printClipBatchResult({ context, result, helpers, }) {
|
|
351
|
+
helpers.printResult({
|
|
352
|
+
json: context.json,
|
|
353
|
+
value: result,
|
|
354
|
+
human: [
|
|
355
|
+
`Batch ${result.batch.batch_id}: ${result.batch.status}`,
|
|
356
|
+
`Studio Sound: ${result.batch.studio_sound.status}`,
|
|
357
|
+
`Accepted: ${result.batch.rendered_count}/${result.batch.estimated_clip_count}`,
|
|
358
|
+
...(result.batch.last_error_message === null
|
|
359
|
+
? []
|
|
360
|
+
: [`Error: ${result.batch.last_error_message}`]),
|
|
361
|
+
],
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
async function waitForClipBatch({ context, helpers, }) {
|
|
365
|
+
const batchId = helpers.requireStringFlag({
|
|
366
|
+
flags: context.args.flags,
|
|
367
|
+
name: "batch-id",
|
|
368
|
+
});
|
|
369
|
+
const intervalMs = helpers.getNumberFlag({
|
|
370
|
+
flags: context.args.flags,
|
|
371
|
+
name: "interval-ms",
|
|
372
|
+
}) ?? 3000;
|
|
373
|
+
const timeoutMs = helpers.getNumberFlag({
|
|
374
|
+
flags: context.args.flags,
|
|
375
|
+
name: "timeout-ms",
|
|
376
|
+
}) ?? 20 * 60 * 1000;
|
|
377
|
+
const startedAt = Date.now();
|
|
378
|
+
while (true) {
|
|
379
|
+
const result = await context.client.clipBatches.get({ batchId });
|
|
380
|
+
if (result.batch.studio_sound.status === "failed") {
|
|
381
|
+
throw new CliOperationError({
|
|
382
|
+
code: "studio_sound_failed",
|
|
383
|
+
exitCode: 5,
|
|
384
|
+
message: `Clip batch ${batchId} failed Studio Sound: ${result.batch.studio_sound.error_message ?? result.batch.last_error_message ?? "treatment was not applied"}`,
|
|
385
|
+
retryable: false,
|
|
386
|
+
suggestions: [
|
|
387
|
+
`blitzreels clip-batches recover --batch-id ${batchId} --idempotency-key NEW_KEY --json`,
|
|
388
|
+
],
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
if (result.batch.status === "failed") {
|
|
392
|
+
throw new CliOperationError({
|
|
393
|
+
code: "clip_batch_failed",
|
|
394
|
+
exitCode: 5,
|
|
395
|
+
message: `Clip batch ${batchId} failed: ${result.batch.last_error_message ?? result.batch.studio_sound.error_message ?? "clip processing failed"}`,
|
|
396
|
+
retryable: false,
|
|
397
|
+
suggestions: [
|
|
398
|
+
`blitzreels clip-batches recover --batch-id ${batchId} --idempotency-key NEW_KEY --json`,
|
|
399
|
+
],
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
if (result.batch.status === "completed_with_errors") {
|
|
403
|
+
throw new CliOperationError({
|
|
404
|
+
code: "clip_batch_incomplete",
|
|
405
|
+
exitCode: 5,
|
|
406
|
+
message: `Clip batch ${batchId} completed with ${result.batch.failed_count + result.batch.review_count} clips needing recovery.`,
|
|
407
|
+
retryable: false,
|
|
408
|
+
suggestions: [
|
|
409
|
+
`blitzreels clip-batches recover --batch-id ${batchId} --idempotency-key NEW_KEY --json`,
|
|
410
|
+
],
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
if (result.batch.status === "completed") {
|
|
414
|
+
return result;
|
|
415
|
+
}
|
|
416
|
+
if (Date.now() - startedAt >= timeoutMs) {
|
|
417
|
+
throw new CliOperationError({
|
|
418
|
+
code: "clip_batch_wait_timeout",
|
|
419
|
+
exitCode: 7,
|
|
420
|
+
message: `Timed out waiting for clip batch ${batchId}.`,
|
|
421
|
+
retryable: true,
|
|
422
|
+
suggestions: [
|
|
423
|
+
`blitzreels clip-batches get --batch-id ${batchId} --json`,
|
|
424
|
+
],
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
await helpers.sleep({ ms: intervalMs });
|
|
428
|
+
}
|
|
429
|
+
}
|
|
166
430
|
export function createClipsCommandOperation({ helpers, }) {
|
|
167
431
|
return {
|
|
168
432
|
name: "clips",
|
|
169
|
-
matches: ({ command }) => command[0] === "clips" ||
|
|
433
|
+
matches: ({ command }) => command[0] === "clips" ||
|
|
434
|
+
command[0] === "clip-batches" ||
|
|
435
|
+
command[0] === "clip-share-pages",
|
|
170
436
|
handle: ({ context }) => handleClipsCommand({ context, helpers }),
|
|
171
437
|
buildDryRun: ({ context, spec }) => buildClipsDryRun({ context, spec, helpers }),
|
|
172
438
|
};
|
|
@@ -174,6 +440,118 @@ export function createClipsCommandOperation({ helpers, }) {
|
|
|
174
440
|
async function handleClipsCommand({ context, helpers, }) {
|
|
175
441
|
const action = context.args.command[1];
|
|
176
442
|
const flags = context.args.flags;
|
|
443
|
+
if (context.args.command[0] === "clip-share-pages") {
|
|
444
|
+
const assetId = helpers.requireStringFlag({ flags, name: "asset-id" });
|
|
445
|
+
if (action === "get") {
|
|
446
|
+
const result = await context.client.clipSharePages.get({ assetId });
|
|
447
|
+
helpers.printResult({
|
|
448
|
+
json: context.json,
|
|
449
|
+
value: result,
|
|
450
|
+
human: [
|
|
451
|
+
result.enabled
|
|
452
|
+
? `Published: ${result.share_url}`
|
|
453
|
+
: "Share page is not published.",
|
|
454
|
+
`Hidden clips: ${result.hidden_clip_ids.length}`,
|
|
455
|
+
],
|
|
456
|
+
});
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
if (action === "publish" || action === "unpublish") {
|
|
460
|
+
const result = await context.client.clipSharePages.setEnabled({
|
|
461
|
+
assetId,
|
|
462
|
+
enabled: action === "publish",
|
|
463
|
+
allowDownloads: helpers.getOptionalBooleanFlag({
|
|
464
|
+
flags,
|
|
465
|
+
name: "allow-downloads",
|
|
466
|
+
}),
|
|
467
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
468
|
+
flags,
|
|
469
|
+
name: "idempotency-key",
|
|
470
|
+
}),
|
|
471
|
+
});
|
|
472
|
+
helpers.printResult({
|
|
473
|
+
json: context.json,
|
|
474
|
+
value: result,
|
|
475
|
+
human: [
|
|
476
|
+
result.enabled
|
|
477
|
+
? `Published: ${result.share_url}`
|
|
478
|
+
: "Share page unpublished.",
|
|
479
|
+
],
|
|
480
|
+
});
|
|
481
|
+
return true;
|
|
482
|
+
}
|
|
483
|
+
if (action === "set-clip-visibility") {
|
|
484
|
+
const visibility = parseClipShareVisibility({
|
|
485
|
+
value: helpers.requireStringFlag({
|
|
486
|
+
flags,
|
|
487
|
+
name: "visibility",
|
|
488
|
+
}),
|
|
489
|
+
});
|
|
490
|
+
const result = await context.client.clipSharePages.setClipVisibility({
|
|
491
|
+
assetId,
|
|
492
|
+
clipId: helpers.requireStringFlag({ flags, name: "clip-id" }),
|
|
493
|
+
visibility,
|
|
494
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
495
|
+
flags,
|
|
496
|
+
name: "idempotency-key",
|
|
497
|
+
}),
|
|
498
|
+
});
|
|
499
|
+
helpers.printResult({
|
|
500
|
+
json: context.json,
|
|
501
|
+
value: result,
|
|
502
|
+
human: [`Clip ${result.clip_id}: ${result.visibility}`],
|
|
503
|
+
});
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
if (context.args.command[0] === "clip-batches" && action === "get") {
|
|
508
|
+
const result = await context.client.clipBatches.get({
|
|
509
|
+
batchId: helpers.requireStringFlag({ flags, name: "batch-id" }),
|
|
510
|
+
});
|
|
511
|
+
printClipBatchResult({ context, result, helpers });
|
|
512
|
+
return true;
|
|
513
|
+
}
|
|
514
|
+
if (context.args.command[0] === "clip-batches" && action === "wait") {
|
|
515
|
+
const result = await waitForClipBatch({ context, helpers });
|
|
516
|
+
printClipBatchResult({ context, result, helpers });
|
|
517
|
+
return true;
|
|
518
|
+
}
|
|
519
|
+
if (context.args.command[0] === "clip-batches" && action === "recover") {
|
|
520
|
+
const result = await context.client.clipBatches.recover({
|
|
521
|
+
batchId: helpers.requireStringFlag({ flags, name: "batch-id" }),
|
|
522
|
+
targetClipCount: helpers.getNumberFlag({ flags, name: "target-count" }) ?? null,
|
|
523
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
524
|
+
flags,
|
|
525
|
+
name: "idempotency-key",
|
|
526
|
+
}),
|
|
527
|
+
});
|
|
528
|
+
if (result.status === "failed") {
|
|
529
|
+
throw new CliOperationError({
|
|
530
|
+
code: "clip_batch_recovery_failed",
|
|
531
|
+
exitCode: 5,
|
|
532
|
+
message: `Recovery batch ${result.recovery_batch_id ?? result.source_batch_id} failed: ${result.queue_reason ?? "clip recovery failed"}`,
|
|
533
|
+
retryable: false,
|
|
534
|
+
suggestions: [
|
|
535
|
+
'blitzreels agent-context --command "clip-batches recover" --json',
|
|
536
|
+
],
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
const statusLine = result.status === "satisfied"
|
|
540
|
+
? `Batch ${result.source_batch_id} already has ${result.retained_clip_count}/${result.target_clip_count} accepted clips.`
|
|
541
|
+
: result.status === "queued"
|
|
542
|
+
? `Recovery batch ${result.recovery_batch_id} queued for ${result.refill_clip_count} missing clips.`
|
|
543
|
+
: `Recovery batch ${result.recovery_batch_id} created; waiting: ${result.queue_reason ?? "not ready to queue"}.`;
|
|
544
|
+
helpers.printResult({
|
|
545
|
+
json: context.json,
|
|
546
|
+
value: result,
|
|
547
|
+
human: [
|
|
548
|
+
statusLine,
|
|
549
|
+
`Folder: ${result.project_folder_id}`,
|
|
550
|
+
"Duration policy: quality first; suggestion boundaries preserved.",
|
|
551
|
+
],
|
|
552
|
+
});
|
|
553
|
+
return true;
|
|
554
|
+
}
|
|
177
555
|
if (context.args.command[0] === "clip-batches" && action === "delete") {
|
|
178
556
|
if (helpers.getOptionalBooleanFlag({ flags, name: "confirm-delete" }) !== true) {
|
|
179
557
|
throw new Error("Pass --confirm-delete to delete a clip batch.");
|
|
@@ -216,6 +594,66 @@ async function handleClipsCommand({ context, helpers, }) {
|
|
|
216
594
|
});
|
|
217
595
|
return true;
|
|
218
596
|
}
|
|
597
|
+
if (action === "attach-export") {
|
|
598
|
+
if (helpers.getOptionalBooleanFlag({
|
|
599
|
+
flags,
|
|
600
|
+
name: "confirm-visual-qa",
|
|
601
|
+
}) !== true) {
|
|
602
|
+
throw new CliUsageError({
|
|
603
|
+
code: "missing_visual_qa_confirmation",
|
|
604
|
+
message: "Pass --confirm-visual-qa only after reviewing the completed MP4.",
|
|
605
|
+
usage: "blitzreels clips attach-export --asset-id ID --project-id ID --export-id ID --confirm-visual-qa --idempotency-key KEY",
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
const result = await context.client.clips.attachExport({
|
|
609
|
+
assetId: helpers.requireStringFlag({ flags, name: "asset-id" }),
|
|
610
|
+
projectId: helpers.requireStringFlag({ flags, name: "project-id" }),
|
|
611
|
+
exportId: helpers.requireStringFlag({ flags, name: "export-id" }),
|
|
612
|
+
confirmVisualQa: true,
|
|
613
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
614
|
+
flags,
|
|
615
|
+
name: "idempotency-key",
|
|
616
|
+
}),
|
|
617
|
+
});
|
|
618
|
+
helpers.printResult({
|
|
619
|
+
json: context.json,
|
|
620
|
+
value: result,
|
|
621
|
+
human: [
|
|
622
|
+
`Attached export ${result.export_id} to managed clip ${result.clip_id}.`,
|
|
623
|
+
],
|
|
624
|
+
});
|
|
625
|
+
return true;
|
|
626
|
+
}
|
|
627
|
+
if (action === "promote-export") {
|
|
628
|
+
if (helpers.getOptionalBooleanFlag({
|
|
629
|
+
flags,
|
|
630
|
+
name: "confirm-visual-qa",
|
|
631
|
+
}) !== true) {
|
|
632
|
+
throw new CliUsageError({
|
|
633
|
+
code: "missing_visual_qa_confirmation",
|
|
634
|
+
message: "Pass --confirm-visual-qa only after reviewing the completed MP4.",
|
|
635
|
+
usage: "blitzreels clips promote-export --clip-id ID --export-id ID --confirm-visual-qa --idempotency-key KEY",
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
const result = await context.client.clips.promoteExport({
|
|
639
|
+
clipId: helpers.requireStringFlag({ flags, name: "clip-id" }),
|
|
640
|
+
exportId: helpers.requireStringFlag({ flags, name: "export-id" }),
|
|
641
|
+
confirmVisualQa: true,
|
|
642
|
+
idempotencyKey: helpers.requireStringFlag({
|
|
643
|
+
flags,
|
|
644
|
+
name: "idempotency-key",
|
|
645
|
+
}),
|
|
646
|
+
});
|
|
647
|
+
helpers.printResult({
|
|
648
|
+
json: context.json,
|
|
649
|
+
value: result,
|
|
650
|
+
human: [
|
|
651
|
+
`Promoted export ${result.export_id} for managed clip ${result.clip_id}.`,
|
|
652
|
+
`Previous export retained: ${result.previous_export_id}.`,
|
|
653
|
+
],
|
|
654
|
+
});
|
|
655
|
+
return true;
|
|
656
|
+
}
|
|
219
657
|
if (action === "list") {
|
|
220
658
|
const result = await context.client.clips.list({
|
|
221
659
|
assetId: helpers.getStringFlag({ flags, name: "asset-id" }),
|
|
@@ -223,7 +661,9 @@ async function handleClipsCommand({ context, helpers, }) {
|
|
|
223
661
|
status: parseClipStatus({
|
|
224
662
|
value: helpers.getStringFlag({ flags, name: "status" }),
|
|
225
663
|
}),
|
|
226
|
-
limit:
|
|
664
|
+
limit: parseClipListLimit({
|
|
665
|
+
value: helpers.getNumberFlag({ flags, name: "limit" }),
|
|
666
|
+
}),
|
|
227
667
|
offset: helpers.getNumberFlag({ flags, name: "offset" }),
|
|
228
668
|
});
|
|
229
669
|
helpers.printResult({
|
|
@@ -259,6 +699,8 @@ async function handleClipsCommand({ context, helpers, }) {
|
|
|
259
699
|
flags,
|
|
260
700
|
name: "selection-mode",
|
|
261
701
|
});
|
|
702
|
+
const layout = buildReselectLayout({ flags, helpers });
|
|
703
|
+
const captions = buildReselectCaptions({ flags, helpers });
|
|
262
704
|
const result = await context.client.clips.reselect({
|
|
263
705
|
clipId,
|
|
264
706
|
...(selectionMode === undefined
|
|
@@ -267,10 +709,14 @@ async function handleClipsCommand({ context, helpers, }) {
|
|
|
267
709
|
startSeconds: selection.startSeconds,
|
|
268
710
|
endSeconds: selection.endSeconds,
|
|
269
711
|
target,
|
|
712
|
+
layout,
|
|
713
|
+
captions,
|
|
270
714
|
}
|
|
271
715
|
: {
|
|
272
716
|
selection,
|
|
273
717
|
target,
|
|
718
|
+
layout,
|
|
719
|
+
captions,
|
|
274
720
|
}),
|
|
275
721
|
});
|
|
276
722
|
helpers.printClipResult({ context, result });
|
|
@@ -342,6 +788,128 @@ function formatClipListLine({ clip }) {
|
|
|
342
788
|
function buildClipsDryRun({ context, spec, helpers, }) {
|
|
343
789
|
const action = context.args.command[1];
|
|
344
790
|
const flags = context.args.flags;
|
|
791
|
+
if (context.args.command[0] === "clips" && action === "attach-export") {
|
|
792
|
+
if (helpers.getOptionalBooleanFlag({
|
|
793
|
+
flags,
|
|
794
|
+
name: "confirm-visual-qa",
|
|
795
|
+
}) !== true) {
|
|
796
|
+
throw new CliUsageError({
|
|
797
|
+
code: "missing_visual_qa_confirmation",
|
|
798
|
+
message: "Pass --confirm-visual-qa only after reviewing the completed MP4.",
|
|
799
|
+
usage: "blitzreels clips attach-export --asset-id ID --project-id ID --export-id ID --confirm-visual-qa --idempotency-key KEY",
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
return helpers.dryRunRequest({
|
|
803
|
+
spec,
|
|
804
|
+
method: "POST",
|
|
805
|
+
path: "/clips/attach-export",
|
|
806
|
+
headers: {
|
|
807
|
+
"Idempotency-Key": helpers.requireStringFlag({
|
|
808
|
+
flags,
|
|
809
|
+
name: "idempotency-key",
|
|
810
|
+
}),
|
|
811
|
+
},
|
|
812
|
+
body: {
|
|
813
|
+
asset_id: helpers.requireStringFlag({ flags, name: "asset-id" }),
|
|
814
|
+
project_id: helpers.requireStringFlag({ flags, name: "project-id" }),
|
|
815
|
+
export_id: helpers.requireStringFlag({ flags, name: "export-id" }),
|
|
816
|
+
confirm_visual_qa: true,
|
|
817
|
+
},
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
if (context.args.command[0] === "clips" && action === "promote-export") {
|
|
821
|
+
if (helpers.getOptionalBooleanFlag({
|
|
822
|
+
flags,
|
|
823
|
+
name: "confirm-visual-qa",
|
|
824
|
+
}) !== true) {
|
|
825
|
+
throw new CliUsageError({
|
|
826
|
+
code: "missing_visual_qa_confirmation",
|
|
827
|
+
message: "Pass --confirm-visual-qa only after reviewing the completed MP4.",
|
|
828
|
+
usage: "blitzreels clips promote-export --clip-id ID --export-id ID --confirm-visual-qa --idempotency-key KEY",
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
const clipId = helpers.requireStringFlag({ flags, name: "clip-id" });
|
|
832
|
+
return helpers.dryRunRequest({
|
|
833
|
+
spec,
|
|
834
|
+
method: "POST",
|
|
835
|
+
path: `/clips/${encodeURIComponent(clipId)}/promote-export`,
|
|
836
|
+
headers: {
|
|
837
|
+
"Idempotency-Key": helpers.requireStringFlag({
|
|
838
|
+
flags,
|
|
839
|
+
name: "idempotency-key",
|
|
840
|
+
}),
|
|
841
|
+
},
|
|
842
|
+
body: {
|
|
843
|
+
export_id: helpers.requireStringFlag({ flags, name: "export-id" }),
|
|
844
|
+
confirm_visual_qa: true,
|
|
845
|
+
},
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
if (context.args.command[0] === "clip-share-pages") {
|
|
849
|
+
const assetId = helpers.requireStringFlag({ flags, name: "asset-id" });
|
|
850
|
+
if (action === "publish" || action === "unpublish") {
|
|
851
|
+
return helpers.dryRunRequest({
|
|
852
|
+
spec,
|
|
853
|
+
method: "POST",
|
|
854
|
+
path: `/clip-share-pages/${encodeURIComponent(assetId)}`,
|
|
855
|
+
headers: {
|
|
856
|
+
"Idempotency-Key": helpers.requireStringFlag({
|
|
857
|
+
flags,
|
|
858
|
+
name: "idempotency-key",
|
|
859
|
+
}),
|
|
860
|
+
},
|
|
861
|
+
body: {
|
|
862
|
+
enabled: action === "publish",
|
|
863
|
+
allow_downloads: helpers.getOptionalBooleanFlag({
|
|
864
|
+
flags,
|
|
865
|
+
name: "allow-downloads",
|
|
866
|
+
}),
|
|
867
|
+
},
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
if (action === "set-clip-visibility") {
|
|
871
|
+
const clipId = helpers.requireStringFlag({ flags, name: "clip-id" });
|
|
872
|
+
return helpers.dryRunRequest({
|
|
873
|
+
spec,
|
|
874
|
+
method: "POST",
|
|
875
|
+
path: `/clip-share-pages/${encodeURIComponent(assetId)}/clips/${encodeURIComponent(clipId)}/visibility`,
|
|
876
|
+
headers: {
|
|
877
|
+
"Idempotency-Key": helpers.requireStringFlag({
|
|
878
|
+
flags,
|
|
879
|
+
name: "idempotency-key",
|
|
880
|
+
}),
|
|
881
|
+
},
|
|
882
|
+
body: {
|
|
883
|
+
visibility: parseClipShareVisibility({
|
|
884
|
+
value: helpers.requireStringFlag({
|
|
885
|
+
flags,
|
|
886
|
+
name: "visibility",
|
|
887
|
+
}),
|
|
888
|
+
}),
|
|
889
|
+
},
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
if (context.args.command[0] === "clip-batches" && action === "recover") {
|
|
894
|
+
return helpers.dryRunRequest({
|
|
895
|
+
spec,
|
|
896
|
+
method: "POST",
|
|
897
|
+
path: `/clip-batches/${encodeURIComponent(helpers.requireStringFlag({ flags, name: "batch-id" }))}/recover`,
|
|
898
|
+
headers: {
|
|
899
|
+
"Idempotency-Key": helpers.requireStringFlag({
|
|
900
|
+
flags,
|
|
901
|
+
name: "idempotency-key",
|
|
902
|
+
}),
|
|
903
|
+
},
|
|
904
|
+
body: {
|
|
905
|
+
target_clip_count: helpers.getNumberFlag({ flags, name: "target-count" }) ?? null,
|
|
906
|
+
},
|
|
907
|
+
notes: [
|
|
908
|
+
"Accepted exports remain linked; only the missing accepted count is refilled.",
|
|
909
|
+
"Suggestion boundaries are preserved even when a coherent clip exceeds the target duration.",
|
|
910
|
+
],
|
|
911
|
+
});
|
|
912
|
+
}
|
|
345
913
|
if (context.args.command[0] === "clip-batches" && action === "delete") {
|
|
346
914
|
return helpers.dryRunRequest({
|
|
347
915
|
spec,
|
|
@@ -392,8 +960,10 @@ function buildClipsDryRun({ context, spec, helpers, }) {
|
|
|
392
960
|
quality: null,
|
|
393
961
|
},
|
|
394
962
|
clip_preset_id: options.clipPresetId,
|
|
963
|
+
max_clip_count: options.count,
|
|
395
964
|
caption_theme_id: options.captionThemeId,
|
|
396
|
-
|
|
965
|
+
studio_sound: options.studioSound,
|
|
966
|
+
create_flow_options: buildClipWorkflowCreateFlowOptions({ options }),
|
|
397
967
|
branding_options: buildClipWorkflowBrandingOptions({
|
|
398
968
|
logoAssetId: options.logoAssetId,
|
|
399
969
|
}),
|
|
@@ -426,6 +996,8 @@ function buildClipsDryRun({ context, spec, helpers, }) {
|
|
|
426
996
|
flags,
|
|
427
997
|
name: "selection-mode",
|
|
428
998
|
});
|
|
999
|
+
const layout = buildReselectLayout({ flags, helpers });
|
|
1000
|
+
const captions = buildReselectCaptions({ flags, helpers });
|
|
429
1001
|
return helpers.dryRunRequest({
|
|
430
1002
|
spec,
|
|
431
1003
|
method: "POST",
|
|
@@ -449,6 +1021,12 @@ function buildClipsDryRun({ context, spec, helpers, }) {
|
|
|
449
1021
|
max_duration_seconds: target.maxDurationSeconds,
|
|
450
1022
|
},
|
|
451
1023
|
}),
|
|
1024
|
+
...(layout === null
|
|
1025
|
+
? {}
|
|
1026
|
+
: { layout: toApiClipLayout({ layout }) }),
|
|
1027
|
+
...(captions === null
|
|
1028
|
+
? {}
|
|
1029
|
+
: { captions: toApiClipCaptions({ captions }) }),
|
|
452
1030
|
}
|
|
453
1031
|
: {
|
|
454
1032
|
selection: toApiClipSelection({ selection }),
|
|
@@ -458,6 +1036,8 @@ function buildClipsDryRun({ context, spec, helpers, }) {
|
|
|
458
1036
|
min_duration_seconds: target.minDurationSeconds,
|
|
459
1037
|
max_duration_seconds: target.maxDurationSeconds,
|
|
460
1038
|
},
|
|
1039
|
+
layout: layout === null ? null : toApiClipLayout({ layout }),
|
|
1040
|
+
captions: captions === null ? null : toApiClipCaptions({ captions }),
|
|
461
1041
|
},
|
|
462
1042
|
});
|
|
463
1043
|
}
|
|
@@ -501,6 +1081,17 @@ function parseClipBatchDeleteRetention({ value, }) {
|
|
|
501
1081
|
}
|
|
502
1082
|
throw new Error("--retention must be retain_projects_and_exports or delete_projects_and_exports.");
|
|
503
1083
|
}
|
|
1084
|
+
function buildClipWorkflowCreateFlowOptions({ options, }) {
|
|
1085
|
+
return {
|
|
1086
|
+
...(options.layoutMode === undefined
|
|
1087
|
+
? {}
|
|
1088
|
+
: { reframeLayoutMode: options.layoutMode }),
|
|
1089
|
+
...(options.contentTypeHint === undefined
|
|
1090
|
+
? {}
|
|
1091
|
+
: { reframeContentTypeHint: options.contentTypeHint }),
|
|
1092
|
+
...(options.studioSound ? { useStudioSound: true } : {}),
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
504
1095
|
function parseClipWorkflowOptions({ flags, helpers, }) {
|
|
505
1096
|
const count = helpers.getNumberFlag({ flags, name: "count" }) ?? 5;
|
|
506
1097
|
if (!Number.isInteger(count) || count < 1 || count > 10) {
|
|
@@ -540,6 +1131,13 @@ function parseClipWorkflowOptions({ flags, helpers, }) {
|
|
|
540
1131
|
captionThemeId: parseNullableWorkflowString({
|
|
541
1132
|
value: helpers.getStringFlag({ flags, name: "caption-theme-id" }),
|
|
542
1133
|
}),
|
|
1134
|
+
layoutMode: parseClipLayoutMode({
|
|
1135
|
+
value: helpers.getStringFlag({ flags, name: "layout-mode" }),
|
|
1136
|
+
}),
|
|
1137
|
+
contentTypeHint: parseClipContentTypeHint({
|
|
1138
|
+
value: helpers.getStringFlag({ flags, name: "content-type-hint" }),
|
|
1139
|
+
}),
|
|
1140
|
+
studioSound: helpers.getOptionalBooleanFlag({ flags, name: "studio-sound" }) ?? false,
|
|
543
1141
|
idempotencyKey: helpers.getStringFlag({ flags, name: "idempotency-key" }) ?? null,
|
|
544
1142
|
};
|
|
545
1143
|
}
|
|
@@ -574,8 +1172,10 @@ async function createClipWorkflow({ context, helpers, }) {
|
|
|
574
1172
|
quality: null,
|
|
575
1173
|
},
|
|
576
1174
|
clipPresetId: options.clipPresetId,
|
|
1175
|
+
maxClipCount: options.count,
|
|
577
1176
|
captionThemeId: options.captionThemeId,
|
|
578
|
-
|
|
1177
|
+
studioSound: options.studioSound,
|
|
1178
|
+
createFlowOptions: buildClipWorkflowCreateFlowOptions({ options }),
|
|
579
1179
|
brandingOptions: buildClipWorkflowBrandingOptions({
|
|
580
1180
|
logoAssetId: options.logoAssetId,
|
|
581
1181
|
}),
|
|
@@ -695,4 +1295,138 @@ function toApiClipSelection({ selection, }) {
|
|
|
695
1295
|
end_seconds: selection.endSeconds,
|
|
696
1296
|
};
|
|
697
1297
|
}
|
|
1298
|
+
function parseClipLayoutMode({ value, }) {
|
|
1299
|
+
if (value === undefined ||
|
|
1300
|
+
value === "auto" ||
|
|
1301
|
+
value === "people_first" ||
|
|
1302
|
+
value === "screen_first" ||
|
|
1303
|
+
value === "preserve_full_source" ||
|
|
1304
|
+
value === "prefer_split" ||
|
|
1305
|
+
value === "prefer_focus" ||
|
|
1306
|
+
value === "prefer_tutorial" ||
|
|
1307
|
+
value === "prefer_demo") {
|
|
1308
|
+
return value;
|
|
1309
|
+
}
|
|
1310
|
+
throw new Error(`Unsupported clip layout mode: ${value}`);
|
|
1311
|
+
}
|
|
1312
|
+
function parseClipContentTypeHint({ value, }) {
|
|
1313
|
+
if (value === undefined ||
|
|
1314
|
+
value === "auto" ||
|
|
1315
|
+
value === "podcast" ||
|
|
1316
|
+
value === "tutorial" ||
|
|
1317
|
+
value === "demo" ||
|
|
1318
|
+
value === "generic") {
|
|
1319
|
+
return value;
|
|
1320
|
+
}
|
|
1321
|
+
throw new Error(`Unsupported clip content type hint: ${value}`);
|
|
1322
|
+
}
|
|
1323
|
+
function parseTutorialStackRatio({ value, }) {
|
|
1324
|
+
if (value === undefined ||
|
|
1325
|
+
value === "screen_70_face_30" ||
|
|
1326
|
+
value === "screen_50_face_50") {
|
|
1327
|
+
return value;
|
|
1328
|
+
}
|
|
1329
|
+
throw new Error(`Unsupported tutorial stack ratio: ${value}`);
|
|
1330
|
+
}
|
|
1331
|
+
function buildReselectLayout({ flags, helpers, }) {
|
|
1332
|
+
const mode = parseClipLayoutMode({
|
|
1333
|
+
value: helpers.getStringFlag({ flags, name: "layout-mode" }),
|
|
1334
|
+
});
|
|
1335
|
+
const contentTypeHint = parseClipContentTypeHint({
|
|
1336
|
+
value: helpers.getStringFlag({ flags, name: "content-type-hint" }),
|
|
1337
|
+
});
|
|
1338
|
+
const tutorialStackRatio = parseTutorialStackRatio({
|
|
1339
|
+
value: helpers.getStringFlag({ flags, name: "tutorial-stack-ratio" }),
|
|
1340
|
+
});
|
|
1341
|
+
if (mode === undefined &&
|
|
1342
|
+
contentTypeHint === undefined &&
|
|
1343
|
+
tutorialStackRatio === undefined) {
|
|
1344
|
+
return null;
|
|
1345
|
+
}
|
|
1346
|
+
return { mode, contentTypeHint, tutorialStackRatio };
|
|
1347
|
+
}
|
|
1348
|
+
function buildReselectCaptions({ flags, helpers, }) {
|
|
1349
|
+
const enabled = helpers.getOptionalBooleanFlag({
|
|
1350
|
+
flags,
|
|
1351
|
+
name: "captions-enabled",
|
|
1352
|
+
});
|
|
1353
|
+
const styleId = helpers.getStringFlag({
|
|
1354
|
+
flags,
|
|
1355
|
+
name: "caption-style-id",
|
|
1356
|
+
});
|
|
1357
|
+
const wordRevealAnimation = parseCaptionWordRevealAnimation({
|
|
1358
|
+
value: helpers.getStringFlag({
|
|
1359
|
+
flags,
|
|
1360
|
+
name: "caption-word-reveal-animation",
|
|
1361
|
+
}),
|
|
1362
|
+
});
|
|
1363
|
+
const maxLinesPerCaption = helpers.getNumberFlag({
|
|
1364
|
+
flags,
|
|
1365
|
+
name: "caption-max-lines",
|
|
1366
|
+
});
|
|
1367
|
+
const wordsPerLineLimit = helpers.getNumberFlag({
|
|
1368
|
+
flags,
|
|
1369
|
+
name: "caption-words-per-line",
|
|
1370
|
+
});
|
|
1371
|
+
const pageCombineMs = helpers.getNumberFlag({
|
|
1372
|
+
flags,
|
|
1373
|
+
name: "caption-page-combine-ms",
|
|
1374
|
+
});
|
|
1375
|
+
if (enabled === undefined &&
|
|
1376
|
+
styleId === undefined &&
|
|
1377
|
+
wordRevealAnimation === undefined &&
|
|
1378
|
+
maxLinesPerCaption === undefined &&
|
|
1379
|
+
wordsPerLineLimit === undefined &&
|
|
1380
|
+
pageCombineMs === undefined) {
|
|
1381
|
+
return null;
|
|
1382
|
+
}
|
|
1383
|
+
return {
|
|
1384
|
+
enabled,
|
|
1385
|
+
styleId,
|
|
1386
|
+
wordRevealAnimation,
|
|
1387
|
+
maxLinesPerCaption,
|
|
1388
|
+
wordsPerLineLimit,
|
|
1389
|
+
pageCombineMs,
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
function parseCaptionWordRevealAnimation({ value, }) {
|
|
1393
|
+
const supported = [
|
|
1394
|
+
"none",
|
|
1395
|
+
"fade",
|
|
1396
|
+
"scale",
|
|
1397
|
+
"slide-up",
|
|
1398
|
+
"slide-left",
|
|
1399
|
+
"slide-mix",
|
|
1400
|
+
"pop",
|
|
1401
|
+
"drop",
|
|
1402
|
+
"slam",
|
|
1403
|
+
"typewriter",
|
|
1404
|
+
"glitch",
|
|
1405
|
+
"mask-reveal",
|
|
1406
|
+
"bounce-up",
|
|
1407
|
+
"split-reveal",
|
|
1408
|
+
];
|
|
1409
|
+
if (value === undefined ||
|
|
1410
|
+
supported.some((candidate) => candidate === value)) {
|
|
1411
|
+
return value;
|
|
1412
|
+
}
|
|
1413
|
+
throw new Error(`Unsupported caption word reveal animation: ${value}`);
|
|
1414
|
+
}
|
|
1415
|
+
function toApiClipLayout({ layout }) {
|
|
1416
|
+
return {
|
|
1417
|
+
layout_mode: layout.mode,
|
|
1418
|
+
content_type_hint: layout.contentTypeHint,
|
|
1419
|
+
tutorial_stack_ratio: layout.tutorialStackRatio,
|
|
1420
|
+
};
|
|
1421
|
+
}
|
|
1422
|
+
function toApiClipCaptions({ captions }) {
|
|
1423
|
+
return {
|
|
1424
|
+
enabled: captions.enabled,
|
|
1425
|
+
style_id: captions.styleId,
|
|
1426
|
+
word_reveal_animation: captions.wordRevealAnimation,
|
|
1427
|
+
max_lines_per_caption: captions.maxLinesPerCaption,
|
|
1428
|
+
words_per_line_limit: captions.wordsPerLineLimit,
|
|
1429
|
+
page_combine_ms: captions.pageCombineMs,
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
698
1432
|
//# sourceMappingURL=clips.js.map
|