@mevdragon/vidfarm-devcli 0.20.6 → 0.20.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/.agents/skills/editor-capabilities/SKILL.md +15 -1
  2. package/.agents/skills/vidfarm-director/SKILL.md +106 -0
  3. package/.agents/skills/vidfarm-director/recipes/find-and-fork-template.md +16 -0
  4. package/.agents/skills/vidfarm-director/recipes/local-edit-render-approve.md +13 -0
  5. package/.agents/skills/vidfarm-director/recipes/onboard-a-new-director.md +13 -0
  6. package/.agents/skills/vidfarm-director/recipes/retheme-template.md +17 -0
  7. package/.agents/skills/vidfarm-director/references/assets-and-sourcing.md +111 -0
  8. package/.agents/skills/vidfarm-director/references/automation-and-local-dev.md +243 -0
  9. package/.agents/skills/vidfarm-director/references/core-workflows.md +273 -0
  10. package/.agents/skills/vidfarm-director/references/editor-workflows.md +365 -0
  11. package/.agents/skills/vidfarm-director/references/onboarding.md +28 -0
  12. package/.agents/skills/vidfarm-director/references/primitives.md +265 -0
  13. package/SKILL.director.md +476 -260
  14. package/dist/src/cli.js +362 -96
  15. package/dist/src/devcli/clips.js +15 -10
  16. package/dist/src/devcli/doctor.js +2 -2
  17. package/dist/src/devcli/local-backend.js +46 -2
  18. package/dist/src/services/clip-curation/cost.js +5 -1
  19. package/dist/src/services/clip-curation/gemini.js +10 -0
  20. package/package.json +30 -10
  21. package/SKILL.platform.md +0 -432
  22. package/demo/README.md +0 -28
  23. package/demo/dist/app.css +0 -1
  24. package/demo/dist/app.js +0 -1850
  25. package/demo/dist/chunks/chunk-DXB73IDG.js +0 -1
  26. package/demo/dist/chunks/chunk-S7OWAJDS.js +0 -36
  27. package/demo/dist/chunks/chunk-VTIBZ6AN.js +0 -1
  28. package/demo/dist/chunks/dist-ADSJKBVE.js +0 -332
  29. package/demo/dist/chunks/domEditingLayers-VZMLL4AP-SGHWPND4.js +0 -1
  30. package/demo/dist/chunks/hyperframes-player-XB65TCD6.js +0 -425
  31. package/demo/dist/chunks/lib-XAQ37YOE.js +0 -1
  32. package/demo/dist/chunks/src-TJ2QYA4U.js +0 -207
  33. package/demo/dist/favicon.ico +0 -0
  34. package/demo/dist/icons/timeline/audio.svg +0 -7
  35. package/demo/dist/icons/timeline/captions.svg +0 -5
  36. package/demo/dist/icons/timeline/composition.svg +0 -12
  37. package/demo/dist/icons/timeline/image.svg +0 -18
  38. package/demo/dist/icons/timeline/music.svg +0 -10
  39. package/demo/dist/icons/timeline/text.svg +0 -3
  40. package/demo/dist/index.html +0 -15
  41. package/dist/src/account-pages-legacy.js +0 -9396
  42. package/dist/src/account-pages.js +0 -61
  43. package/dist/src/app.js +0 -21603
  44. package/dist/src/composition-runtime.js +0 -1053
  45. package/dist/src/config.js +0 -217
  46. package/dist/src/context.js +0 -447
  47. package/dist/src/dev-app-legacy.js +0 -739
  48. package/dist/src/dev-app.js +0 -6
  49. package/dist/src/devcli/migrate-local.js +0 -140
  50. package/dist/src/devcli/sync.js +0 -368
  51. package/dist/src/domain.js +0 -5
  52. package/dist/src/editor-chat-history.js +0 -82
  53. package/dist/src/editor-chat.js +0 -828
  54. package/dist/src/editor-dark-theme.js +0 -1128
  55. package/dist/src/frontend/debug.js +0 -71
  56. package/dist/src/frontend/discover-client.js +0 -130
  57. package/dist/src/frontend/discover-store.js +0 -23
  58. package/dist/src/frontend/file-directory.js +0 -1018
  59. package/dist/src/frontend/flockposter-cache-store.js +0 -124
  60. package/dist/src/frontend/homepage-client.js +0 -446
  61. package/dist/src/frontend/homepage-shared.js +0 -201
  62. package/dist/src/frontend/homepage-store.js +0 -66
  63. package/dist/src/frontend/homepage-view.js +0 -705
  64. package/dist/src/frontend/page-runtime-client.js +0 -132
  65. package/dist/src/frontend/page-runtime-store.js +0 -9
  66. package/dist/src/frontend/sentry.js +0 -42
  67. package/dist/src/frontend/template-editor-chat.js +0 -4181
  68. package/dist/src/help-page.js +0 -346
  69. package/dist/src/homepage.js +0 -1458
  70. package/dist/src/index.js +0 -16
  71. package/dist/src/instrument.js +0 -30
  72. package/dist/src/landing-page.js +0 -384
  73. package/dist/src/page-runtime.js +0 -2
  74. package/dist/src/page-shell.js +0 -1452
  75. package/dist/src/primitive-context.js +0 -416
  76. package/dist/src/primitive-registry.js +0 -3940
  77. package/dist/src/primitive-sdk.js +0 -4
  78. package/dist/src/primitives/hyperframes-media.js +0 -108
  79. package/dist/src/react-page-shell.js +0 -35
  80. package/dist/src/ready-post-schedule-component.js +0 -1540
  81. package/dist/src/registry.js +0 -296
  82. package/dist/src/reskin/agency-page.js +0 -299
  83. package/dist/src/reskin/calendar-page.js +0 -568
  84. package/dist/src/reskin/chat-page.js +0 -942
  85. package/dist/src/reskin/discover-page.js +0 -1788
  86. package/dist/src/reskin/document.js +0 -1587
  87. package/dist/src/reskin/help-page.js +0 -357
  88. package/dist/src/reskin/index-page.js +0 -62
  89. package/dist/src/reskin/inpaint-clipper-page.js +0 -890
  90. package/dist/src/reskin/inpaint-page.js +0 -2554
  91. package/dist/src/reskin/inpaint-video-page.js +0 -1339
  92. package/dist/src/reskin/job-runs-page.js +0 -477
  93. package/dist/src/reskin/library-page.js +0 -1634
  94. package/dist/src/reskin/login-page.js +0 -262
  95. package/dist/src/reskin/portfolio-page.js +0 -687
  96. package/dist/src/reskin/pricing-page.js +0 -390
  97. package/dist/src/reskin/settings-page.js +0 -732
  98. package/dist/src/reskin/theme.js +0 -711
  99. package/dist/src/runtime.js +0 -35
  100. package/dist/src/services/api-call-history.js +0 -249
  101. package/dist/src/services/auth.js +0 -152
  102. package/dist/src/services/billing-pricing.js +0 -39
  103. package/dist/src/services/billing.js +0 -241
  104. package/dist/src/services/cast.js +0 -127
  105. package/dist/src/services/chat-threads.js +0 -92
  106. package/dist/src/services/clip-records.js +0 -250
  107. package/dist/src/services/clip-search.js +0 -77
  108. package/dist/src/services/clip-vectors.js +0 -125
  109. package/dist/src/services/composition-sanitize.js +0 -124
  110. package/dist/src/services/composition-watch.js +0 -79
  111. package/dist/src/services/elevenlabs.js +0 -222
  112. package/dist/src/services/file-directory.js +0 -117
  113. package/dist/src/services/fork-access.js +0 -93
  114. package/dist/src/services/fork-manifest.js +0 -42
  115. package/dist/src/services/ghostcut.js +0 -179
  116. package/dist/src/services/hyperframes.js +0 -3654
  117. package/dist/src/services/job-capacity.js +0 -14
  118. package/dist/src/services/job-logs.js +0 -197
  119. package/dist/src/services/jobs.js +0 -136
  120. package/dist/src/services/local-dynamo.js +0 -0
  121. package/dist/src/services/media-processing.js +0 -766
  122. package/dist/src/services/primitive-media-lambda.js +0 -280
  123. package/dist/src/services/providers.js +0 -2748
  124. package/dist/src/services/rate-limits.js +0 -262
  125. package/dist/src/services/scene-annotations.js +0 -32
  126. package/dist/src/services/serverless-auth.js +0 -382
  127. package/dist/src/services/serverless-jobs.js +0 -1084
  128. package/dist/src/services/serverless-provider-keys.js +0 -409
  129. package/dist/src/services/serverless-records.js +0 -1515
  130. package/dist/src/services/serverless-template-configs.js +0 -75
  131. package/dist/src/services/storage.js +0 -461
  132. package/dist/src/services/swipe-customize.js +0 -437
  133. package/dist/src/services/template-certification.js +0 -413
  134. package/dist/src/services/template-loader.js +0 -99
  135. package/dist/src/services/template-runtime-bundles.js +0 -217
  136. package/dist/src/services/template-sources.js +0 -1017
  137. package/dist/src/services/upstream.js +0 -248
  138. package/dist/src/services/video-normalization.js +0 -2
  139. package/dist/src/services/webhooks.js +0 -62
  140. package/dist/src/template-editor-pages.js +0 -2576
  141. package/dist/src/template-editor-shell.js +0 -2893
  142. package/dist/src/template-sdk.js +0 -4
  143. package/dist/src/worker.js +0 -17
  144. package/public/assets/discover-client-app.js +0 -1
  145. package/public/assets/file-directory-app.js +0 -3
  146. package/public/assets/homepage-app.js +0 -54
  147. package/public/assets/homepage-client-app.js +0 -80
  148. package/public/assets/page-runtime-client-app.js +0 -94
  149. package/public/assets/placeholders/scene-placeholder.png +0 -0
  150. package/src/assets/SELLING_AWARENESS_STAGES.md +0 -579
  151. package/src/assets/SELLING_WITH_HOOKS.md +0 -377
  152. package/src/assets/SELLING_WITH_VSLS.md +0 -606
  153. package/src/assets/favicon.ico +0 -0
  154. package/src/assets/logo-vidfarm.png +0 -0
@@ -0,0 +1,265 @@
1
+ ## Primitive: image_remove_background
2
+
3
+ Remove the background from any image URL. Result is a transparent PNG/WebP stored at a durable Vidfarm URL you can reuse in compositions or downstream primitives.
4
+
5
+ - `POST /api/v1/primitives/images/remove-background`
6
+ - Body: `{ "source_image_url": "https://...", "output_format": "webp" | "png" | "jpeg" }` (`output_format` defaults to `webp`)
7
+ - Response: standard primitive job; poll for completion, then read `image.file_url` / `primary_file_url`
8
+ - Billing: flat pass-through fee via RapidAPI (`rapidapi_remove_background` cost center)
9
+ - Reach for this only for an **arbitrary photo with a messy background**. If the image already sits on a **flat solid background** (anything you generated on a controlled backdrop), use the far cheaper `image_remove_background_greenscreen` below instead.
10
+
11
+ Example:
12
+
13
+ ```bash
14
+ curl -X POST "$VIDFARM_BASE/api/v1/primitives/images/remove-background" \
15
+ -H "vidfarm-api-key: $VIDFARM_API_KEY" \
16
+ -H "content-type: application/json" \
17
+ -d '{"source_image_url": "https://cdn.example.com/photo.jpg"}'
18
+ ```
19
+
20
+ ## Primitive: image_remove_background_greenscreen
21
+
22
+ Cheap **local chroma-key** background removal — no third-party API, just `sharp` doing per-pixel color-distance keying, so it costs a fraction of `image_remove_background`. Use it whenever the source sits on a **flat, solid, evenly-lit background**: a green screen, or any single fill color you pass via `key_color` (e.g. `#FFFFFF` for a white background, `#0047BB` for blue). The result is a transparent PNG/WebP at a durable Vidfarm URL.
23
+
24
+ - `POST /api/v1/primitives/images/remove-background-greenscreen` (flat alias: `POST /api/v1/primitives/remove-background-greenscreen`)
25
+ - Body: `{ "tracer": "...", "payload": { "source_image_url": "https://...", "key_color"?: "#00FF00", "tolerance"?: 0.3, "softness"?: 0.1, "despill"?: true, "output_format"?: "png" | "webp" }, "webhook_url"?: "..." }`
26
+ - `key_color` — the background color to key out (hex / `rgb(...)` / named `green`/`white`/`blue`/`black`). Default `#00FF00`.
27
+ - `tolerance` (0–1, default `0.3`) — how close a pixel must be to `key_color` to be removed. Raise it if fringe survives, lower it if the subject is being eaten.
28
+ - `softness` (0–1, default `0.1`) — feather band beyond `tolerance` for anti-aliased edges.
29
+ - `despill` (default `true`) — suppresses the residual key-color rim on the subject's edges (only applied for chromatic keys like green/blue).
30
+ - Response: standard primitive job; poll for completion, then read `image.file_url` / `primary_file_url`. `keyed_fraction` in the output tells you what share of pixels were removed (near-0 usually means the wrong `key_color` or too-low `tolerance`).
31
+ - Billing: small compute-only wallet fee (`greenscreen_chroma_key` cost center) — cheaper than the RapidAPI route.
32
+
33
+ ## Primitive: media_overlay ("create media overlay" — Vox-style)
34
+
35
+ **The go-to way to mint a transparent overlay graphic to float over a composition.** So-called "Vox-style" animations are really just AI-generated illustrations with transparent backgrounds animated in HTML over the timeline — this primitive is that two-step process fused into one job: it (1) generates an AI image of your subject on a **forced flat key-color background** (using the caller's own BYOK image keys, with the greenscreen instruction injected into the prompt automatically) and (2) chroma-keys that background out, returning a ready-to-composite transparent PNG/WebP. **Prefer this over generate-then-manually-remove**, and reach for it *frequently* whenever a scene wants a floating illustration, prop, icon, sticker, or cut-out character.
36
+
37
+ - `POST /api/v1/primitives/images/create-overlay` (flat alias: `POST /api/v1/primitives/create-media-overlay`)
38
+ - Body: `{ "tracer": "...", "payload": { "prompt": "a cartoon rocket ship, flat vector illustration", "provider"?: "...", "model"?: "...", "prompt_attachments"?: ["https://..."], "aspect_ratio"?: "1:1", "image_size"?: "1K"|"2K"|"4K", "key_color"?: "#00FF00", "tolerance"?: 0.3, "softness"?: 0.1, "despill"?: true, "output_format"?: "png"|"webp" }, "webhook_url"?: "..." }`
39
+ - Just describe the **subject** in `prompt` — do NOT describe the background; the primitive appends the flat key-color background requirement for you.
40
+ - `key_color` lets you key against something other than green if your subject is itself green-heavy (e.g. key against `#FF00FF` magenta for a green frog).
41
+ - The chroma-key params (`tolerance`/`softness`/`despill`) behave exactly as in `image_remove_background_greenscreen`.
42
+ - Response: `primary_file_url` is the finished transparent overlay; `greenscreen_source_url` is the raw pre-key frame (kept so you can re-key at a different tolerance without paying for another generation).
43
+ - Billing: small platform wallet fee (`media_overlay` cost center) **plus** the BYOK image-generation cost on the caller's own provider key.
44
+ - Placement: once the job settles, `add_layer` (or the editor's `generate_layer`/`add_layer`) the `primary_file_url` as an image layer over the video and animate it (Ken Burns, keyframes, entrance transitions) like any other overlay.
45
+
46
+ Example:
47
+
48
+ ```bash
49
+ curl -X POST "$VIDFARM_BASE/api/v1/primitives/images/create-overlay" \
50
+ -H "vidfarm-api-key: $VIDFARM_API_KEY" \
51
+ -H "content-type: application/json" \
52
+ -d '{"tracer": "vox-overlay", "payload": {"prompt": "a friendly cartoon lightbulb mascot, flat vector illustration", "aspect_ratio": "1:1"}}'
53
+ ```
54
+
55
+ ## Primitive: video_remove_captions
56
+
57
+ Remove burned-in captions/subtitles/on-screen text from any video URL (GhostCut-powered — the same pipeline auto-decompose uses for its caption-free mirror, exposed as a standalone reusable primitive). Result is a durable caption-free MP4 stored at a Vidfarm URL.
58
+
59
+ - `POST /api/v1/primitives/videos/remove-captions` (alias: `POST /api/v1/primitives/remove-video-captions`)
60
+ - Body: `{ "tracer": "...", "payload": { "source_video_url": "https://..." }, "webhook_url"?: "..." }`
61
+ - Response: standard primitive job (`202 { job_id }`). The job probes the source, submits to GhostCut, polls to completion server-side (typically a few minutes), and mirrors the result. Poll `GET /api/v1/primitives/jobs/:jobId` until `status: "succeeded"`, then read `primary_file_url` / `video.file_url` (`captionsRemovedVideoUrl` in the output).
62
+ - Billing: `~$0.10 per 30 seconds` of source video (per-chunk, 1-chunk minimum; `ghostcut_subtitle_removal` cost center), plus the small probe cost.
63
+ - For the CURRENT fork's decompose flow, don't re-run this primitive — the caption-free mirror already exists via `GET /api/v1/compositions/:forkId/remove-video-captions`.
64
+ - **Short clips only — hard cap ~15 minutes** (`GHOSTCUT_MAX_DURATION_SEC`, default 900s). Never point this at a long-form source: for "clips without captions" from a long video, run a raws hunt with `avoid_text: true` (scene selection — see "Raws") and, if needed, apply this primitive to the individual FINISHED raws.
65
+
66
+ Example:
67
+
68
+ ```bash
69
+ curl -X POST "$VIDFARM_BASE/api/v1/primitives/videos/remove-captions" \
70
+ -H "vidfarm-api-key: $VIDFARM_API_KEY" \
71
+ -H "content-type: application/json" \
72
+ -d '{"tracer": "demo-remove-captions", "payload": {"source_video_url": "https://cdn.example.com/clip.mp4"}}'
73
+ ```
74
+
75
+ ## Primitive: media_dedupe
76
+
77
+ Apply subtle camouflage transforms (zoom, tilt, rotate, saturation, playback speed, contrast, brightness, hue rotate, blur, horizontal flip, tint overlay) to any source **image or video** URL. Useful when reposting existing media and you want small perceptual differences to reduce duplicate-detection.
78
+
79
+ - `POST /api/v1/primitives/media/dedupe`
80
+ - Body: `{ "tracer": "...", "payload": { ...fields... }, "webhook_url"?: "..." }`
81
+ - Note: webhook delivery is not yet active — `webhook_url` is accepted and persisted on the job but never fired. Poll the job endpoints (`GET /api/v1/primitives/jobs/:jobId`) for completion.
82
+ - Response: standard primitive job. Poll to completion, then read `primary_file_url` (also `video.file_url` for MP4 or `image.file_url` for stills)
83
+ - Billing: metered as a HyperFrames render (via `hyperframes_lambda` on prod cloud render; free on a local serve box)
84
+
85
+ Payload fields:
86
+
87
+ - `source_media_url` (required, URL) — the image or video to transform
88
+ - `media_type` (`"image" | "video"`, optional) — auto-detected from URL extension if omitted (`.mp4/.mov/.webm/.m4v` → video, else image)
89
+ - `effects` (optional object). All fields optional; defaults camouflage lightly:
90
+ - `zoom` (default `1.04`) — scale factor
91
+ - `tilt` (default `3`) — degrees of 3D X-axis tilt (perspective 1000px)
92
+ - `rotate` (default `3`) — degrees of 2D rotation
93
+ - `saturation` (default `1.05`)
94
+ - `speed` (default `1.05`, video only) — playback rate, also compresses output duration accordingly
95
+ - `horizontal_flip` (default `false`)
96
+ - `contrast` (default `1.05`)
97
+ - `brightness` (default `1.05`)
98
+ - `hue_rotate` (default `0`) — degrees
99
+ - `blur` (default `0`) — pixels
100
+ - `tint_color` (default `"#FF8C00"`), `tint_opacity` (default `0.08`) — subtle color overlay
101
+ - `width` (default `1080`), `height` (default `1920`) — output canvas
102
+ - `duration_ms` — output duration for video; if omitted, `fallback_duration_ms` (default `5000`) is used
103
+ - `object_fit` (`"cover" | "contain" | "fill" | "none" | "scale-down"`, default `"cover"`)
104
+ - `background_color` (default `"#000000"`) — visible when `object_fit` leaves letterboxing
105
+ - `muted` (default `false`), `volume` (default `1`) — audio pass-through on video
106
+ - `output_format` (`"png" | "jpeg" | "webp"`, default `"png"`) — image mode only; video mode always outputs MP4
107
+
108
+ Video example (camouflage a reused clip):
109
+
110
+ ```bash
111
+ curl -X POST "$VIDFARM_BASE/api/v1/primitives/media/dedupe" \
112
+ -H "vidfarm-api-key: $VIDFARM_API_KEY" \
113
+ -H "content-type: application/json" \
114
+ -d '{
115
+ "tracer": "dedupe-2026-07-01-abc",
116
+ "payload": {
117
+ "source_media_url": "https://cdn.example.com/reel.mp4",
118
+ "media_type": "video",
119
+ "duration_ms": 8500,
120
+ "effects": {
121
+ "zoom": 1.05,
122
+ "tilt": 2,
123
+ "rotate": -2,
124
+ "speed": 1.03,
125
+ "hue_rotate": 4,
126
+ "horizontal_flip": true
127
+ },
128
+ "tint_color": "#00A3FF",
129
+ "tint_opacity": 0.06
130
+ }
131
+ }'
132
+ ```
133
+
134
+ Image example:
135
+
136
+ ```bash
137
+ curl -X POST "$VIDFARM_BASE/api/v1/primitives/media/dedupe" \
138
+ -H "vidfarm-api-key: $VIDFARM_API_KEY" \
139
+ -H "content-type: application/json" \
140
+ -d '{
141
+ "tracer": "dedupe-still-01",
142
+ "payload": {
143
+ "source_media_url": "https://cdn.example.com/photo.jpg",
144
+ "media_type": "image",
145
+ "effects": { "zoom": 1.06, "rotate": -1, "hue_rotate": 8 },
146
+ "output_format": "webp"
147
+ }
148
+ }'
149
+ ```
150
+
151
+ ## Primitive: music (text → music)
152
+
153
+ Generate music (instrumental, songs with lyrics, background beds, jingles, scores) via ElevenLabs. **Default this on freely — music is a core primitive.** `use_wallet_credits` defaults **true**: it runs on vidfarm's platform ElevenLabs key and bills the customer's wallet. Recommend keeping it on; set it false only to save wallet credits or to use the customer's OWN saved ElevenLabs key.
154
+
155
+ - `POST /api/v1/primitives/music/generate` (alias: `POST /api/v1/primitives/music`)
156
+ - Body: `{ "tracer": "...", "payload": { "prompt": "...", "music_length_ms"?: 30000, "composition_plan"?: {...}, "model"?: "...", "use_wallet_credits"?: true }, "webhook_url"?: "..." }`
157
+ - `prompt` — describe the vibe/genre/instrumentation. `music_length_ms` ≤ 300000 (5 min), default 30000.
158
+ - `composition_plan` (optional) — ElevenLabs section-by-section plan for granular lyric/style control (see the loadable `music` skill pack).
159
+ - Result: durable mp3 (`primary_file_url` / `audio.file_url`). Mount as its own `<audio>` layer ~0.1–0.2 under narration.
160
+ - devcli: `vidfarm music "<prompt>" --length 30` (`--own-key` to use your ElevenLabs key).
161
+
162
+ ## Primitive: tts (text → speech)
163
+
164
+ Generate spoken narration audio from text. **`use_wallet_credits` defaults true** → high-quality ElevenLabs narration on vidfarm's platform key, billed to the wallet — the recommended default. Set it false to use the customer's OWN ElevenLabs key or a BYOK OpenAI/Gemini/OpenRouter key (BYOK is never wallet-billed). The **voice style is promptable** via `instructions` (tone/pacing/accent/emotion/persona). Result is a durable Vidfarm audio URL (mp3/wav) ready to drop into a composition as an audio layer.
165
+
166
+ - `POST /api/v1/primitives/audio/speech` (alias: `POST /api/v1/primitives/tts`)
167
+ - Body: `{ "tracer": "...", "payload": { "text": "...", "voice"?: "...", "instructions"?: "...", "use_wallet_credits"?: true, "provider"?: "openai" | "gemini" | "openrouter", "model"?: "...", "output_format"?: "mp3" | "wav" }, "webhook_url"?: "..." }`
168
+ - `text` (required, ≤8000 chars) — the words to speak, verbatim. Aliases: `input`, `script`.
169
+ - `voice` (optional) — on the ElevenLabs path, an ElevenLabs **voice_id** (or friendly name george/sarah/…); on the BYOK path a provider preset (OpenAI `alloy`/…; Gemini `Kore`/…). **Default a sensible voice and tell the user they can pick from many** — list them with `GET /api/v1/primitives/audio/voices` (or `vidfarm voices`).
170
+ - `instructions` (optional) — the voice-STYLE prompt. Aliases: `style`, `style_instructions`, `voice_style`.
171
+ - `output_format` defaults to `mp3` (Gemini/ElevenLabs may answer in wav — read `audio.content_type`).
172
+ - Response: standard primitive job. Poll to completion, then read `primary_file_url` / `audio.file_url`.
173
+ - Billing: wallet-billed on the platform ElevenLabs key (default); free/BYOK when `use_wallet_credits: false` and the caller's own key serves it.
174
+ - devcli: `vidfarm tts "…" --style "…"` runs LOCAL-FIRST on your own env key (no job); add `--cloud` for the ElevenLabs platform job (`--own-key` = your key). `vidfarm voices` lists voices.
175
+
176
+ ## Primitive: audio/voices (list ElevenLabs voices)
177
+
178
+ `GET /api/v1/primitives/audio/voices` returns the ElevenLabs voice catalog — `{ scope, default_voice_id, voice_library_url, voices: [{ voice_id, name, category, labels, description, preview_url }] }`. Default scope is vidfarm's platform account; add `?use_wallet_credits=false` to list the voices on the customer's OWN saved ElevenLabs key. Pick a `voice_id` and pass it as `voice` to `/audio/speech`. devcli: `vidfarm voices` (`--own-key` for the user's account).
179
+
180
+ Example:
181
+
182
+ ```bash
183
+ curl -X POST "$VIDFARM_BASE/api/v1/primitives/audio/speech" \
184
+ -H "vidfarm-api-key: $VIDFARM_API_KEY" \
185
+ -H "content-type: application/json" \
186
+ -d '{
187
+ "tracer": "demo-tts",
188
+ "payload": {
189
+ "text": "Welcome back. Today we are testing the three most viral hooks.",
190
+ "voice": "coral",
191
+ "instructions": "energetic UGC creator, conversational, slightly breathless"
192
+ }
193
+ }'
194
+ ```
195
+
196
+ ## Primitive: stt (video/audio → transcript)
197
+
198
+ Transcribe speech from **any video or audio URL** on the caller's saved AI provider keys (video sources are demuxed to audio automatically via the platform ffmpeg seam). One job returns **BOTH formats**:
199
+
200
+ 1. **Simple subtitle version** — the plain transcript (`output.text`, `transcript.txt`) plus timed SRT cues (`output.subtitles.srt`, `transcript.srt`) with no speaker labels — drop-in captions.
201
+ 2. **Advanced multi-speaker version** — speaker-attributed, timestamped segments (`output.segments`, each `{ speaker, start_sec, end_sec, text }`, with `output.speakers` listing the cast) for multi-narration sources like podcasts, interviews, and skits — stored durably as `transcript.json`.
202
+
203
+ - `POST /api/v1/primitives/audio/transcribe` (alias: `POST /api/v1/primitives/stt`)
204
+ - Body: `{ "tracer": "...", "payload": { "source_url": "https://...", "diarize"?: true, "word_timestamps"?: false, "use_wallet_credits"?: true, "language"?: "en", "prompt"?: "...", "provider"?: "gemini" | "openai" | "openrouter", "model"?: "...", "media_type"?: "auto" | "video" | "audio" }, "webhook_url"?: "..." }`
205
+ - `source_url` (required) — video OR audio URL. Aliases: `source_video_url`, `source_audio_url`, `video_url`, `audio_url`, `url`. For a fork's composition, pick the right source via `GET /api/v1/compositions/:forkId/remove-video-captions` first.
206
+ - `use_wallet_credits` (default `true`) — ElevenLabs Scribe on the platform key (native diarization + real word timestamps), billed to the wallet. Set false to use the customer's OWN ElevenLabs key or a BYOK gemini/openai/openrouter key.
207
+ - `diarize` (default `true`) — attribute segments to speakers. On the BYOK path speaker labels need a **Gemini key**; OpenAI/OpenRouter degrade to a single-speaker transcript. ElevenLabs Scribe (the default) diarizes natively.
208
+ - `prompt` (optional) — domain/vocabulary hint; `language` (optional) — expected language code.
209
+ - Response: standard primitive job. Poll to completion; `output` carries both formats inline (very long transcripts set `text_truncated: true` and keep the full copy in the `transcript.json` artifact), and the artifacts `transcript.json` / `transcript.srt` / `transcript.txt` are durable URLs.
210
+ - Limits: ~40 minutes of speech per job (20MB extracted audio) — trim longer sources with `/videos/trim` or `/audio/trim` and transcribe in parts.
211
+ - Billing: wallet-billed on the platform ElevenLabs key (default); free/BYOK when `use_wallet_credits: false`. The tiny audio-demux compute step always bills (`primitive_media_lambda`), like every media primitive.
212
+ - For the CURRENT fork, the decompose-time transcript may already exist via `video-context.json` — prefer it before paying for a new transcription; use this primitive for other URLs, multi-speaker attribution, or SRT output.
213
+ - devcli: `vidfarm stt <file|url>` runs LOCAL-FIRST (local ffmpeg + your own key); add `--cloud` to run this route instead.
214
+
215
+ Example:
216
+
217
+ ```bash
218
+ curl -X POST "$VIDFARM_BASE/api/v1/primitives/audio/transcribe" \
219
+ -H "vidfarm-api-key: $VIDFARM_API_KEY" \
220
+ -H "content-type: application/json" \
221
+ -d '{
222
+ "tracer": "demo-stt",
223
+ "payload": {
224
+ "source_url": "https://cdn.example.com/podcast-clip.mp4",
225
+ "diarize": true,
226
+ "language": "en"
227
+ }
228
+ }'
229
+ ```
230
+
231
+ ## Brainstorm primitives
232
+
233
+ The `brainstorm/*` primitives are the strategy toolkit. They are reusable, billable AI reasoning steps — the same family the AI Copilot exposes as chip suggestions. Treat **product placement** as a first-class member of this family, right alongside angles and hooks:
234
+
235
+ - `POST /api/v1/primitives/brainstorm/coldstart` — `{ payload: { user_message } }` → foundational questionnaire for a customer starting from zero.
236
+ - `POST /api/v1/primitives/brainstorm/awareness_stages` — `{ payload: { offer_description } }` → which Eugene-Schwartz awareness stages to target first.
237
+ - `POST /api/v1/primitives/brainstorm/angles` — `{ payload: { offer_description, problem_awareness, solution_awareness } }` → persuasive angles.
238
+ - `POST /api/v1/primitives/brainstorm/hooks` — `{ payload: { offer_description } }` → many TikTok-native hooks.
239
+ - `POST /api/v1/primitives/brainstorm/product_placement` — `{ payload: { source_video_url, offer_description } }` → **watches the video** and returns concrete, timestamped opportunities to natively place the product.
240
+
241
+ ### Primitive: brainstorm_product_placement
242
+
243
+ Analyze a source video and identify where a product can be organically placed so it feels native rather than bolted on. This is a **multimodal** primitive: it feeds the actual video to a vision-capable model, so prefer a saved **Gemini** key (native video understanding). OpenRouter multimodal models also work; plain OpenAI chat keys cannot watch video.
244
+
245
+ - `POST /api/v1/primitives/brainstorm/product_placement`
246
+ - Body: `{ "tracer": "...", "payload": { "source_video_url": "...", "offer_description": "...", "count"?: 8, "provider"?: "gemini" }, "webhook_url"?: "..." }`
247
+ - `source_video_url` (required, URL) — the exact durable/public video to analyze. Aliases accepted: `video_url`, `source_url`, `url`. For a fork's composition, call `GET /api/v1/compositions/:forkId/remove-video-captions` first and pass the correct URL — the **original video** (`original_source_url`) or the **decomposed video** (`mirrored_url`).
248
+ - `offer_description` (required) — the product/offer to place. Aliases: `offer`, `description`, `details`.
249
+ - `count` (optional, 3–30, default 8) — number of opportunities; only send when the user asks for a specific number.
250
+ - Response: standard primitive job. Poll `GET /api/v1/primitives/jobs/:jobId` to completion, then read `result.json` (also surfaced on the job output as `opportunities[]`), where each entry has `timestamp`, `scene`, `placement_type`, `placement_idea`, and `why_it_works`.
251
+
252
+ You can also satisfy a quick, conversational product-placement question by reasoning over an attached video directly instead of calling this primitive — use the primitive when you want a durable, structured, billable artifact the customer can save and reuse.
253
+
254
+ ```bash
255
+ curl -X POST "$VIDFARM_BASE/api/v1/primitives/brainstorm/product_placement" \
256
+ -H "vidfarm-api-key: $VIDFARM_API_KEY" \
257
+ -H "content-type: application/json" \
258
+ -d '{
259
+ "tracer": "product-placement-01",
260
+ "payload": {
261
+ "source_video_url": "https://cdn.example.com/source.mp4",
262
+ "offer_description": "A $29/mo AI meal-planning app for busy parents."
263
+ }
264
+ }'
265
+ ```