cueframe 0.9.4 → 0.11.3
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/README.md +39 -30
- package/dist/analyze-C3MSCON6.js +2 -0
- package/dist/chunk-OAJBHFAJ.js +18 -0
- package/dist/cueframe.js +55 -54
- package/dist/skills/add-music-bed/SKILL.md +5 -23
- package/dist/skills/brand-reel/SKILL.md +5 -28
- package/dist/skills/clip-a-talking-head/SKILL.md +2 -20
- package/dist/skills/composing-video/SKILL.md +36 -424
- package/dist/skills/composing-video/references/acceptance-template.md +21 -0
- package/dist/skills/composing-video/references/audio-design.md +125 -0
- package/dist/skills/composing-video/references/card-and-motion-runtime.md +49 -0
- package/dist/skills/composing-video/references/craft-principles.md +25 -0
- package/dist/skills/composing-video/references/film-planning.md +37 -0
- package/dist/skills/composing-video/references/format-decisions.md +17 -0
- package/dist/skills/composing-video/references/format-playbooks.md +96 -0
- package/dist/skills/composing-video/references/motion-design.md +25 -0
- package/dist/skills/composing-video/references/project-policy.md +18 -0
- package/dist/skills/composing-video/references/sfx-pack.md +69 -0
- package/dist/skills/composing-video/references/sound-and-timing.md +15 -0
- package/dist/skills/composing-video/references/tool-map.md +43 -0
- package/dist/skills/cueframe-brand-demo/SKILL.md +2 -8
- package/dist/skills/cueframe-cli/SKILL.md +73 -59
- package/dist/skills/cueframe-component-authoring/SKILL.md +20 -169
- package/dist/skills/cueframe-component-authoring/references/authoring-paths.md +72 -0
- package/dist/skills/cueframe-component-authoring/references/forking-and-layout.md +35 -0
- package/dist/skills/cueframe-component-authoring/references/native-component-workflows.md +98 -0
- package/dist/skills/cueframe-component-authoring/references/native-source-contract.md +54 -0
- package/dist/skills/cueframe-component-authoring/references/parented-device-card.json +13 -0
- package/dist/skills/cueframe-component-authoring/references/parented-motion.md +25 -0
- package/dist/skills/cueframe-component-authoring/references/retired-projects.md +26 -0
- package/dist/skills/cueframe-compose-loop/SKILL.md +14 -112
- package/dist/skills/cueframe-compose-loop/references/convergence-loop.md +128 -0
- package/dist/skills/cueframe-compose-loop/references/preview-workflow.md +7 -3
- package/dist/skills/cueframe-connect/SKILL.md +4 -9
- package/dist/skills/cueframe-connect/references/tools.md +146 -0
- package/dist/skills/cueframe-product-video/SKILL.md +9 -14
- package/dist/skills/cueframe-reference-video/SKILL.md +30 -0
- package/dist/skills/cueframe-reference-video/references/measurement-and-comparison.md +45 -0
- package/dist/skills/cueframe-reference-video/scripts/motion-grid.sh +116 -0
- package/dist/skills/cueframe-scene-shot/SKILL.md +2 -8
- package/dist/skills/cueframe-storyboard/SKILL.md +1 -7
- package/dist/skills/every-format-from-one-edit/SKILL.md +3 -19
- package/dist/skills/extracting-brand-kits/SKILL.md +1 -7
- package/dist/skills/launch-video/SKILL.md +6 -26
- package/dist/skills/make-a-social-reel/SKILL.md +7 -26
- package/dist/skills/rebrand-a-video/SKILL.md +2 -19
- package/dist/skills/video-craft-standards/SKILL.md +20 -103
- package/dist/skills/video-craft-standards/references/format-standards.md +118 -0
- package/package.json +12 -11
- package/dist/analyze-XP2BESVX.js +0 -2
- package/dist/chunk-RSOHINDT.js +0 -18
|
@@ -5,13 +5,7 @@ description: Turns footage into a finished 9:16 social reel — hook inside 2 se
|
|
|
5
5
|
|
|
6
6
|
# Make a social reel
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
User intent and acceptance criteria override this recipe's aesthetic defaults. Silent, typography-only, uncaptioned and slow work are valid; no universal narration, footage, CTA, beat count or score target. Contracts, factual fidelity, media bindings and current source revisions remain mandatory.
|
|
11
|
-
|
|
12
|
-
Read available tools and current project; preserve the chosen local/hosted lane. Supported local work needs no hosted registration. Do not silently install, authenticate, switch projects or upload local content. Before metered hosted work, check `get_account`, entitlements, balance and quotes. Desktop setup: https://docs.cueframe.ai.
|
|
13
|
-
|
|
14
|
-
For scoped revisions, preserve unrelated timing, media, audio and shared brand-kit state. Edit affected content; inspect relevant frames, continuous motion and affected audio. No restarted intake, new approval pause, paid judge or final export by default. Judge only when useful; scores never override acceptance failures. Stop/report after two no-improvement passes. See [preview workflow](../cueframe-compose-loop/references/preview-workflow.md).
|
|
8
|
+
Use the [project and capability policy](../composing-video/references/project-policy.md) for scope, current state and metered work.
|
|
15
9
|
|
|
16
10
|
You hand over footage (a file URL, a talk, a product moment); you get back a 9:16 reel of 8–30
|
|
17
11
|
seconds that opens on its strongest image, cuts on the music, carries brand-grade type, and ends
|
|
@@ -74,29 +68,16 @@ affected window and regressions without automatically rerunning the full-film ju
|
|
|
74
68
|
`describe_composition_ops({type:"captions.fromComposition"})`, then style via
|
|
75
69
|
`setCaptionStyle` (plated, bottom, out of the mouth/eyes). Most social viewing is sound-off;
|
|
76
70
|
don't karaoke a beat with no speech.
|
|
77
|
-
8. **
|
|
78
|
-
describe each still in words
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
9. **
|
|
71
|
+
8. **Inspect and revise.** `preview_frame` at the important layout and transition landmarks;
|
|
72
|
+
describe each still in words, then inspect the intervening motion and relevant audio. Use
|
|
73
|
+
`score_composition` only when broader critique is useful and within budget, with your one-line
|
|
74
|
+
vision as `editorialIntent`, and fix the worst criterion first. Fix located acceptance failures against the brief.
|
|
75
|
+
9. **Export for requested final delivery.** `create_render` → `wait_job (kind:"render")`. Iterate with previews,
|
|
82
76
|
not renders.
|
|
83
77
|
|
|
84
78
|
## What good looks like
|
|
85
79
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
> **DEFAULT** The hook lands inside 2 seconds: the strongest image, motion, or claim opens the
|
|
89
|
-
> piece. No logo-first cold opens, no fade-in-from-black preambles.
|
|
90
|
-
|
|
91
|
-
> **DEFAULT** Typography is poster-grade: composed plates/fields in the brand palette, considered
|
|
92
|
-
> alignment and scale. **Consider:** centered white text floating on footage.
|
|
93
|
-
|
|
94
|
-
> **DEFAULT** Pacing is cut-driven: a new visual beat at least every ~4s […] **DEFAULT** Ends on a
|
|
95
|
-
> deliberate beat: tagline, logo, or CTA lockup — not a clip running out.
|
|
96
|
-
|
|
97
|
-
And the cross-cutting audio rule:
|
|
98
|
-
|
|
99
|
-
> **DEFAULT** Audio is decided, never defaulted […] **Consider:** a render whose silence nobody chose.
|
|
80
|
+
Use the relevant [craft review questions](../video-craft-standards/SKILL.md) and the [preview workflow](../cueframe-compose-loop/references/preview-workflow.md). Judge the brief's actual intent, visual relationships, timing and sound; format suggestions do not override the requested treatment. For this format's defaults read section 1 (Social reel) of the [format standards](../video-craft-standards/references/format-standards.md).
|
|
100
81
|
|
|
101
82
|
## Delivering
|
|
102
83
|
|
|
@@ -5,13 +5,7 @@ description: Swaps the brand kit under an existing video and re-renders — toke
|
|
|
5
5
|
|
|
6
6
|
# Rebrand a video
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
User intent and acceptance criteria override this recipe's aesthetic defaults. Silent, typography-only, uncaptioned and slow work are valid; no universal narration, footage, CTA, beat count or score target. Contracts, factual fidelity, media bindings and current source revisions remain mandatory.
|
|
11
|
-
|
|
12
|
-
Read available tools and current project; preserve the chosen local/hosted lane. Supported local work needs no hosted registration. Do not silently install, authenticate, switch projects or upload local content. Before metered hosted work, check `get_account`, entitlements, balance and quotes. Desktop setup: https://docs.cueframe.ai.
|
|
13
|
-
|
|
14
|
-
For scoped revisions, preserve unrelated timing, media, audio and shared brand-kit state. Edit affected content; inspect relevant frames, continuous motion and affected audio. No restarted intake, new approval pause, paid judge or final export by default. Judge only when useful; scores never override acceptance failures. Stop/report after two no-improvement passes. See [preview workflow](../cueframe-compose-loop/references/preview-workflow.md).
|
|
8
|
+
Use the [project and capability policy](../composing-video/references/project-policy.md) for scope, current state and metered work.
|
|
15
9
|
|
|
16
10
|
You bring a finished video and a new brand (a kit, a website, or new colors/fonts/logo); you get
|
|
17
11
|
the same video back wearing the new identity — everything bound to brand tokens re-themes at
|
|
@@ -72,18 +66,7 @@ keep the final re-render separate from previews used to resolve individual styli
|
|
|
72
66
|
|
|
73
67
|
## What good looks like
|
|
74
68
|
|
|
75
|
-
|
|
76
|
-
card in any class:
|
|
77
|
-
|
|
78
|
-
> **DEFAULT** Every graphic is bespoke to the brand: its type, its palette as fields, its layout
|
|
79
|
-
> system. **Consider:** any layout that would look correct with another brand's hex swapped in.
|
|
80
|
-
|
|
81
|
-
> **DEFAULT** Footage color and brand palette agree — grade toward the palette or choose footage
|
|
82
|
-
> that lives in it.
|
|
83
|
-
|
|
84
|
-
And cross-cutting: *"**DEFAULT** Brand/text graphics are AUTHORED — `kind:"card"` HTML (your
|
|
85
|
-
typography, layout, palette-as-fields) […] **Consider:** a brand graphic rendered from a catalog text
|
|
86
|
-
primitive."*
|
|
69
|
+
Use the relevant [craft review questions](../video-craft-standards/SKILL.md) and the [preview workflow](../cueframe-compose-loop/references/preview-workflow.md). Judge the brief's actual intent, visual relationships, timing and sound; format suggestions do not override the requested treatment. The bespoke test in section 3 of the [format standards](../video-craft-standards/references/format-standards.md) applies to every card in any class.
|
|
87
70
|
|
|
88
71
|
## Delivering
|
|
89
72
|
|
|
@@ -1,121 +1,38 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: video-craft-standards
|
|
3
|
-
description:
|
|
3
|
+
description: "Use when judging whether a CueFrame video's idea, visual form, motion, timing and sound meet its brief or reference (social reel, launch film, brand reel, talking-head clip). For tool selection and scoped revision use cueframe-compose-loop. Triggers on \"is this good enough\", \"quality bar\", \"what should a finished reel have\", \"review my video\", or any request to make a video when no other skill has stated the bar."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Video
|
|
6
|
+
# Video craft review
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Use the [project and capability policy](../composing-video/references/project-policy.md). Judge the requested film, not a universal house style. Typography, gradients, logo openings, deliberate stillness, silent work and reconstructed UI artwork can all be valid choices. Factual claims and the identity of actual captures must remain truthful.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
[cueframe-compose-loop](../cueframe-compose-loop/SKILL.md) owns evidence, optional judge use and revision scope. Its [preview workflow](../cueframe-compose-loop/references/preview-workflow.md) distinguishes isolated previews, saved compositions and final exports. Use these questions where they matter to the brief; a small color correction does not require a new whole-film critique.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
## What should the viewer experience?
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Can the film's intended idea, transformation, mood or observation be understood? Does each major choice support it? For a story, does an action change what follows? For an identity study, are form and movement specific to that identity? A film can intentionally be non-narrative; do not invent a sales argument to justify it.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
## Do the visual relationships hold?
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Inspect hierarchy, silhouette, spacing and legibility at the intended viewing size. Verify that essential copy has enough readable time after settling. For a reference, compare projected bounds, glyph form, angles, materials and camera path as well as subject names. Two scenes showing the same phone are not necessarily the same shot.
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
the thing a viewer should be able to repeat afterward ("real bread takes
|
|
22
|
-
48 hours and you can taste every one of them"). Not a vibe, not a tagline:
|
|
23
|
-
a claim with tension (what does this brand/story believe that its category
|
|
24
|
-
doesn't?).
|
|
25
|
-
- **DEFAULT** Each included channel serves the requested intent, in harmony:
|
|
26
|
-
- **Footage** — each clip earns its place as proof of the claim, chosen
|
|
27
|
-
from the claim's shot list, not from search-term aesthetics.
|
|
28
|
-
- **Sound** — the bed's mood and TEMPO embody the claim (a "slow" claim
|
|
29
|
-
gets a patient, sparse bed and the nerve to hold shots; an "instant"
|
|
30
|
-
claim cuts hot). Silence and pauses are rhetoric, not absence.
|
|
31
|
-
- **Pacing** — the cut rhythm IS part of the argument; it may defy
|
|
32
|
-
platform convention when the claim demands it.
|
|
33
|
-
- **Type/cards** — copy advances the argument; the tagline lands as the
|
|
34
|
-
CONCLUSION the beats have earned, never as a caption.
|
|
35
|
-
- **Review prompts:** (1) beats reorderable without changing what the video
|
|
36
|
-
says; (2) any channel (bed, shot, card) that would fit a different claim
|
|
37
|
-
equally well; (3) a viewer who watched it cannot state the claim.
|
|
20
|
+
Mounted UI should remain attached to its screen. Masks, edges and occlusion should agree with the pose. A pointer contacts the intended control before the response; an object carried through a transition retains identity and an intelligible path. Multiple simultaneous movements are useful when the viewer can follow their relationship. An attractive still does not establish any of these temporal properties.
|
|
38
21
|
|
|
39
|
-
##
|
|
22
|
+
## Does time express the idea?
|
|
40
23
|
|
|
41
|
-
|
|
42
|
-
For scoped corrections and preview selection, use `cueframe-compose-loop`'s
|
|
43
|
-
[preview workflow](../cueframe-compose-loop/references/preview-workflow.md). Inspect continuous
|
|
44
|
-
motion and listen to affected audio, not only stills or judge scores. Keep the user's explicit
|
|
45
|
-
scope and acceptance criteria; approved simulated UI is not evidence of a real product capture.
|
|
24
|
+
Look for accidental pauses, rushed reading windows, unexplained changes in speed and transitions that lose the subject. A deliberate hold can be the strongest beat. Check actual stable time rather than a layer's nominal duration. For a revision, ensure dependent motion and sound still agree with the new event order. Inspect the complete end, including backgrounds, captions and tails.
|
|
46
25
|
|
|
47
|
-
|
|
48
|
-
typography, layout, palette-as-fields) animated in CSS or with `clip.setKeyframes`,
|
|
49
|
-
or a native component (`create_component`). Catalog text primitives are for utility only.
|
|
50
|
-
**Consider:** a brand graphic rendered from a catalog text primitive.
|
|
51
|
-
- **DEFAULT** Audio is decided, never defaulted: a music bed (curated packs via
|
|
52
|
-
`import_resource {kind:"music-pack"}`) or ambience/loops (Freesound via
|
|
53
|
-
`search_resources kind:"sfx"`), honoring the brand kit's `musicMood`;
|
|
54
|
-
cut to the beat via `materializeGrid` when the bed drives pacing — OR an
|
|
55
|
-
explicit intentional-silence decision recorded in your delivery note with
|
|
56
|
-
the reason. **Consider:** a render whose silence nobody chose.
|
|
57
|
-
- **DEFAULT** Footage carries the video: real footage / real UI / real data
|
|
58
|
-
≥60% of runtime for footage-first classes. Typography-only work is a valid requested format.
|
|
59
|
-
- **DEFAULT** Every stock asset's provenance is recorded (provider, id, author).
|
|
60
|
-
- **DEFAULT** Safe-area respected: no critical copy in the outer ~8% of frame.
|
|
61
|
-
- **DEFAULT** One final render per approval; iterate with previews, not renders.
|
|
62
|
-
- **DEFAULT** Delivery never ends with "done": the last message carries the
|
|
63
|
-
output link and where to find it, plus the intentional-silence note if any.
|
|
26
|
+
## Does the medium support the promise?
|
|
64
27
|
|
|
65
|
-
|
|
28
|
+
- **Product evidence:** a real interaction and its result are visible and legible. Simulated UI is identified as artwork, not a capture of working software.
|
|
29
|
+
- **Speech-led footage:** selected words preserve meaning; captions and framing follow actual source evidence and the saved edit. Camera movement and captions are choices governed by the brief.
|
|
30
|
+
- **Type, illustration or data:** geometry and transformation carry meaning; text remains accurate, values are sourced and material behavior is coherent.
|
|
31
|
+
- **Brand work:** type, palette, material and motion form an intentional system; a new logo/name should not be the only thing distinguishing a supposedly specific treatment.
|
|
32
|
+
- **Sound:** heard intelligibility, balance and event synchronization are separate from loudness or waveform measurements. Silence needs no apology when it serves the piece.
|
|
66
33
|
|
|
67
|
-
|
|
68
|
-
or claim opens the piece. No logo-first cold opens, no fade-in-from-black
|
|
69
|
-
preambles.
|
|
70
|
-
- **DEFAULT** Typography is poster-grade: composed plates/fields in the brand
|
|
71
|
-
palette, considered alignment and scale. **Consider:** centered white text
|
|
72
|
-
floating on footage.
|
|
73
|
-
- **DEFAULT** Pacing is cut-driven: a new visual beat at least every ~4s; static
|
|
74
|
-
holds >4s need motion inside the frame (reframe push, kenBurns, animated
|
|
75
|
-
card) or they die.
|
|
76
|
-
- **DEFAULT** Ends on a deliberate beat: tagline, logo, or CTA lockup — not a
|
|
77
|
-
clip running out.
|
|
78
|
-
- **SHOULD** Cuts land on the music grid when a bed exists.
|
|
34
|
+
A useful critique names a timestamp/window, observed problem, its consequence and a plausible correction. Prioritize failures of intent, fidelity or continuity over minor polish. Do not certify unseen motion or unheard audio, and do not substitute a score for the user's acceptance criteria.
|
|
79
35
|
|
|
80
|
-
##
|
|
36
|
+
## Detailed guidance
|
|
81
37
|
|
|
82
|
-
-
|
|
83
|
-
("Close the books two days faster" beats "Introducing the reconciliation
|
|
84
|
-
module"). No throat-clearing ("in this video we're going to…").
|
|
85
|
-
- **DEFAULT** Narration or a bed that builds toward the reveal; pacing tightens
|
|
86
|
-
as the payoff approaches.
|
|
87
|
-
- **DEFAULT** Real product surface: actual UI/screens/output — never mocked.
|
|
88
|
-
- **DEFAULT** End card with a single CTA.
|
|
89
|
-
- **DEFAULT** Captions present when narrated.
|
|
90
|
-
|
|
91
|
-
## 3. Brand-identity reel — 9:16 · 12–20s (the showcase class)
|
|
92
|
-
|
|
93
|
-
Everything in §1, plus:
|
|
94
|
-
- **DEFAULT** Three-beat arc: opening brand moment (wordmark treatment) →
|
|
95
|
-
middle craft/proof beat (the subject's world, with an editorial device —
|
|
96
|
-
numbered chapter, pull-quote, stat) → closing tagline lockup.
|
|
97
|
-
- **DEFAULT** Every graphic is bespoke to the brand: its type, its palette as
|
|
98
|
-
fields, its layout system. **Consider:** any layout that would look correct with
|
|
99
|
-
another brand's hex swapped in.
|
|
100
|
-
- **DEFAULT** Footage color and brand palette agree — grade toward the palette
|
|
101
|
-
or choose footage that lives in it.
|
|
102
|
-
|
|
103
|
-
## 4. Talking-head clip — any aspect · 15–60s
|
|
104
|
-
|
|
105
|
-
- **DEFAULT** Hook = the strongest sentence, first. Cut TO the moment;
|
|
106
|
-
never open on wind-up.
|
|
107
|
-
- **DEFAULT** Active-speaker reframe (`focus: active-speaker` / `face`) — a
|
|
108
|
-
moving camera, not a static center crop.
|
|
109
|
-
- **DEFAULT** Captions timed to the saved edited timeline (`captions.fromComposition`
|
|
110
|
-
after the clip edits; re-run after later edits). Speech clips must have saved duration matching playable source duration divided by
|
|
111
|
-
playbackRate.
|
|
112
|
-
The focused behind-the-speaker LOOK is an overlay text layer at
|
|
113
|
-
`zPlane:"behind-subject"` where the footage allows. Use caption-layer
|
|
114
|
-
`zPlane:"behind-subject"` only when the user explicitly wants every running
|
|
115
|
-
caption behind the speaker and the legibility gate accepts it.
|
|
116
|
-
- **DEFAULT** Dead air and false starts cut (`addExcludedRange` /
|
|
117
|
-
`cutAndRipple`).
|
|
118
|
-
|
|
119
|
-
## Scoring discipline
|
|
120
|
-
|
|
121
|
-
Check the requested criteria against appropriate real evidence: affected stills, continuous motion and audio when relevant. Broader review can use `score_composition` when useful and within budget; it is not mandatory for a scoped correction. The hosted judge includes a fixed caption criterion and can penalize intentionally uncaptioned work; do not add captions solely to improve that score. These skill changes do not change judge behavior. Failed user acceptance criteria remain failures regardless of score. Stop and report remaining gaps after two passes without improvement; export only for requested final delivery.
|
|
38
|
+
[Format standards](references/format-standards.md) has the controlling idea, the cross-cutting rules, and the checklists for social reels, launch films, brand-identity reels and talking-head clips, plus scoring discipline.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Format standards
|
|
2
|
+
|
|
3
|
+
Defaults, examples and detail for this topic. The [skill](../SKILL.md) and the [project and capability policy](../../composing-video/references/project-policy.md) take precedence where they differ, and the current tool schemas are authoritative.
|
|
4
|
+
|
|
5
|
+
## Scope and capability policy
|
|
6
|
+
|
|
7
|
+
User intent and acceptance criteria override this recipe's aesthetic defaults. Silent, typography-only, uncaptioned and slow work are valid; no universal narration, footage, CTA, beat count or score target. Contracts, factual fidelity, media bindings and current source revisions remain mandatory.
|
|
8
|
+
|
|
9
|
+
Read available tools and current project; preserve the chosen local/hosted lane. Supported local work needs no hosted registration. Do not silently install, authenticate, switch projects or upload local content. Before metered hosted work, check `get_account`, entitlements, balance and quotes. Desktop setup: https://docs.cueframe.ai.
|
|
10
|
+
|
|
11
|
+
For scoped revisions, preserve unrelated timing, media, audio and shared brand-kit state. Edit affected content; inspect relevant frames, continuous motion and affected audio. No restarted intake, new approval pause, paid judge or final export by default. Judge only when useful; scores never override acceptance failures. Stop/report after two no-improvement passes. See [preview workflow](../../cueframe-compose-loop/references/preview-workflow.md).
|
|
12
|
+
|
|
13
|
+
These are aesthetic defaults for the named formats, not universal delivery gates. Apply only the checklist items relevant to the requested artifact; a silent typography study needs neither footage nor narration, and a title correction needs only affected evidence. User acceptance criteria govern delivery. The labels below describe recommendations; do not reject explicit creative choices using a default or a judge score.
|
|
14
|
+
|
|
15
|
+
## The controlling idea — the rule above every rule
|
|
16
|
+
|
|
17
|
+
- **DEFAULT** For new work, consider stating the video's CLAIM in one sentence —
|
|
18
|
+
the thing a viewer should be able to repeat afterward ("real bread takes
|
|
19
|
+
48 hours and you can taste every one of them"). Not a vibe, not a tagline:
|
|
20
|
+
a claim with tension (what does this brand/story believe that its category
|
|
21
|
+
doesn't?).
|
|
22
|
+
- **DEFAULT** Each included channel serves the requested intent, in harmony:
|
|
23
|
+
- **Footage** — each clip earns its place as proof of the claim, chosen
|
|
24
|
+
from the claim's shot list, not from search-term aesthetics.
|
|
25
|
+
- **Sound** — the bed's mood and TEMPO embody the claim (a "slow" claim
|
|
26
|
+
gets a patient, sparse bed and the nerve to hold shots; an "instant"
|
|
27
|
+
claim cuts hot). Silence and pauses are rhetoric, not absence.
|
|
28
|
+
- **Pacing** — the cut rhythm IS part of the argument; it may defy
|
|
29
|
+
platform convention when the claim demands it.
|
|
30
|
+
- **Type/cards** — copy advances the argument; the tagline lands as the
|
|
31
|
+
CONCLUSION the beats have earned, never as a caption.
|
|
32
|
+
- **Review prompts:** (1) beats reorderable without changing what the video
|
|
33
|
+
says; (2) any channel (bed, shot, card) that would fit a different claim
|
|
34
|
+
equally well; (3) a viewer who watched it cannot state the claim.
|
|
35
|
+
|
|
36
|
+
## Cross-cutting rules (every artifact)
|
|
37
|
+
|
|
38
|
+
These are final-artifact criteria, not a requirement to re-plan or export after every tweak.
|
|
39
|
+
For scoped corrections and preview selection, use `cueframe-compose-loop`'s
|
|
40
|
+
[preview workflow](../../cueframe-compose-loop/references/preview-workflow.md). Inspect continuous
|
|
41
|
+
motion and listen to affected audio, not only stills or judge scores. Keep the user's explicit
|
|
42
|
+
scope and acceptance criteria; approved simulated UI is not evidence of a real product capture.
|
|
43
|
+
|
|
44
|
+
- **DEFAULT** Brand/text graphics are AUTHORED — `kind:"card"` HTML (your
|
|
45
|
+
typography, layout, palette-as-fields) animated in CSS or with `clip.setKeyframes`,
|
|
46
|
+
or a native component (`create_component`). Catalog text primitives are for utility only.
|
|
47
|
+
**Consider:** a brand graphic rendered from a catalog text primitive.
|
|
48
|
+
- **DEFAULT** Audio is decided, never defaulted: a music bed (curated packs via
|
|
49
|
+
`import_resource {kind:"music-pack"}`) or ambience/loops (Freesound via
|
|
50
|
+
`search_resources kind:"sfx"`), honoring the brand kit's `musicMood`;
|
|
51
|
+
cut to the beat via `materializeGrid` when the bed drives pacing — OR an
|
|
52
|
+
explicit intentional-silence decision recorded in your delivery note with
|
|
53
|
+
the reason. **Consider:** a render whose silence nobody chose.
|
|
54
|
+
- **DEFAULT** Footage carries the video: real footage / real UI / real data
|
|
55
|
+
≥60% of runtime for footage-first classes. Typography-only work is a valid requested format.
|
|
56
|
+
- **DEFAULT** Every stock asset's provenance is recorded (provider, id, author).
|
|
57
|
+
- **DEFAULT** Safe-area respected: no critical copy in the outer ~8% of frame.
|
|
58
|
+
- **DEFAULT** One final render per approval; iterate with previews, not renders.
|
|
59
|
+
- **DEFAULT** Delivery never ends with "done": the last message carries the
|
|
60
|
+
output link and where to find it, plus the intentional-silence note if any.
|
|
61
|
+
|
|
62
|
+
## 1. Social reel — 9:16 · 8–30s
|
|
63
|
+
|
|
64
|
+
- **DEFAULT** The hook lands inside 2 seconds: the strongest image, motion,
|
|
65
|
+
or claim opens the piece. No logo-first cold opens, no fade-in-from-black
|
|
66
|
+
preambles.
|
|
67
|
+
- **DEFAULT** Typography is poster-grade: composed plates/fields in the brand
|
|
68
|
+
palette, considered alignment and scale. **Consider:** centered white text
|
|
69
|
+
floating on footage.
|
|
70
|
+
- **DEFAULT** Pacing is cut-driven: a new visual beat at least every ~4s; static
|
|
71
|
+
holds >4s need motion inside the frame (reframe push, kenBurns, animated
|
|
72
|
+
card) or they die.
|
|
73
|
+
- **DEFAULT** Ends on a deliberate beat: tagline, logo, or CTA lockup — not a
|
|
74
|
+
clip running out.
|
|
75
|
+
- **SHOULD** Cuts land on the music grid when a bed exists.
|
|
76
|
+
|
|
77
|
+
## 2. Launch film / feature announcement — 16:9 · 30–90s
|
|
78
|
+
|
|
79
|
+
- **DEFAULT** Payoff-first hook: the OUTCOME, not the feature name
|
|
80
|
+
("Close the books two days faster" beats "Introducing the reconciliation
|
|
81
|
+
module"). No throat-clearing ("in this video we're going to…").
|
|
82
|
+
- **DEFAULT** Narration or a bed that builds toward the reveal; pacing tightens
|
|
83
|
+
as the payoff approaches.
|
|
84
|
+
- **DEFAULT** Real product surface: actual UI/screens/output — never mocked.
|
|
85
|
+
- **DEFAULT** End card with a single CTA.
|
|
86
|
+
- **DEFAULT** Captions present when narrated.
|
|
87
|
+
|
|
88
|
+
## 3. Brand-identity reel — 9:16 · 12–20s (the showcase class)
|
|
89
|
+
|
|
90
|
+
Everything in §1, plus:
|
|
91
|
+
- **DEFAULT** Three-beat arc: opening brand moment (wordmark treatment) →
|
|
92
|
+
middle craft/proof beat (the subject's world, with an editorial device —
|
|
93
|
+
numbered chapter, pull-quote, stat) → closing tagline lockup.
|
|
94
|
+
- **DEFAULT** Every graphic is bespoke to the brand: its type, its palette as
|
|
95
|
+
fields, its layout system. **Consider:** any layout that would look correct with
|
|
96
|
+
another brand's hex swapped in.
|
|
97
|
+
- **DEFAULT** Footage color and brand palette agree — grade toward the palette
|
|
98
|
+
or choose footage that lives in it.
|
|
99
|
+
|
|
100
|
+
## 4. Talking-head clip — any aspect · 15–60s
|
|
101
|
+
|
|
102
|
+
- **DEFAULT** Hook = the strongest sentence, first. Cut TO the moment;
|
|
103
|
+
never open on wind-up.
|
|
104
|
+
- **DEFAULT** Active-speaker reframe (`focus: active-speaker` / `face`) — a
|
|
105
|
+
moving camera, not a static center crop.
|
|
106
|
+
- **DEFAULT** Captions timed to the saved edited timeline (`captions.fromComposition`
|
|
107
|
+
after the clip edits; re-run after later edits). Speech clips must have saved duration matching playable source duration divided by
|
|
108
|
+
playbackRate.
|
|
109
|
+
The focused behind-the-speaker LOOK is an overlay text layer at
|
|
110
|
+
`zPlane:"behind-subject"` where the footage allows. Use caption-layer
|
|
111
|
+
`zPlane:"behind-subject"` only when the user explicitly wants every running
|
|
112
|
+
caption behind the speaker and the legibility gate accepts it.
|
|
113
|
+
- **DEFAULT** Dead air and false starts cut (`addExcludedRange` /
|
|
114
|
+
`cutAndRipple`).
|
|
115
|
+
|
|
116
|
+
## Scoring discipline
|
|
117
|
+
|
|
118
|
+
Check the requested criteria against appropriate real evidence: affected stills, continuous motion and audio when relevant. Broader review can use `score_composition` when useful and within budget; it is not mandatory for a scoped correction. The hosted judge includes a fixed caption criterion and can penalize intentionally uncaptioned work; do not add captions solely to improve that score. These skill changes do not change judge behavior. Failed user acceptance criteria remain failures regardless of score. Stop and report remaining gaps after two passes without improvement; export only for requested final delivery.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cueframe",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.3",
|
|
4
4
|
"description": "CueFrame video editing CLI: manage media, edit compositions and render MP4s from terminals and scripts.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cueframe",
|
|
@@ -33,20 +33,21 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"add-mcp": "^2.4.0",
|
|
36
|
-
"better-auth": "1.
|
|
37
|
-
"commander": "^
|
|
38
|
-
"open": "^
|
|
39
|
-
"ora": "^
|
|
36
|
+
"better-auth": "1.7.7",
|
|
37
|
+
"commander": "^15.0.0",
|
|
38
|
+
"open": "^11.0.4",
|
|
39
|
+
"ora": "^9.4.1",
|
|
40
40
|
"pino": "^10.3.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"zod": "^4.
|
|
44
|
-
"@types/node": "^
|
|
43
|
+
"zod": "^4.6.7",
|
|
44
|
+
"@types/node": "^26.6.5",
|
|
45
45
|
"tsup": "^8.5.1",
|
|
46
|
-
"typescript": "
|
|
47
|
-
"vitest": "^
|
|
48
|
-
"@
|
|
49
|
-
"@cueframe/
|
|
46
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
47
|
+
"vitest": "^5.0.3",
|
|
48
|
+
"@typescript/native": "npm:typescript@^7.0.2",
|
|
49
|
+
"@cueframe/sdk": "^0.16.1",
|
|
50
|
+
"@cueframe/skills": "0.4.5"
|
|
50
51
|
},
|
|
51
52
|
"repository": {
|
|
52
53
|
"type": "git",
|
package/dist/analyze-XP2BESVX.js
DELETED
package/dist/chunk-RSOHINDT.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import{a as y}from"./chunk-3QSA3EBY.js";var u=class extends Error{status;code;details;requestId;constructor(t,r,n){super(r.message),this.name="ApiError",this.status=t,this.code=r.code,this.details=r.details,this.requestId=n}},v=class extends Error{url;timeoutMs;constructor(t,r){super(`Request timed out after ${r}ms: ${t}`),this.name="TimeoutError",this.url=t,this.timeoutMs=r}},q=class extends Error{url;constructor(t,r){super(`Request failed before a response: ${t}`,{cause:r}),this.name="NetworkError",this.url=t}},g={baseUrl:""};function O(e){return g={timeoutMs:3e4,...e},g}function I(){return g}function pt(e,t){return/^https?:\/\//.test(t)?t:e.replace(/\/$/,"")+(t.startsWith("/")?t:`/${t}`)}async function N(e,t={}){if(!g.baseUrl)throw new Error("@cueframe/sdk: createClient({baseUrl}) must be called before issuing requests.");let r=g.fetch??fetch,n=pt(g.baseUrl,e),o=new Headers({accept:"application/json"});for(let[c,d]of Object.entries(g.headers??{}))o.set(c,d);t.headers&&new Headers(t.headers).forEach((c,d)=>o.set(d,c)),g.apiKey&&!o.has("authorization")&&o.set("authorization",`Bearer ${g.apiKey}`);let s=g.timeoutMs??3e4,i=new AbortController,p=setTimeout(()=>i.abort(),s),m=t.signal?AbortSignal.any([t.signal,i.signal]):i.signal;try{let c=await r(n,{...t,headers:o,signal:m}),d={};c.headers.forEach((b,x)=>{d[x.toLowerCase()]=b});let l=null;if(c.status!==204)if((c.headers.get("content-type")??"").includes("application/json"))try{l=await c.json()}catch{l=null}else l=await c.text();return{status:c.status,statusText:c.statusText,headers:d,body:l,requestId:d["x-request-id"]}}catch(c){throw t.signal?.aborted?c:i.signal.aborted?new v(n,s):new q(n,c)}finally{clearTimeout(p)}}async function a(e,t={}){let r=await N(e,t);if(r.status>=400){let n;throw r.body&&typeof r.body=="object"&&"error"in r.body?n=r.body.error??{code:"unknown",message:r.statusText}:n={code:"unknown",message:r.statusText},new u(r.status,n,r.requestId)}if(r.status!==204)return r.body}var ct={unauthorized:"The credential is invalid or expired for this target, or it belongs to a different environment. Re-authenticate the way you connected: reconnect the MCP server, run `cueframe login` in a terminal, or supply a current API key.",forbidden:"The credential's permissions don't cover this operation. The server message above names the exact missing ones and the `permissions` body that grants them; a key's permissions are fixed at creation, so this needs a NEW key, not a change to this one.",not_found:"No such resource in this org (cross-org access also reads as 404). Check the id, or enumerate with the matching list command/tool.",media_not_ready:"Media is still processing. Wait for the `media.transcribed` webhook or retry after ~30s.",suggestions_already_complete:"Suggestions already exist for this media item. To re-run, call DELETE /v1/media/:id/suggestions first to reset state.",precondition_required:"Fetch the resource with GET first to obtain its ETag, then resend the write with `If-Match: <etag>`. `cueframe composition get` returns one for you.",stale_etag:"Resource was modified since your last GET \u2014 `details.currentEtag` is the value to thread next. Re-GET (or run `cueframe composition get`) and rebase your edits before retrying.",conflict:"ETag mismatch \u2014 the resource was modified since your last GET. Re-fetch and merge before retrying.",media_in_use:"Media is referenced by other resources. See `details.projectIds` and `details.sessionIds` \u2014 remove those references before deleting.",session_in_use:"Session is referenced by a composition. See `details.projectIds` \u2014 remove those references before deleting.",render_not_cancellable:"Render is already in a terminal state (complete / error / cancelled) and cannot be cancelled.",rate_limited:"Rate limit exceeded. Back off using the `retry-after` response header.",invalid_composition:"Composition violates an invariant (see `details`). Common ones: clip_source_track_kind_mismatch, track_clips_overlap, transition_no_predecessor.",clip_not_found:"The clip suggestion publicId doesn't exist in this org. Run `cueframe clips <mediaItemId>` to enumerate valid sug_* ids.",service_unavailable:"The processing pipeline is temporarily unavailable. Retry shortly; if it persists, contact support@cueframe.ai with the requestId.",payment_required:"The request exceeds a billing limit. For generation, the estimated cost is over the per-call ceiling (see `details.estimateUsd` / `details.ceilingUsd`) \u2014 lower the requested duration or raise the ceiling."};function j(e){return e instanceof u?ct[e.code]??null:null}async function*dt(e,t,r){let n=I();if(!n?.baseUrl)throw new Error(`@cueframe/sdk: createClient({baseUrl}) must be called before ${t}.`);let o=n.baseUrl.replace(/\/$/,"")+e,s=new Headers({accept:"text/event-stream",...n.headers??{}});n.apiKey&&!s.has("authorization")&&s.set("authorization",`Bearer ${n.apiKey}`);let p=await(n.fetch??fetch)(o,{method:"GET",headers:s,signal:r.signal});if(!p.ok){let l;try{l=(await p.json()).error??{code:"unknown",message:p.statusText}}catch{l={code:"unknown",message:p.statusText}}throw new u(p.status,l,p.headers.get("x-request-id")??void 0)}if(!p.body)throw new Error("SSE response has no body");let m=p.body.getReader(),c=new TextDecoder("utf-8"),d="";try{for(;;){let{value:l,done:b}=await m.read();if(b)break;d+=c.decode(l,{stream:!0});let x=d.indexOf(`
|
|
3
|
-
|
|
4
|
-
`);for(;x!==-1;){let at=d.slice(0,x);d=d.slice(x+2);let B=ft(at);B&&(yield B),x=d.indexOf(`
|
|
5
|
-
|
|
6
|
-
`)}}}finally{try{m.releaseLock()}catch{}}}function ft(e){if(!e.trim())return null;let t=null,r=[];for(let n of e.split(`
|
|
7
|
-
`)){if(!n||n.startsWith(":"))continue;let o=n.indexOf(":");if(o===-1)continue;let s=n.slice(0,o),i=n.slice(o+1).replace(/^ /,"");s==="event"?t=i:s==="data"&&r.push(i)}return!t||r.length===0?null:{event:t,data:r.join(`
|
|
8
|
-
`)}}async function*mt(e,t,r={}){let n=`/v1/projects/${encodeURIComponent(e)}/renders/${encodeURIComponent(t)}/stream`;for await(let o of dt(n,"iterRenderEvents",r)){let s=ut(o);s&&(yield s)}}function ut(e){let{event:t,data:r}=e;if(r===null||t!=="progress"&&t!=="complete"&&t!=="error")return null;let n;try{n=JSON.parse(r)}catch{return null}return{event:t,data:n}}var P={};y(P,{composeFromSuggestion:()=>bt,getComposeFromSuggestionUrl:()=>L,getListMediaSuggestionsUrl:()=>G,getResetMediaSuggestionsUrl:()=>F,getSuggestBriefsUrl:()=>$,listMediaSuggestions:()=>Pt,resetMediaSuggestions:()=>ht,suggestBriefs:()=>St});var L=e=>`/v1/projects/${e}/composition/from-suggestion`,bt=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(L(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},G=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/media/${e}/suggestions?${n}`:`/v1/media/${e}/suggestions`},Pt=async(e,t,r)=>a(G(e,t),{...r,method:"GET"}),$=e=>`/v1/media/${e}/suggestions`,St=async(e,t)=>a($(e),{...t,method:"POST"}),F=e=>`/v1/media/${e}/suggestions`,ht=async(e,t)=>a(F(e),{...t,method:"DELETE"});var Z={};y(Z,{createComponent:()=>Tt,getBlankComponentSource:()=>qt,getComponent:()=>jt,getComponentSource:()=>At,getCreateComponentUrl:()=>V,getGetBlankComponentSourceUrl:()=>J,getGetComponentSourceUrl:()=>Y,getGetComponentUrl:()=>X,getListCatalogUrl:()=>D,getPatchComponentUrl:()=>z,getRepinComponentUrl:()=>_,getResolveBuiltinComponentUrl:()=>H,getUpdateComponentUrl:()=>W,listCatalog:()=>kt,patchComponent:()=>It,repinComponent:()=>vt,resolveBuiltinComponent:()=>Et,updateComponent:()=>Ot});var _=e=>`/v1/projects/${e}/components/native-upgrade`,vt=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(_(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},J=()=>"/v1/components/blank-source",qt=async e=>a(J(),{...e,method:"GET"}),H=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/components/builtin/resolve?${r}`:"/v1/components/builtin/resolve"},Et=async(e,t)=>a(H(e),{...t,method:"GET"}),D=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/components?${r}`:"/v1/components"},kt=async(e,t)=>a(D(e),{...t,method:"GET"}),V=()=>"/v1/components",Tt=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(V(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},W=e=>`/v1/components/${e}`,Ot=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(W(e),{...r,method:"PUT",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},z=e=>`/v1/components/${e}`,It=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(z(e),{...r,method:"PATCH",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},X=e=>`/v1/components/${e}`,jt=async(e,t)=>a(X(e),{...t,method:"GET"}),Y=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/components/${e}/source?${n}`:`/v1/components/${e}/source`},At=async(e,t,r)=>a(Y(e,t),{...r,method:"GET"});var oe={};y(oe,{cancelExport:()=>_t,createFcpxmlExport:()=>Gt,createPremiereExport:()=>$t,getCancelExportUrl:()=>re,getCreateFcpxmlExportUrl:()=>Q,getCreatePremiereExportUrl:()=>ee,getExport:()=>Ft,getGetExportUrl:()=>te});var Q=e=>`/v1/projects/${e}/exports/fcpxml`,Gt=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(Q(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},ee=e=>`/v1/projects/${e}/exports/premiere`,$t=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(ee(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},te=(e,t)=>`/v1/projects/${e}/exports/${t}`,Ft=async(e,t,r)=>a(te(e,t),{...r,method:"GET"}),re=(e,t)=>`/v1/projects/${e}/exports/${t}/cancel`,_t=async(e,t,r)=>a(re(e,t),{...r,method:"POST"});var Ee={};y(Ee,{analyzeTimeline:()=>lr,analyzeTranscript:()=>ur,cancelHostedProcessingRun:()=>Yt,createMediaUpload:()=>Qt,createUploadToken:()=>Zt,deleteMedia:()=>nr,finalizeMedia:()=>tr,generateMedia:()=>rr,getAnalyzeTimelineUrl:()=>qe,getAnalyzeTranscriptUrl:()=>ve,getCancelHostedProcessingRunUrl:()=>pe,getCreateMediaUploadUrl:()=>de,getCreateUploadTokenUrl:()=>ce,getDeleteMediaUrl:()=>ge,getFinalizeMediaUrl:()=>me,getGenerateMediaUrl:()=>ue,getGetHostedProcessingArtifactUrl:()=>ae,getGetHostedProcessingRunUrl:()=>ie,getGetMediaContextUrl:()=>Ce,getGetMediaDownloadUrlUrl:()=>xe,getGetMediaTranscriptUrl:()=>Re,getGetMediaUrl:()=>ye,getHostedProcessingArtifact:()=>Xt,getHostedProcessingRun:()=>zt,getImportMediaUrl:()=>le,getListMediaFactsUrl:()=>Se,getListMediaUrl:()=>fe,getMedia:()=>sr,getMediaContext:()=>pr,getMediaDownloadUrl:()=>ir,getMediaTranscript:()=>ar,getPurchaseMediaFactUrl:()=>he,getSearchLibraryUrl:()=>ne,getStartHostedProcessingRunUrl:()=>se,getTriggerMatteBakeUrl:()=>Pe,getTriggerSubjectDetectionUrl:()=>be,importMedia:()=>or,listMedia:()=>er,listMediaFacts:()=>fr,purchaseMediaFact:()=>mr,searchLibrary:()=>Vt,startHostedProcessingRun:()=>Wt,triggerMatteBake:()=>dr,triggerSubjectDetection:()=>cr});var ne=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{let s=["mediaId"];if(Array.isArray(o)&&s.includes(n)){o.forEach(i=>{t.append(n,i===null?"null":String(i))});return}o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/media/search?${r}`:"/v1/media/search"},Vt=async(e,t)=>a(ne(e),{...t,method:"GET"}),se=e=>`/v1/media/${e}/processing-runs`,Wt=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(se(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},ie=(e,t)=>`/v1/media/${e}/processing-runs/${t}`,zt=async(e,t,r)=>a(ie(e,t),{...r,method:"GET"}),ae=(e,t,r)=>`/v1/media/${e}/processing-runs/${t}/artifacts/${r}`,Xt=async(e,t,r,n)=>a(ae(e,t,r),{...n,method:"GET"}),pe=(e,t)=>`/v1/media/${e}/processing-runs/${t}/cancel`,Yt=async(e,t,r)=>a(pe(e,t),{...r,method:"POST"}),ce=()=>"/v1/uploads/token",Zt=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(ce(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},de=()=>"/v1/media",Qt=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(de(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},fe=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/media?${r}`:"/v1/media"},er=async(e,t)=>a(fe(e),{...t,method:"GET"}),me=e=>`/v1/media/${e}/finalize`,tr=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(me(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},ue=()=>"/v1/media/generate",rr=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(ue(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},le=()=>"/v1/media/import",or=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(le(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},ge=e=>`/v1/media/${e}`,nr=async(e,t)=>a(ge(e),{...t,method:"DELETE"}),ye=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/media/${e}?${n}`:`/v1/media/${e}`},sr=async(e,t,r)=>a(ye(e,t),{...r,method:"GET"}),xe=e=>`/v1/media/${e}/download-url`,ir=async(e,t)=>a(xe(e),{...t,method:"GET"}),Re=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/media/${e}/transcript?${n}`:`/v1/media/${e}/transcript`},ar=async(e,t,r)=>a(Re(e,t),{...r,method:"GET"}),Ce=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/media/${e}/context?${n}`:`/v1/media/${e}/context`},pr=async(e,t,r)=>a(Ce(e,t),{...r,method:"GET"}),be=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/media/${e}/detect-subjects?${n}`:`/v1/media/${e}/detect-subjects`},cr=async(e,t,r)=>a(be(e,t),{...r,method:"POST"}),Pe=e=>`/v1/media/${e}/matte`,dr=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(Pe(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},Se=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/media/${e}/facts?${n}`:`/v1/media/${e}/facts`},fr=async(e,t,r)=>a(Se(e,t),{...r,method:"GET"}),he=e=>`/v1/media/${e}/facts`,mr=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(he(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},ve=e=>`/v1/media/${e}/transcript/analyze`,ur=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(ve(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},qe=()=>"/v1/timeline-analysis",lr=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(qe(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})};var we={};y(we,{createProject:()=>yr,deleteProject:()=>Cr,getCreateProjectUrl:()=>Te,getDeleteProjectUrl:()=>je,getGetProjectContextUrl:()=>Ae,getGetProjectUrl:()=>Oe,getListProjectsUrl:()=>ke,getPatchProjectUrl:()=>Ie,getProject:()=>xr,getProjectContext:()=>br,listProjects:()=>gr,patchProject:()=>Rr});var ke=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/projects?${r}`:"/v1/projects"},gr=async(e,t)=>a(ke(e),{...t,method:"GET"}),Te=()=>"/v1/projects",yr=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(Te(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},Oe=e=>`/v1/projects/${e}`,xr=async(e,t)=>a(Oe(e),{...t,method:"GET"}),Ie=e=>`/v1/projects/${e}`,Rr=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(Ie(e),{...r,method:"PATCH",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},je=e=>`/v1/projects/${e}`,Cr=async(e,t)=>a(je(e),{...t,method:"DELETE"}),Ae=e=>`/v1/projects/${e}/context`,br=async(e,t)=>a(Ae(e),{...t,method:"GET"});var Fe={};y(Fe,{cancelRender:()=>qr,createRender:()=>Pr,getCancelRenderUrl:()=>Ne,getCreateRenderUrl:()=>Me,getGetRenderUrl:()=>Be,getListProjectRendersUrl:()=>Ue,getPreviewClipUrl:()=>Ke,getRefreshRenderUrlUrl:()=>Ge,getRender:()=>vr,getRetryRenderUrl:()=>Le,getStreamRenderUrl:()=>$e,listProjectRenders:()=>Sr,previewClip:()=>hr,refreshRenderUrl:()=>kr,retryRender:()=>Er,streamRender:()=>Tr});var Me=e=>`/v1/projects/${e}/renders`,Pr=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(Me(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},Ue=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/projects/${e}/renders?${n}`:`/v1/projects/${e}/renders`},Sr=async(e,t,r)=>a(Ue(e,t),{...r,method:"GET"}),Ke=e=>`/v1/projects/${e}/preview-clip`,hr=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(Ke(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},Be=(e,t)=>`/v1/projects/${e}/renders/${t}`,vr=async(e,t,r)=>a(Be(e,t),{...r,method:"GET"}),Ne=(e,t)=>`/v1/projects/${e}/renders/${t}/cancel`,qr=async(e,t,r)=>a(Ne(e,t),{...r,method:"POST"}),Le=(e,t)=>`/v1/projects/${e}/renders/${t}/retry`,Er=async(e,t,r)=>a(Le(e,t),{...r,method:"POST"}),Ge=(e,t)=>`/v1/projects/${e}/renders/${t}/refresh-url`,kr=async(e,t,r)=>a(Ge(e,t),{...r,method:"POST"}),$e=(e,t)=>`/v1/projects/${e}/renders/${t}/stream`,Tr=async(e,t,r)=>a($e(e,t),{...r,method:"GET"});var Xe={};y(Xe,{cancelMuxJob:()=>Br,createSession:()=>Ar,deleteSession:()=>Mr,getCancelMuxJobUrl:()=>ze,getCreateSessionUrl:()=>Je,getDeleteSessionUrl:()=>De,getGetMuxJobUrl:()=>We,getGetSessionUrl:()=>He,getListSessionsUrl:()=>_e,getMuxJob:()=>Kr,getSession:()=>wr,getTriggerMuxJobUrl:()=>Ve,listSessions:()=>jr,triggerMuxJob:()=>Ur});var _e=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/sessions?${r}`:"/v1/sessions"},jr=async(e,t)=>a(_e(e),{...t,method:"GET"}),Je=()=>"/v1/sessions",Ar=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(Je(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},He=e=>`/v1/sessions/${e}`,wr=async(e,t)=>a(He(e),{...t,method:"GET"}),De=e=>`/v1/sessions/${e}`,Mr=async(e,t)=>a(De(e),{...t,method:"DELETE"}),Ve=e=>`/v1/sessions/${e}/mux-job`,Ur=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(Ve(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},We=e=>`/v1/sessions/${e}/mux-job`,Kr=async(e,t)=>a(We(e),{...t,method:"GET"}),ze=e=>`/v1/sessions/${e}/mux-job/cancel`,Br=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(ze(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})};var _r=[3,4],Jr={version:4,componentId:"blank-component",template:`<template><div id="root" data-composition-id="blank-component" data-width="1920" data-height="1080" data-no-timeline data-composition-variables='[{"id":"background","type":"color","label":"Background","default":"#101014"}]'><div data-cf-scene></div></div><script>
|
|
9
|
-
const { h, MediaTileScene } = __cfScene;
|
|
10
|
-
function Blank({ params }) {
|
|
11
|
-
return h(MediaTileScene, { streams: {}, tiles: [], background: params.background ?? '#101014' });
|
|
12
|
-
}
|
|
13
|
-
__cfScene.mount({ root: document.getElementById('root'), component: Blank, variables: __hyperframes.getVariables() });
|
|
14
|
-
</script></template>`,manifest:{version:4,runtime:"hyperframes",hfContract:1,kind:"scene",assets:{},graphics:{api:"webgl2",required:!0,accelerationPreference:"software-allowed"},alphaPolicy:"allows-opaque"},definition:{inputSchema:{type:"object",additionalProperties:!1,properties:{background:{type:"string",pattern:"^#[0-9a-fA-F]{6}$",default:"#101014",title:"Background"}}},defaults:{},brandBindings:[],timing:{defaultDuration:{frames:90,fps:30}},capabilities:[{kind:"clip"}]}};var E="X-CueFrame-Client";var Hr=/^[A-Za-z0-9][A-Za-z0-9._+-]{0,31}$/,Dr=["web","console","clips"];function Vr(e,t){return Dr.includes(e)===(t==="browser")}function Ye(e){if(!Hr.test(e.version))throw new Error(`${E} cannot carry the version ${JSON.stringify(e.version)}.`);if(!Vr(e.surface,e.os))throw new Error(`${E} cannot carry ${e.surface} on ${e.os}.`);return`${e.surface}/${e.version}/${e.os}`}function Ze(e){return e==="darwin"?"macos":e==="win32"?"windows":e==="linux"?"linux":"unknown"}import{readFileSync as Wr,writeFileSync as zr,mkdirSync as Xr,existsSync as Yr}from"fs";import{join as Qe}from"path";import{homedir as Zr}from"os";var f={Success:0,UserError:2,ApiClientError:3,ApiServerError:4,NetworkError:5,PaymentRequired:6};function A(e){if(e instanceof u){if(e.status===402)return f.PaymentRequired;if(e.status>=500)return f.ApiServerError;if(e.status>=400)return f.ApiClientError}let t=e?.exitCode;return typeof t=="number"?t:f.NetworkError}function _h(e){return e===402?f.PaymentRequired:e>=500?f.ApiServerError:e>=400?f.ApiClientError:f.Success}function S(e){process.exit(e)}var et=Qe(Zr(),".cueframe"),k=Qe(et,"auth.json"),R={local:"http://127.0.0.1:3211",prod:"https://api.cueframe.ai"},Qr="prod";function zh(e=Qr){return process.env.CUEFRAME_API_URL??R[e]??R.prod}var h=class extends Error{constructor(r,n){super(n);this.code=r;this.name="AuthStoreError"}code;exitCode=f.UserError};function Xh(e){if(!/^cf_(?:live|test)_[A-Za-z0-9_-]{8,}$/.test(e))throw new h("auth_invalid","Invalid API key. Expected a key beginning with cf_live_ or cf_test_.")}function tt(){if(!Yr(k))return{targets:{}};let e=Wr(k,"utf-8");try{return JSON.parse(e)}catch{throw new h("auth_config_corrupt",`${k} is corrupt and cannot be parsed. Delete it and re-run \`cueframe login\`.`)}}function eo(e){Xr(et,{recursive:!0,mode:448}),zr(k,JSON.stringify(e,null,2),{mode:384})}function Yh(e,t="prod",r){let n=tt(),o=R[t]??R.prod;n.targets[t]={apiKey:e,apiUrl:r??o},eo(n)}function rt(e="prod"){let t=process.env.CUEFRAME_API_KEY,r=process.env.CUEFRAME_API_URL;if(t)return{apiKey:t,apiUrl:r??R[e]??R.prod};let o=tt().targets[e];if(!o)throw new h("auth_missing",`No auth configured for target "${e}". Run \`cueframe login --target ${e}\` (browser sign-in) or \`cueframe auth <api-key> --target ${e}\` (CI / headless).`);return o}function to(){return{[E]:Ye({surface:"cli",version:"0.9.4",os:Ze(process.platform)})}}function ot(e){let{apiKey:t,apiUrl:r}=rt(e);O({baseUrl:r,apiKey:t,headers:to()})}function T(e){let t=e instanceof u?`${e.message} (${e.code}${e.status?`, ${e.status}`:""})`:e instanceof Error?e.message:String(e),r=j(e);return r?`${t}
|
|
15
|
-
\u2192 ${r}`:t}import ro from"ora";import oo from"pino";var no="v1",nt=oo({level:"trace",base:{schemaVersion:no},messageKey:"event",timestamp:()=>`,"ts":${Date.now()}`,formatters:{level:()=>({_:0})}});function w(e,t){return ro({text:e,isSilent:!!t}).start()}function C(e,t,r={}){e.json&&nt.info(r,t)}function iv(e,t,r){if(e.json){console.log(JSON.stringify(t,null,2));return}r()}function M(e,t,r,n){let o=r instanceof Error?r.message:String(r),s=typeof r?.code=="string"?r.code:void 0,i=r?.status;e.json?nt.info({phase:t,message:o,...s?{code:s}:{},...typeof i=="number"?{status:i}:{},exitCode:n},"error"):process.stderr.write(`\u2716 ${t}: ${T(r)}
|
|
16
|
-
`)}function U(e,t,r,n){e.json&&M(e,t,r,n)}function av(e,t){t.json||console.log(e)}function so(e){for(let t=0;t<e.length;t++){let r=e.charCodeAt(t);if(r<=31||r===127)return!0}return!1}function it(e,t,r){e.length===0&&st(`${t} is empty.`,r),so(e)&&st(`${t} contains a control character (newline, tab, or null byte). Identifiers must be plain text \u2014 check for a stray copy-paste artifact.`,r)}function st(e,t){M(t,"preflight",new Error(e),f.UserError),S(f.UserError)}var io=5e3,K=300*1e3;async function xv(e,t){if(it(e,"mediaItemId",t),t.dryRun){C(t,"analyze_dry_run",{mediaItemId:e,target:t.target,wait:!!t.wait,wouldCall:"POST /v1/media/:id/suggestions"}),t.json||console.log(`[dry-run] Would trigger clip analysis for ${e} on ${t.target}.`);return}ot(t.target),C(t,"analyze_prepare",{mediaItemId:e,target:t.target,wait:!!t.wait});let r=w("Triggering clip analysis\u2026",t.json),n;try{n=await P.suggestBriefs(e),r.succeed(`Analysis ${n.alreadyRunning?"already running":"started"}`)}catch(i){r.fail(`Failed to start analysis: ${T(i)}`),U(t,"analyze_prepare",i,A(i)),S(A(i))}if(C(t,"analyze_ready",{mediaItemId:e,status:n.status,alreadyRunning:!!n.alreadyRunning}),!t.wait){t.json||console.log(`
|
|
17
|
-
Run \`cueframe clips ${e}\` to check results.`);return}let o=w("Waiting for analysis to complete\u2026",t.json),s=Date.now();for(;;){await new Promise(i=>setTimeout(i,io)),Date.now()-s>K&&(o.fail(`Timed out after ${Math.round(K/1e3)}s. Run \`cueframe clips ${e}\` to check later.`),U(t,"analyze_progress",new Error(`Analysis did not complete within ${Math.round(K/1e3)}s`),f.UserError),S(f.UserError));try{let i=await P.listMediaSuggestions(e);if(i.suggestions.length>0){o.succeed(`Analysis complete \u2014 ${i.suggestions.length} clips found`),C(t,"analyze_complete",{mediaItemId:e,durationMs:Date.now()-s,suggestionCount:i.suggestions.length,suggestions:i.suggestions}),t.json||i.suggestions.forEach((m,c)=>{let d=(m.trim.end-m.trim.start).toFixed(1);console.log(`
|
|
18
|
-
${c+1}. ${m.title} (${m.id})`),console.log(` ${m.trim.start.toFixed(1)}s \u2013 ${m.trim.end.toFixed(1)}s (${d}s) score: ${m.score}`),console.log(` ${m.reason}`)});return}let p=Math.round((Date.now()-s)/1e3);o.text=`Waiting for analysis\u2026 (${p}s)`,C(t,"analyze_progress",{mediaItemId:e,elapsedSec:p})}catch{}}}export{u as a,O as b,N as c,a as d,j as e,mt as f,P as g,Z as h,oe as i,Ee as j,we as k,Fe as l,Xe as m,_r as n,Jr as o,f as p,A as q,_h as r,S as s,zh as t,Xh as u,Yh as v,to as w,ot as x,T as y,w as z,C as A,iv as B,M as C,U as D,av as E,it as F,xv as G};
|