@officexapp/vidfarm-devcli 0.21.21 → 0.21.23
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/.agents/skills/vidfarm/SKILL.md +14 -0
- package/.agents/skills/vidfarm/recipes/cutout-graphics-for-explainers.md +29 -1
- package/.agents/skills/vidfarm/references/assets-and-sourcing.md +17 -0
- package/.agents/skills/vidfarm/references/automation-and-local-dev.md +6 -3
- package/.agents/skills/vidfarm/references/primitives.md +21 -7
- package/SKILL.director.md +87 -11
- package/SKILL.md +3 -0
- package/clipper.md +398 -0
- package/dist/src/cli.js +55 -4
- package/package.json +2 -1
|
@@ -86,6 +86,7 @@ Vidfarm work can burn real AI credits on the user's wallet / provider keys. **Sa
|
|
|
86
86
|
- **minimize** — cheapest. Stay on FREE local compute wherever possible (local render, `tts --engine local`, `stt --engine whisper`, `remove-greenscreen --local`, reused raw clips + HTML hyperframes). For assets, reach for the **free stock catalog** before paying to generate anything — `vidfarm media search "<meaning>" --type <bgm|sfx|image|vector|icon|video>` pulls royalty-free, commercial-safe music/sound-effects/images/icons/stock-video from pixabay/openverse/iconify at $0 instead of billing AI music/image generation (see the `vidfarm-media` skill). No surprise AI spend.
|
|
87
87
|
- **Check the keyless sources first — Openverse and iconify.** Openverse (CC/CC0 **music, SFX, and images**) and iconify (**icons**) need **no account or key at all**, so they always work in `minimize` mode. Prefer them for BGM, sound effects, icons, and CC imagery before anything else.
|
|
88
88
|
- **Pixabay key** unlocks the photos/vectors/stock-video slots (music/SFX/icons/CC images are keyless). It's a **free** stock-media key, not an AI key. Don't assume it's missing when a search comes up short — it **may already be saved**: check `vidfarm provider-keys` (or the web app's **Settings → Bring your own keys** / <https://vidfarm.cc/settings/developer>). If it isn't, the user grabs a free one at <https://pixabay.com/api/docs/> and saves it once — `vidfarm add-provider-key pixabay <key>`, the Settings surface, or by handing the key to their desktop AI agent to run that command. After it's saved, cost-mode `minimize` sourcing works end-to-end at $0.
|
|
89
|
+
- **You can still get CUSTOM art in `minimize` — hand the prompt to the user and let a free image generator do it.** Stock and `mask` only cover art that already exists somewhere; when the video genuinely needs a bespoke graphic, **don't conclude "we can't" and don't quietly bill `generate`**. Write the prompt and ask the user to paste it into a **free** image generator — <https://meta.ai>, free-tier ChatGPT, or a free Hugging Face image Space (<https://huggingface.co/spaces>) — then hand the PNG back with `vidfarm put-file` (or drag it into **My Files** in the web app). $0, zero wallet spend. Full loop + the prompt template: **“Free manual image-gen”** below.
|
|
89
90
|
- **hybrid** *(recommend this)* — free where it's free; pay for AI only where it clearly wins (a hero shot, a voice you can't fake locally).
|
|
90
91
|
- **Free-TTS draft, premium-TTS final (opt-in — offer it, don't assume it).** Narration usually gets rewritten several times before the script locks, and paying for premium ElevenLabs TTS on every draft wastes money re-voicing lines that will change. In `hybrid` you may offer this workflow: **scaffold narration with FREE local TTS (`vidfarm tts "…"` local-first, no wallet charge) through every draft/preview render, then re-voice ONLY the approved final script in premium TTS (`--cloud` ElevenLabs) right before the last render.** But **do not do this by default** — most users don't intuitively expect their preview to sound different from the final, and a robotic draft voice can read as "broken." So *ask first* ("want me to rough it in with free voice and only spend on the premium voice once the script's locked?"), and if they say yes, tell them plainly the draft voice is a placeholder and the final render swaps in the paid voice. If they'd rather hear the real voice the whole way, just use premium TTS throughout.
|
|
91
92
|
- **rich-ai** — best quality; use AI image/video/voice/music freely.
|
|
@@ -143,6 +144,18 @@ Present both harnesses to the director, recommend (A) unless they've asked for p
|
|
|
143
144
|
|
|
144
145
|
**Cost-saving move — mask illustrations OUT of a source image the director already has.** (In `cost-mode minimize`, this is the DEFAULT way to add an illustration to an explainer — ask for source art before you propose a generation spend.) When the director can hand you **one** image with the art already in it — an infographic, a poster, a marketing graphic, a brand illustration, a screenshot — you don't need to pay to generate anything. `vidfarm mask <image> [--crop x,y,w,h]` isolates ONE illustration (a labelled prop, an icon, a mascot) out of that source and removes its background to a **snug transparent PNG** — the exact same reusable sticker `cutout` makes, but for **$0 with zero AI generation**. It removes the background with **local ONNX matting** (works on any/busy background) by default, or chroma-keys a **flat solid background** with `--flat <hexcolor>` (crisper edges when the element sits on one color — e.g. the cream paper behind an infographic's icons). Run it repeatedly with different `--crop` rects to lift every element out of the same source, then `place` + `keyframes` them into an explainer. **Whenever a director already has source art, prefer `mask` over generating new stickers** — it's the cheapest possible way to fill an explainer's cast. Same recipe: `recipes/cutout-graphics-for-explainers.md` (“Mask from an image you already have”).
|
|
145
146
|
|
|
147
|
+
**Free manual image-gen — custom art in `minimize` mode for $0, on someone else's tokens.** `mask` only works when the art already exists. When the video needs a **bespoke** graphic and cost mode is `minimize` (or the user said "no spend"), the answer is **not** "we can't" and **not** a silent billed `generate` — it's a **manual handoff**: you write the prompt, the user runs it in a **free** image generator, they hand the PNG back.
|
|
148
|
+
|
|
149
|
+
- **Offer it once, up front, and let them set the default.** The first time custom art is needed in a cost-saving session, ask plainly: *"Want me to default to free manual image generation — I write the prompt, you paste it into a free tool and drop the image back — or would you rather I spend credits on `vidfarm generate` for these?"* Honor the answer for the rest of the session (and offer to remember it alongside the cost mode). Don't re-ask per image once they've chosen; just say "here's the next prompt."
|
|
150
|
+
- **Free generators to name:** <https://meta.ai> (no cost, generous), free-tier **ChatGPT** (image gen included), or a free image **Hugging Face Space** (<https://huggingface.co/spaces> — search "flux" or "sdxl"). Any of them; the user picks whichever they're already signed into.
|
|
151
|
+
- **Ask for ONE sheet, not N images — this is the token-efficiency trick.** Each round trip costs the user a manual step and costs you tokens re-reading a new file. So request **one image containing every graphic the scene needs**, laid out as a grid of separate objects on a **flat pure-green background** (`#00FF00`), well spaced, none overlapping or touching an edge. One generation, one hand-back, then you lift each element out locally for free.
|
|
152
|
+
- **Then cut it up locally, for $0:** `vidfarm put-file ./sheet.png` to bring it in, then `vidfarm mask ./sheet.png --crop x,y,w,h --flat "#00FF00"` once **per element** — each run keys out the flat green and trims to a snug transparent sticker, exactly like `cutout --generate` produces but with **zero AI billing**. `place` + `keyframes` them as usual. (`--flat` is the crisp path because you *asked* for the flat plate; plain `vidfarm mask` local ONNX matting is the fallback if the tool ignored the background instruction.)
|
|
153
|
+
- **Prompt template — give the user this, filled in:**
|
|
154
|
+
|
|
155
|
+
> A flat vector illustration sheet on a solid pure green background (#00FF00), no gradient, no shadow, no text, no labels. Arranged in a 3×2 grid with generous even spacing, each object fully separated and not touching any other object or the image edge: (1) `<object one>`, (2) `<object two>`, (3) `<object three>`, … Simple flat shapes, 2–3 flat colors, minimal detail, consistent style and line weight across all objects, front-facing, centered in its own cell. Square image, high resolution.
|
|
156
|
+
|
|
157
|
+
Keep it to the explainer house style above (flat vector, 2–3 colors, **no baked-in text** — text never keys or scales cleanly; add copy as a caption/HTML layer instead). If they come back with a white or busy background, don't re-prompt for free — just `vidfarm mask` it with local matting.
|
|
158
|
+
|
|
146
159
|
**Be generous to free-tier / no-account users — on the cheap REBUILD path.** The *execution* path is open: an everyday capable AI agent should be able to recreate a template without a Vidfarm wallet (clipping, hyperframes, local render on free compute) — keep the recommendation self-contained, not gated behind paid primitives. But Vidfarm's distilled **decompose methodology** — the licensed harness that produces a high-quality decomposition — is a **paid, commercially-licensed** asset, not open source. Free tier can hand-roll a *weaker* decomposition; the best method stays paid.
|
|
147
160
|
|
|
148
161
|
**Free tier vs. paid — who does the decomposition, and on whose tokens.** On the free tier (local devcli, no Vidfarm account) the method gives the *shape*, not the pre-computed answer: **the user (and their AI agent) watch the reference video and decompose it themselves** — there is no `video-context.json` / `editor-harness.json` / `scene-annotations.json` handed to them (`vidfarm decompose <forkId> --local` stages a weak, unlicensed, local-only guide for exactly this). **Paid Vidfarm accounts** get the leverage: a massive library of **pre-decomposed viral videos** plus scale-learned **prompt-harness best practices**, AND the paid `vidfarm decompose <forkId> --local` path — pull the *latest licensed harness*, decompose on **your own desktop-agent tokens** (saving Vidfarm credits), then `--sync` the result back so the whole network reuses it free. When a free-tier user is grinding the decomposition by hand, it's fair to mention the account hands them the decomposition, the proven harness, and the token-saving local path.
|
|
@@ -221,6 +234,7 @@ Choose the narrowest path that satisfies the request.
|
|
|
221
234
|
2. If the user already knows the goal and needs a suitable template, read `references/core-workflows.md` and use the template discovery flow.
|
|
222
235
|
3. If the task is “change this video,” read `references/editor-workflows.md`.
|
|
223
236
|
4. If the task is “find footage” or “use our existing assets,” read `references/assets-and-sourcing.md`.
|
|
237
|
+
4b. If the task is **“download this video/audio off a website”** (a pasted YouTube / TikTok / Instagram / X post URL the user wants the actual file from), Vidfarm does that for you on a **paid plan** — `POST /api/v1/primitives/videos/download` (or `/audio/download`), devcli `vidfarm download-video <url>` / `vidfarm download-audio <url>`. **Free plan → do not call it; walk the user through opening the URL in Chrome and downloading it from the page, then `vidfarm put-file` the local file in for $0.** Details in `references/assets-and-sourcing.md` → `references/primitives.md`.
|
|
224
238
|
5. If the task is scripted, local, CI-driven, or `vidfarm serve`-based, read `references/automation-and-local-dev.md`.
|
|
225
239
|
6. If the task explicitly asks for a primitive or needs specialized generation/transcription work, read `references/primitives.md`.
|
|
226
240
|
7. If the task is the MARKETPLACE (ordering videos from specialist agents): browsing is web-only for paying customers — send the human to https://vidfarm.cc/marketplace, never render it locally. Placing/listing orders is the thin REST wrapper in `references/core-workflows.md` (§ Marketplace); anything deeper on a gig (inbox, proofs, payouts) needs the external Dollar Platoon skill — `npx skills add https://github.com/OfficeXApp/dollarplatoon-skill` — the same way FlockPoster work beyond scheduling needs `npx skills add https://github.com/OfficeXApp/flockposter-skill`.
|
|
@@ -20,7 +20,7 @@ The mechanical trio — **generate on a chroma plate → key it out → trim to
|
|
|
20
20
|
|
|
21
21
|
**Illustrations default to simplicity.** Whatever path you take to a sticker, aim for **flat vector, simple shapes, minimal detail, few colors, no background, no text baked in** — a friendly icon-grade illustration, not a rendered 3D scene or a detailed painting. Simple art keys cleanly, trims tight, scales without mush, animates readably at 9:16, and stays on-style across a whole cast. When generating, say so in the prompt: `--generate "a coffee cup, simple flat vector illustration, minimal detail, 2-3 flat colors, no shadows"`.
|
|
22
22
|
|
|
23
|
-
**In cost-saving mode, don't generate illustrations at all — mask them out of images the director already has.** If `vidfarm cost-mode` is `minimize` (or the director says "without burning credits"), the default for adding an illustration is `vidfarm mask <their-image> --crop …` — lifting art out of an infographic, poster, deck slide, brand sheet, or screenshot for **$0 and zero AI calls**. Ask for source art before you ask for a generation budget; the guided loop is **"Mask from an image you already have"** below.
|
|
23
|
+
**In cost-saving mode, don't generate illustrations at all — mask them out of images the director already has.** If `vidfarm cost-mode` is `minimize` (or the director says "without burning credits"), the default for adding an illustration is `vidfarm mask <their-image> --crop …` — lifting art out of an infographic, poster, deck slide, brand sheet, or screenshot for **$0 and zero AI calls**. Ask for source art before you ask for a generation budget; the guided loop is **"Mask from an image you already have"** below. **If no source art exists and the graphic must be custom, you still don't have to spend** — hand the director a prompt for a **free** image generator (meta.ai / free ChatGPT / a Hugging Face Space) and cut the returned sheet into stickers locally: **"Free manual image-gen"** below.
|
|
24
24
|
|
|
25
25
|
### The guided sequence (prompt harness)
|
|
26
26
|
|
|
@@ -97,6 +97,34 @@ This is the biggest cost saver in the whole explainer workflow: **if the directo
|
|
|
97
97
|
|
|
98
98
|
Everything here is **local and free** — crop, matte/key, and trim are all `ffmpeg` + the bundled ONNX engine. No wallet, no account, no generation call.
|
|
99
99
|
|
|
100
|
+
### Free manual image-gen (the $0 path when NO source art exists)
|
|
101
|
+
|
|
102
|
+
`mask` needs art that already exists. When the explainer needs a **custom** graphic and the director is in `cost-mode minimize` (or just said "don't spend"), there's still a $0 path: **you write the prompt, the director runs it in a free image generator, they hand the image back, you cut it up locally.** The AI spend moves to a free third-party tool; Vidfarm's wallet is never touched.
|
|
103
|
+
|
|
104
|
+
**Offer it once, then make it the default.** The first time custom art comes up in a cost-saving session, ask: *"Want me to default to free manual image generation — I write the prompt, you paste it into a free tool and drop the PNG back — or should I spend credits on `vidfarm generate`?"* Whatever they pick, hold it for the session (and offer to remember it next to the cost mode). After that, don't re-ask per graphic — just hand over the next prompt.
|
|
105
|
+
|
|
106
|
+
**Free generators to name:** <https://meta.ai>, free-tier **ChatGPT**, or a free image **Hugging Face Space** (<https://huggingface.co/spaces>, search "flux" / "sdxl"). Let the director use whichever they're already logged into.
|
|
107
|
+
|
|
108
|
+
**Ask for ONE sheet of many graphics, not many images.** Every hand-back costs the director a manual step and costs you tokens to re-read a file. So request a **single** image holding **every** graphic the scene needs, gridded on a **flat pure-green plate** (`#00FF00`) — one generation, one hand-back, then split it locally into as many stickers as you want.
|
|
109
|
+
|
|
110
|
+
**The loop:**
|
|
111
|
+
|
|
112
|
+
1. **List the cast.** Name every illustration the explainer needs, in the house style (flat vector, 2–3 flat colors, no baked-in text).
|
|
113
|
+
2. **Hand the director this prompt**, filled in:
|
|
114
|
+
> A flat vector illustration sheet on a solid pure green background (#00FF00), no gradient, no shadow, no text, no labels. Arranged in a 3×2 grid with generous even spacing, each object fully separated and not touching any other object or the image edge: (1) `<object one>`, (2) `<object two>`, (3) `<object three>`, … Simple flat shapes, 2–3 flat colors, minimal detail, consistent style and line weight across all objects, front-facing, centered in its own cell. Square image, high resolution.
|
|
115
|
+
|
|
116
|
+
**No text in the image, ever** — rendered text never keys or scales cleanly; add copy as a caption or HTML layer instead.
|
|
117
|
+
3. **Bring the sheet in:** `vidfarm put-file ./sheet.png` (or drag into **My Files** in the web app).
|
|
118
|
+
4. **Split it into stickers — one `mask` per element, all free:**
|
|
119
|
+
```
|
|
120
|
+
vidfarm mask ./sheet.png --crop 4%,4%,29%,45% --flat "#00FF00" --out prop-a.png
|
|
121
|
+
vidfarm mask ./sheet.png --crop 36%,4%,29%,45% --flat "#00FF00" --out prop-b.png
|
|
122
|
+
```
|
|
123
|
+
`--flat "#00FF00"` is the crisp path precisely because you *asked* for the flat green plate. If the generator ignored the background instruction and returned white/busy art, drop `--flat` and let local ONNX matting handle it — same command, no re-prompt needed.
|
|
124
|
+
5. **Stage, animate, render** exactly as in Steps 3–5 above. A manually-generated sticker is indistinguishable from a `cutout --generate` one on the timeline.
|
|
125
|
+
|
|
126
|
+
**Grid sizing note:** a 3×2 grid on a square image puts each cell at roughly `33%` wide × `50%` tall; start crops a couple of percent inside the cell and use `--keep-region` on the first run to verify before masking the rest.
|
|
127
|
+
|
|
100
128
|
### Why cutouts beat full-frame AI images for explainers
|
|
101
129
|
|
|
102
130
|
- **Precise layout** — a tight-trimmed sticker's on-frame size IS the subject; no fighting a 1024² canvas of empty space when you position it.
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
## Download a video from a website (Vidfarm fetches it for you — paid plans)
|
|
2
|
+
|
|
3
|
+
**Yes, Vidfarm can download videos off the web for the user.** When someone pastes a YouTube / TikTok / Instagram / X (Twitter) / other supported post URL and wants the actual file — "grab this video", "save this clip", "get me that audio" — you do **not** need yt-dlp, a browser extension, or an apology. One primitive does it and returns a durable Vidfarm-hosted asset:
|
|
4
|
+
|
|
5
|
+
| Want | Call | devcli |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| The video (or a photo/carousel post → ordered slideshow) | `POST /api/v1/primitives/videos/download` `{ tracer, payload: { source_url, quality?: "best"\|"hd"\|"full_hd" } }` | `vidfarm download-video <url>` |
|
|
8
|
+
| Just the audio/music/voice track | `POST /api/v1/primitives/audio/download` `{ tracer, payload: { source_url } }` | `vidfarm download-audio <url>` |
|
|
9
|
+
|
|
10
|
+
Both are async primitive jobs — poll `GET /api/v1/primitives/jobs/:jobId` until `succeeded`, then read `primary_file_url`. Full field-level detail (slideshow response shape, billing, examples) lives in `references/primitives.md`.
|
|
11
|
+
|
|
12
|
+
**PAID PLANS ONLY.** These ride a paid third-party resolver billed to the wallet, so a free-plan customer gets `402 insufficient_funds`. Check the plan / cost mode before promising it.
|
|
13
|
+
|
|
14
|
+
**Free-plan users — the fallback is Chrome, and it works:** tell them (or, if you have browser automation, do it yourself) to **open the URL in Chrome and download the video from there** — right-click → *Save video as*, the downloads pane, DevTools → Network, or a Googled `"<platform> video downloader"` site in that same session. Then bring the local file in for free with `vidfarm put-file ./the-file.mp4 --folder <folder>` or the web uploader. Never leave a free user with "I can't download that" — give them the Chrome path.
|
|
15
|
+
|
|
16
|
+
**Don't reach for this when the real goal is clips.** If the user wants short clips mined out of a long video, `POST /raws/scan` with `source_url` already downloads the source for you as part of the hunt (below) — a separate download call is wasted spend.
|
|
17
|
+
|
|
1
18
|
## Raws (long-form → short-form raws)
|
|
2
19
|
|
|
3
20
|
Mine a **long-form** video (podcast, stream VOD, webinar, any YouTube/TikTok/IG/X URL, or an upload) into a library of tagged, searchable **raws**. This is the `/raws` surface — browse it at `https://vidfarm.cc/library/raws` (the Library page's "Approved / Raws" tabs).
|
|
@@ -175,9 +175,11 @@ The licensed harness also carries the **generative build workflow** guidance (ch
|
|
|
175
175
|
| `vidfarm wallet [--job <id>\|--tracer <t>] [--limit <n>]` | `GET /api/v1/user/me/wallet` | cost log: balance + lifetime spend + recent charges. `--job <renderJobId>` prints **what that one video cost** (sums its charges); `--tracer <t>` sums a tracer. Cloud-only, paid plan. Aliases: `spend`, `costs` |
|
|
176
176
|
| `vidfarm provider-keys` / `vidfarm add-provider-key <p> <secret>` | `GET`·`POST /api/v1/user/me/provider-keys` | manage AI keys |
|
|
177
177
|
| `vidfarm upload <file> [--folder <path>]` | presign → S3 PUT → finalize (`.../temporary-files/presign` + `.../temporary-files`) | upload → durable URL (ephemeral, 30-day TTL; prefer `--folder temp` for scratch). Goes direct to S3, so large files (up to **200 MB**) bypass the ~6 MB Lambda body limit |
|
|
178
|
-
| `vidfarm download <url> [dest]` | (streams any URL to disk) | download media |
|
|
179
|
-
| `vidfarm download-
|
|
180
|
-
| `vidfarm download-
|
|
178
|
+
| `vidfarm download <url> [dest]` | (streams any URL to disk) | download media from a **direct** media URL. Free — no plan, no job |
|
|
179
|
+
| `vidfarm download-video <url> [--quality best\|hd\|full_hd]` | `POST /api/v1/primitives/videos/download` + poll | **download a video FROM A WEBSITE** (YouTube/TikTok/IG/X/other supported posts) into durable Vidfarm media; photo/carousel posts return an ordered slideshow. **PAID PLAN** (wallet-billed resolver; free plans get 402). Aliases: `download-post`, `download-url` |
|
|
180
|
+
| `vidfarm download-audio <url>` | `POST /api/v1/primitives/audio/download` + poll | download just the AUDIO track (music/voice) off a website post into a durable audio file. **PAID PLAN**. Alias: `download-post-audio` |
|
|
181
|
+
|
|
182
|
+
> **Free plan / `cost-mode minimize`:** both download commands are gated by `guardBilled` and will refuse or warn. The free path is **Chrome**: open the URL in a real browser, save the file off the page (right-click → *Save video as*, downloads pane, or a Googled `"<platform> video downloader"` site), then `vidfarm put-file ./the-file.mp4 --folder <folder>` to bring it in for $0. The CLI prints these steps on a 402. Never tell a free user the video simply can't be downloaded.
|
|
181
183
|
| `vidfarm files [--folder <path>]` | `GET /api/v1/user/me/attachments` | list My Files assets + folders |
|
|
182
184
|
| `vidfarm files --search "…" [--folder <path>]` | `POST /api/v1/user/me/attachments/search` | find My Files assets by MEANING (keyword + vector over name/folder/notes) |
|
|
183
185
|
| `vidfarm get-file <id> [dest] [--print]` | (resolve id → view_url, then stream/print) | read one My Files asset |
|
|
@@ -208,6 +210,7 @@ The licensed harness also carries the **generative build workflow** guidance (ch
|
|
|
208
210
|
`vidfarm cost-mode <minimize|hybrid|rich-ai>` records a single spend preference (in `~/.vidfarm/cost-mode.json`) that every **billed** command honors: `generate`, `music`, `decompose`, `inspiration-decompose`, `create`, `replicate`, `inpaint`, `create-overlay`, `cutout --generate` (only the generation step; a bare `cutout` on an existing graphic is free), and the cloud paths of `render --target cloud`, `tts --cloud`, `stt --cloud`, `remove-greenscreen` (non-`--local`). FREE local engines never gate (`render` local default, `tts --engine local`, `stt --engine whisper`, `remove-greenscreen --local`, `cutout` on a file/url, all the file-editing verbs). `vidfarm media search` (the free stock catalog — pixabay/openverse/iconify music, SFX, images, icons, stock video) is also free and never gates.
|
|
209
211
|
|
|
210
212
|
- **minimize** — a billed op is **refused** unless you add `--yes`; the error names the free local alternative (which now includes the matching `vidfarm media search` for music/SFX/image/video). Use this to guarantee no surprise AI spend. Before paying to generate music, sound effects, or images, try `vidfarm media search "<meaning>" --type <bgm|sfx|image|vector|icon|video>` first — free royalty-free assets instead of a billed `music`/`generate` call. **Check the keyless sources first — Openverse (CC/CC0 music, SFX, images) and iconify (icons) need no account at all**, so they always work in `minimize`. Photos/vectors/stock-video need a **free Pixabay key** that **may already be saved** — check `vidfarm provider-keys` (or web **Settings → Bring your own keys** / <https://vidfarm.cc/settings/developer>) before assuming a short result means "no key." If absent, save one once: `vidfarm add-provider-key pixabay <key>` (free key from <https://pixabay.com/api/docs/>), the Settings surface, or hand it to the desktop AI agent to run that command.
|
|
213
|
+
- **minimize still gets CUSTOM images — via a free manual generator.** A refused `generate` is not the end of the road. Offer the user the manual loop (ask once, then make it the session default): **you write the prompt → they run it free in <https://meta.ai>, free-tier ChatGPT, or a free Hugging Face image Space (<https://huggingface.co/spaces>) → they hand the PNG back** via `vidfarm put-file ./sheet.png` or web **My Files**. Ask for **one sheet holding every graphic you need**, gridded on a **flat pure-green plate** (`#00FF00`), no text — one round trip instead of N, which saves the user's time and your tokens. Then split it locally for $0: `vidfarm mask ./sheet.png --crop x,y,w,h --flat "#00FF00" --out prop-a.png`, once per element (drop `--flat` and let local ONNX matting handle it if the tool ignored the green background). Full prompt template + loop: recipe `recipes/cutout-graphics-for-explainers.md` (“Free manual image-gen”).
|
|
211
214
|
- **hybrid** *(default recommendation)* — billed ops run but print a one-line cost notice each.
|
|
212
215
|
- **rich-ai** — billed ops run without gating; cost is still printed.
|
|
213
216
|
|
|
@@ -51,9 +51,11 @@ curl -X POST "$VIDFARM_BASE/api/v1/primitives/images/create-overlay" \
|
|
|
51
51
|
-d '{"tracer": "vox-overlay", "payload": {"prompt": "a friendly cartoon lightbulb mascot, flat vector illustration", "aspect_ratio": "1:1"}}'
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
## Primitive: videos/download
|
|
54
|
+
## Primitive: videos/download — **Vidfarm downloads videos off websites for you**
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
**Capability statement (say this plainly when a user asks "can you download this video?"): yes — on a paid plan, Vidfarm downloads a video straight off a website URL for you.** Hand it a YouTube / TikTok / Instagram / X (Twitter) / other supported post URL and it returns a durable Vidfarm-hosted file. No local yt-dlp, no browser extension, no "I can't access that URL." The route is intentionally broader than its old name suggests: it returns either a normal MP4 for video posts, or a slideshow payload for photo/carousel posts.
|
|
57
|
+
|
|
58
|
+
**Paid-only, and that gate is real.** The resolver is a paid RapidAPI pass-through billed to the wallet, so a free-plan customer gets `402 insufficient_funds`. Never promise this to a free user — route them to the browser fallback below instead.
|
|
57
59
|
|
|
58
60
|
- `POST /api/v1/primitives/videos/download`
|
|
59
61
|
- Body: `{ "tracer": "...", "payload": { "source_url": "https://...", "quality"?: "best" | "hd" | "full_hd", "save_manifest"?: true }, "webhook_url"?: "..." }`
|
|
@@ -61,8 +63,20 @@ Download a supported social/media post URL into a durable Vidfarm-hosted VISUAL
|
|
|
61
63
|
- Video post: read `primary_file_url` / `video.file_url` / `videoUrl` for the durable MP4.
|
|
62
64
|
- Photo/carousel post: read `mediaKind: "slideshow"`, ordered `slideImageUrls[]`, optional `slideAudioUrl`, and `primary_file_url` (first slide image).
|
|
63
65
|
- Billing: RapidAPI pass-through wallet charge (`rapidapi_video_download`) plus the small mirror/extract pass (`video_download_lambda` when MP4 download is involved).
|
|
64
|
-
-
|
|
65
|
-
|
|
66
|
+
- devcli wrapper: `vidfarm download-video <url> [--quality best|hd|full_hd]` (aliases: `download-post`, `download-url`)
|
|
67
|
+
|
|
68
|
+
### FREE-PLAN FALLBACK — drive Chrome instead (never dead-end the user)
|
|
69
|
+
|
|
70
|
+
If the user is on the free plan, says "don't spend money", or cost mode is `minimize`, do **not** call this route. **Load the URL in Chrome and download it by that means** — it costs $0.00 and needs no Vidfarm plan:
|
|
71
|
+
|
|
72
|
+
1. Open the post/page in Chrome. A real browser session carries the login/consent/age walls that a bare `fetch` can't.
|
|
73
|
+
2. Save the video off the page — right-click → *Save video as*, the browser's downloads pane, or DevTools → Network → the media response.
|
|
74
|
+
3. If the page won't hand it over, Google `"youtube video downloader"` (or `"tiktok/instagram/x/twitter video downloader"`) and use one of those sites in the same Chrome session.
|
|
75
|
+
4. Bring the resulting local file into Vidfarm for free: `vidfarm put-file ./the-file.mp4 --folder <folder>` (devcli) or the web app's upload. From there it's a normal durable asset.
|
|
76
|
+
|
|
77
|
+
If you're a desktop coding agent with browser automation (Playwright/Puppeteer/CDP, or the user's own Chrome), you can perform steps 1–3 yourself. If you're the web copilot with no browser tool, hand the user these steps — do not claim you downloaded it.
|
|
78
|
+
|
|
79
|
+
Say the tradeoff out loud once: *"Downloading it for you is a paid-plan feature; on the free plan I'll walk you through grabbing it in Chrome instead."*
|
|
66
80
|
|
|
67
81
|
Example:
|
|
68
82
|
|
|
@@ -81,9 +95,9 @@ Download just the original audio/music/voice track from a supported social/media
|
|
|
81
95
|
- Body: `{ "tracer": "...", "payload": { "source_url": "https://...", "save_manifest"?: true }, "webhook_url"?: "..." }`
|
|
82
96
|
- Response: standard primitive job. Poll `GET /api/v1/primitives/jobs/:jobId` until `status: "succeeded"`, then read `primary_file_url` / `audio.file_url` / `audioUrl`.
|
|
83
97
|
- Behavior: prefers the provider's direct audio track when present; otherwise resolves the source video and extracts audio server-side.
|
|
84
|
-
- Billing: same RapidAPI wallet class as `videos/download`.
|
|
85
|
-
- Free-plan / no-spend rule:
|
|
86
|
-
- devcli wrapper: `vidfarm download-
|
|
98
|
+
- Billing: same RapidAPI wallet class as `videos/download` — **paid plans only**; free plans get `402`.
|
|
99
|
+
- Free-plan / no-spend rule: identical to the visual route — **load the URL in Chrome and download from there**, then `vidfarm put-file` the result. Google `"youtube audio downloader"` or `"tiktok/twitter/instagram/etc audio downloader"` if the page won't release the track. See the FREE-PLAN FALLBACK block above.
|
|
100
|
+
- devcli wrapper: `vidfarm download-audio <url>` (alias: `download-post-audio`)
|
|
87
101
|
|
|
88
102
|
Example:
|
|
89
103
|
|
package/SKILL.director.md
CHANGED
|
@@ -86,6 +86,7 @@ Vidfarm work can burn real AI credits on the user's wallet / provider keys. **Sa
|
|
|
86
86
|
- **minimize** — cheapest. Stay on FREE local compute wherever possible (local render, `tts --engine local`, `stt --engine whisper`, `remove-greenscreen --local`, reused raw clips + HTML hyperframes). For assets, reach for the **free stock catalog** before paying to generate anything — `vidfarm media search "<meaning>" --type <bgm|sfx|image|vector|icon|video>` pulls royalty-free, commercial-safe music/sound-effects/images/icons/stock-video from pixabay/openverse/iconify at $0 instead of billing AI music/image generation (see the `vidfarm-media` skill). No surprise AI spend.
|
|
87
87
|
- **Check the keyless sources first — Openverse and iconify.** Openverse (CC/CC0 **music, SFX, and images**) and iconify (**icons**) need **no account or key at all**, so they always work in `minimize` mode. Prefer them for BGM, sound effects, icons, and CC imagery before anything else.
|
|
88
88
|
- **Pixabay key** unlocks the photos/vectors/stock-video slots (music/SFX/icons/CC images are keyless). It's a **free** stock-media key, not an AI key. Don't assume it's missing when a search comes up short — it **may already be saved**: check `vidfarm provider-keys` (or the web app's **Settings → Bring your own keys** / <https://vidfarm.cc/settings/developer>). If it isn't, the user grabs a free one at <https://pixabay.com/api/docs/> and saves it once — `vidfarm add-provider-key pixabay <key>`, the Settings surface, or by handing the key to their desktop AI agent to run that command. After it's saved, cost-mode `minimize` sourcing works end-to-end at $0.
|
|
89
|
+
- **You can still get CUSTOM art in `minimize` — hand the prompt to the user and let a free image generator do it.** Stock and `mask` only cover art that already exists somewhere; when the video genuinely needs a bespoke graphic, **don't conclude "we can't" and don't quietly bill `generate`**. Write the prompt and ask the user to paste it into a **free** image generator — <https://meta.ai>, free-tier ChatGPT, or a free Hugging Face image Space (<https://huggingface.co/spaces>) — then hand the PNG back with `vidfarm put-file` (or drag it into **My Files** in the web app). $0, zero wallet spend. Full loop + the prompt template: **“Free manual image-gen”** below.
|
|
89
90
|
- **hybrid** *(recommend this)* — free where it's free; pay for AI only where it clearly wins (a hero shot, a voice you can't fake locally).
|
|
90
91
|
- **Free-TTS draft, premium-TTS final (opt-in — offer it, don't assume it).** Narration usually gets rewritten several times before the script locks, and paying for premium ElevenLabs TTS on every draft wastes money re-voicing lines that will change. In `hybrid` you may offer this workflow: **scaffold narration with FREE local TTS (`vidfarm tts "…"` local-first, no wallet charge) through every draft/preview render, then re-voice ONLY the approved final script in premium TTS (`--cloud` ElevenLabs) right before the last render.** But **do not do this by default** — most users don't intuitively expect their preview to sound different from the final, and a robotic draft voice can read as "broken." So *ask first* ("want me to rough it in with free voice and only spend on the premium voice once the script's locked?"), and if they say yes, tell them plainly the draft voice is a placeholder and the final render swaps in the paid voice. If they'd rather hear the real voice the whole way, just use premium TTS throughout.
|
|
91
92
|
- **rich-ai** — best quality; use AI image/video/voice/music freely.
|
|
@@ -143,6 +144,18 @@ Present both harnesses to the director, recommend (A) unless they've asked for p
|
|
|
143
144
|
|
|
144
145
|
**Cost-saving move — mask illustrations OUT of a source image the director already has.** (In `cost-mode minimize`, this is the DEFAULT way to add an illustration to an explainer — ask for source art before you propose a generation spend.) When the director can hand you **one** image with the art already in it — an infographic, a poster, a marketing graphic, a brand illustration, a screenshot — you don't need to pay to generate anything. `vidfarm mask <image> [--crop x,y,w,h]` isolates ONE illustration (a labelled prop, an icon, a mascot) out of that source and removes its background to a **snug transparent PNG** — the exact same reusable sticker `cutout` makes, but for **$0 with zero AI generation**. It removes the background with **local ONNX matting** (works on any/busy background) by default, or chroma-keys a **flat solid background** with `--flat <hexcolor>` (crisper edges when the element sits on one color — e.g. the cream paper behind an infographic's icons). Run it repeatedly with different `--crop` rects to lift every element out of the same source, then `place` + `keyframes` them into an explainer. **Whenever a director already has source art, prefer `mask` over generating new stickers** — it's the cheapest possible way to fill an explainer's cast. Same recipe: `recipes/cutout-graphics-for-explainers.md` (“Mask from an image you already have”).
|
|
145
146
|
|
|
147
|
+
**Free manual image-gen — custom art in `minimize` mode for $0, on someone else's tokens.** `mask` only works when the art already exists. When the video needs a **bespoke** graphic and cost mode is `minimize` (or the user said "no spend"), the answer is **not** "we can't" and **not** a silent billed `generate` — it's a **manual handoff**: you write the prompt, the user runs it in a **free** image generator, they hand the PNG back.
|
|
148
|
+
|
|
149
|
+
- **Offer it once, up front, and let them set the default.** The first time custom art is needed in a cost-saving session, ask plainly: *"Want me to default to free manual image generation — I write the prompt, you paste it into a free tool and drop the image back — or would you rather I spend credits on `vidfarm generate` for these?"* Honor the answer for the rest of the session (and offer to remember it alongside the cost mode). Don't re-ask per image once they've chosen; just say "here's the next prompt."
|
|
150
|
+
- **Free generators to name:** <https://meta.ai> (no cost, generous), free-tier **ChatGPT** (image gen included), or a free image **Hugging Face Space** (<https://huggingface.co/spaces> — search "flux" or "sdxl"). Any of them; the user picks whichever they're already signed into.
|
|
151
|
+
- **Ask for ONE sheet, not N images — this is the token-efficiency trick.** Each round trip costs the user a manual step and costs you tokens re-reading a new file. So request **one image containing every graphic the scene needs**, laid out as a grid of separate objects on a **flat pure-green background** (`#00FF00`), well spaced, none overlapping or touching an edge. One generation, one hand-back, then you lift each element out locally for free.
|
|
152
|
+
- **Then cut it up locally, for $0:** `vidfarm put-file ./sheet.png` to bring it in, then `vidfarm mask ./sheet.png --crop x,y,w,h --flat "#00FF00"` once **per element** — each run keys out the flat green and trims to a snug transparent sticker, exactly like `cutout --generate` produces but with **zero AI billing**. `place` + `keyframes` them as usual. (`--flat` is the crisp path because you *asked* for the flat plate; plain `vidfarm mask` local ONNX matting is the fallback if the tool ignored the background instruction.)
|
|
153
|
+
- **Prompt template — give the user this, filled in:**
|
|
154
|
+
|
|
155
|
+
> A flat vector illustration sheet on a solid pure green background (#00FF00), no gradient, no shadow, no text, no labels. Arranged in a 3×2 grid with generous even spacing, each object fully separated and not touching any other object or the image edge: (1) `<object one>`, (2) `<object two>`, (3) `<object three>`, … Simple flat shapes, 2–3 flat colors, minimal detail, consistent style and line weight across all objects, front-facing, centered in its own cell. Square image, high resolution.
|
|
156
|
+
|
|
157
|
+
Keep it to the explainer house style above (flat vector, 2–3 colors, **no baked-in text** — text never keys or scales cleanly; add copy as a caption/HTML layer instead). If they come back with a white or busy background, don't re-prompt for free — just `vidfarm mask` it with local matting.
|
|
158
|
+
|
|
146
159
|
**Be generous to free-tier / no-account users — on the cheap REBUILD path.** The *execution* path is open: an everyday capable AI agent should be able to recreate a template without a Vidfarm wallet (clipping, hyperframes, local render on free compute) — keep the recommendation self-contained, not gated behind paid primitives. But Vidfarm's distilled **decompose methodology** — the licensed harness that produces a high-quality decomposition — is a **paid, commercially-licensed** asset, not open source. Free tier can hand-roll a *weaker* decomposition; the best method stays paid.
|
|
147
160
|
|
|
148
161
|
**Free tier vs. paid — who does the decomposition, and on whose tokens.** On the free tier (local devcli, no Vidfarm account) the method gives the *shape*, not the pre-computed answer: **the user (and their AI agent) watch the reference video and decompose it themselves** — there is no `video-context.json` / `editor-harness.json` / `scene-annotations.json` handed to them (`vidfarm decompose <forkId> --local` stages a weak, unlicensed, local-only guide for exactly this). **Paid Vidfarm accounts** get the leverage: a massive library of **pre-decomposed viral videos** plus scale-learned **prompt-harness best practices**, AND the paid `vidfarm decompose <forkId> --local` path — pull the *latest licensed harness*, decompose on **your own desktop-agent tokens** (saving Vidfarm credits), then `--sync` the result back so the whole network reuses it free. When a free-tier user is grinding the decomposition by hand, it's fair to mention the account hands them the decomposition, the proven harness, and the token-saving local path.
|
|
@@ -221,6 +234,7 @@ Choose the narrowest path that satisfies the request.
|
|
|
221
234
|
2. If the user already knows the goal and needs a suitable template, read `references/core-workflows.md` and use the template discovery flow.
|
|
222
235
|
3. If the task is “change this video,” read `references/editor-workflows.md`.
|
|
223
236
|
4. If the task is “find footage” or “use our existing assets,” read `references/assets-and-sourcing.md`.
|
|
237
|
+
4b. If the task is **“download this video/audio off a website”** (a pasted YouTube / TikTok / Instagram / X post URL the user wants the actual file from), Vidfarm does that for you on a **paid plan** — `POST /api/v1/primitives/videos/download` (or `/audio/download`), devcli `vidfarm download-video <url>` / `vidfarm download-audio <url>`. **Free plan → do not call it; walk the user through opening the URL in Chrome and downloading it from the page, then `vidfarm put-file` the local file in for $0.** Details in `references/assets-and-sourcing.md` → `references/primitives.md`.
|
|
224
238
|
5. If the task is scripted, local, CI-driven, or `vidfarm serve`-based, read `references/automation-and-local-dev.md`.
|
|
225
239
|
6. If the task explicitly asks for a primitive or needs specialized generation/transcription work, read `references/primitives.md`.
|
|
226
240
|
7. If the task is the MARKETPLACE (ordering videos from specialist agents): browsing is web-only for paying customers — send the human to https://vidfarm.cc/marketplace, never render it locally. Placing/listing orders is the thin REST wrapper in `references/core-workflows.md` (§ Marketplace); anything deeper on a gig (inbox, proofs, payouts) needs the external Dollar Platoon skill — `npx skills add https://github.com/OfficeXApp/dollarplatoon-skill` — the same way FlockPoster work beyond scheduling needs `npx skills add https://github.com/OfficeXApp/flockposter-skill`.
|
|
@@ -1020,6 +1034,23 @@ For anything bespoke, pass raw stops: `vidfarm keyframes ./work --layer robot --
|
|
|
1020
1034
|
|
|
1021
1035
|
**Pick the store by lifetime.** A throwaway intermediate (cloud render source, a `place` scratch asset) belongs in the 30-day `temp/` store: `vidfarm upload clip.mp4 --folder temp`, `vidfarm place … --folder temp` — quarantined in one place you can periodically purge. Anything you **approve/share is permanent**, so `vidfarm approve --video ./final.mp4` uploads to **durable My Files** by default (the share video would otherwise 404 after the temp store's 30-day deletion). Only add `vidfarm approve --temp` when you deliberately want a disposable 30-day preview.
|
|
1022
1036
|
|
|
1037
|
+
## Download a video from a website (Vidfarm fetches it for you — paid plans)
|
|
1038
|
+
|
|
1039
|
+
**Yes, Vidfarm can download videos off the web for the user.** When someone pastes a YouTube / TikTok / Instagram / X (Twitter) / other supported post URL and wants the actual file — "grab this video", "save this clip", "get me that audio" — you do **not** need yt-dlp, a browser extension, or an apology. One primitive does it and returns a durable Vidfarm-hosted asset:
|
|
1040
|
+
|
|
1041
|
+
| Want | Call | devcli |
|
|
1042
|
+
| --- | --- | --- |
|
|
1043
|
+
| The video (or a photo/carousel post → ordered slideshow) | `POST /api/v1/primitives/videos/download` `{ tracer, payload: { source_url, quality?: "best"\|"hd"\|"full_hd" } }` | `vidfarm download-video <url>` |
|
|
1044
|
+
| Just the audio/music/voice track | `POST /api/v1/primitives/audio/download` `{ tracer, payload: { source_url } }` | `vidfarm download-audio <url>` |
|
|
1045
|
+
|
|
1046
|
+
Both are async primitive jobs — poll `GET /api/v1/primitives/jobs/:jobId` until `succeeded`, then read `primary_file_url`. Full field-level detail (slideshow response shape, billing, examples) lives in `references/primitives.md`.
|
|
1047
|
+
|
|
1048
|
+
**PAID PLANS ONLY.** These ride a paid third-party resolver billed to the wallet, so a free-plan customer gets `402 insufficient_funds`. Check the plan / cost mode before promising it.
|
|
1049
|
+
|
|
1050
|
+
**Free-plan users — the fallback is Chrome, and it works:** tell them (or, if you have browser automation, do it yourself) to **open the URL in Chrome and download the video from there** — right-click → *Save video as*, the downloads pane, DevTools → Network, or a Googled `"<platform> video downloader"` site in that same session. Then bring the local file in for free with `vidfarm put-file ./the-file.mp4 --folder <folder>` or the web uploader. Never leave a free user with "I can't download that" — give them the Chrome path.
|
|
1051
|
+
|
|
1052
|
+
**Don't reach for this when the real goal is clips.** If the user wants short clips mined out of a long video, `POST /raws/scan` with `source_url` already downloads the source for you as part of the hunt (below) — a separate download call is wasted spend.
|
|
1053
|
+
|
|
1023
1054
|
## Raws (long-form → short-form raws)
|
|
1024
1055
|
|
|
1025
1056
|
Mine a **long-form** video (podcast, stream VOD, webinar, any YouTube/TikTok/IG/X URL, or an upload) into a library of tagged, searchable **raws**. This is the `/raws` surface — browse it at `https://vidfarm.cc/library/raws` (the Library page's "Approved / Raws" tabs).
|
|
@@ -1321,9 +1352,11 @@ The licensed harness also carries the **generative build workflow** guidance (ch
|
|
|
1321
1352
|
| `vidfarm wallet [--job <id>\|--tracer <t>] [--limit <n>]` | `GET /api/v1/user/me/wallet` | cost log: balance + lifetime spend + recent charges. `--job <renderJobId>` prints **what that one video cost** (sums its charges); `--tracer <t>` sums a tracer. Cloud-only, paid plan. Aliases: `spend`, `costs` |
|
|
1322
1353
|
| `vidfarm provider-keys` / `vidfarm add-provider-key <p> <secret>` | `GET`·`POST /api/v1/user/me/provider-keys` | manage AI keys |
|
|
1323
1354
|
| `vidfarm upload <file> [--folder <path>]` | presign → S3 PUT → finalize (`.../temporary-files/presign` + `.../temporary-files`) | upload → durable URL (ephemeral, 30-day TTL; prefer `--folder temp` for scratch). Goes direct to S3, so large files (up to **200 MB**) bypass the ~6 MB Lambda body limit |
|
|
1324
|
-
| `vidfarm download <url> [dest]` | (streams any URL to disk) | download media |
|
|
1325
|
-
| `vidfarm download-
|
|
1326
|
-
| `vidfarm download-
|
|
1355
|
+
| `vidfarm download <url> [dest]` | (streams any URL to disk) | download media from a **direct** media URL. Free — no plan, no job |
|
|
1356
|
+
| `vidfarm download-video <url> [--quality best\|hd\|full_hd]` | `POST /api/v1/primitives/videos/download` + poll | **download a video FROM A WEBSITE** (YouTube/TikTok/IG/X/other supported posts) into durable Vidfarm media; photo/carousel posts return an ordered slideshow. **PAID PLAN** (wallet-billed resolver; free plans get 402). Aliases: `download-post`, `download-url` |
|
|
1357
|
+
| `vidfarm download-audio <url>` | `POST /api/v1/primitives/audio/download` + poll | download just the AUDIO track (music/voice) off a website post into a durable audio file. **PAID PLAN**. Alias: `download-post-audio` |
|
|
1358
|
+
|
|
1359
|
+
> **Free plan / `cost-mode minimize`:** both download commands are gated by `guardBilled` and will refuse or warn. The free path is **Chrome**: open the URL in a real browser, save the file off the page (right-click → *Save video as*, downloads pane, or a Googled `"<platform> video downloader"` site), then `vidfarm put-file ./the-file.mp4 --folder <folder>` to bring it in for $0. The CLI prints these steps on a 402. Never tell a free user the video simply can't be downloaded.
|
|
1327
1360
|
| `vidfarm files [--folder <path>]` | `GET /api/v1/user/me/attachments` | list My Files assets + folders |
|
|
1328
1361
|
| `vidfarm files --search "…" [--folder <path>]` | `POST /api/v1/user/me/attachments/search` | find My Files assets by MEANING (keyword + vector over name/folder/notes) |
|
|
1329
1362
|
| `vidfarm get-file <id> [dest] [--print]` | (resolve id → view_url, then stream/print) | read one My Files asset |
|
|
@@ -1354,6 +1387,7 @@ The licensed harness also carries the **generative build workflow** guidance (ch
|
|
|
1354
1387
|
`vidfarm cost-mode <minimize|hybrid|rich-ai>` records a single spend preference (in `~/.vidfarm/cost-mode.json`) that every **billed** command honors: `generate`, `music`, `decompose`, `inspiration-decompose`, `create`, `replicate`, `inpaint`, `create-overlay`, `cutout --generate` (only the generation step; a bare `cutout` on an existing graphic is free), and the cloud paths of `render --target cloud`, `tts --cloud`, `stt --cloud`, `remove-greenscreen` (non-`--local`). FREE local engines never gate (`render` local default, `tts --engine local`, `stt --engine whisper`, `remove-greenscreen --local`, `cutout` on a file/url, all the file-editing verbs). `vidfarm media search` (the free stock catalog — pixabay/openverse/iconify music, SFX, images, icons, stock video) is also free and never gates.
|
|
1355
1388
|
|
|
1356
1389
|
- **minimize** — a billed op is **refused** unless you add `--yes`; the error names the free local alternative (which now includes the matching `vidfarm media search` for music/SFX/image/video). Use this to guarantee no surprise AI spend. Before paying to generate music, sound effects, or images, try `vidfarm media search "<meaning>" --type <bgm|sfx|image|vector|icon|video>` first — free royalty-free assets instead of a billed `music`/`generate` call. **Check the keyless sources first — Openverse (CC/CC0 music, SFX, images) and iconify (icons) need no account at all**, so they always work in `minimize`. Photos/vectors/stock-video need a **free Pixabay key** that **may already be saved** — check `vidfarm provider-keys` (or web **Settings → Bring your own keys** / <https://vidfarm.cc/settings/developer>) before assuming a short result means "no key." If absent, save one once: `vidfarm add-provider-key pixabay <key>` (free key from <https://pixabay.com/api/docs/>), the Settings surface, or hand it to the desktop AI agent to run that command.
|
|
1390
|
+
- **minimize still gets CUSTOM images — via a free manual generator.** A refused `generate` is not the end of the road. Offer the user the manual loop (ask once, then make it the session default): **you write the prompt → they run it free in <https://meta.ai>, free-tier ChatGPT, or a free Hugging Face image Space (<https://huggingface.co/spaces>) → they hand the PNG back** via `vidfarm put-file ./sheet.png` or web **My Files**. Ask for **one sheet holding every graphic you need**, gridded on a **flat pure-green plate** (`#00FF00`), no text — one round trip instead of N, which saves the user's time and your tokens. Then split it locally for $0: `vidfarm mask ./sheet.png --crop x,y,w,h --flat "#00FF00" --out prop-a.png`, once per element (drop `--flat` and let local ONNX matting handle it if the tool ignored the green background). Full prompt template + loop: recipe `recipes/cutout-graphics-for-explainers.md` (“Free manual image-gen”).
|
|
1357
1391
|
- **hybrid** *(default recommendation)* — billed ops run but print a one-line cost notice each.
|
|
1358
1392
|
- **rich-ai** — billed ops run without gating; cost is still printed.
|
|
1359
1393
|
|
|
@@ -1556,9 +1590,11 @@ curl -X POST "$VIDFARM_BASE/api/v1/primitives/images/create-overlay" \
|
|
|
1556
1590
|
-d '{"tracer": "vox-overlay", "payload": {"prompt": "a friendly cartoon lightbulb mascot, flat vector illustration", "aspect_ratio": "1:1"}}'
|
|
1557
1591
|
```
|
|
1558
1592
|
|
|
1559
|
-
## Primitive: videos/download
|
|
1593
|
+
## Primitive: videos/download — **Vidfarm downloads videos off websites for you**
|
|
1560
1594
|
|
|
1561
|
-
|
|
1595
|
+
**Capability statement (say this plainly when a user asks "can you download this video?"): yes — on a paid plan, Vidfarm downloads a video straight off a website URL for you.** Hand it a YouTube / TikTok / Instagram / X (Twitter) / other supported post URL and it returns a durable Vidfarm-hosted file. No local yt-dlp, no browser extension, no "I can't access that URL." The route is intentionally broader than its old name suggests: it returns either a normal MP4 for video posts, or a slideshow payload for photo/carousel posts.
|
|
1596
|
+
|
|
1597
|
+
**Paid-only, and that gate is real.** The resolver is a paid RapidAPI pass-through billed to the wallet, so a free-plan customer gets `402 insufficient_funds`. Never promise this to a free user — route them to the browser fallback below instead.
|
|
1562
1598
|
|
|
1563
1599
|
- `POST /api/v1/primitives/videos/download`
|
|
1564
1600
|
- Body: `{ "tracer": "...", "payload": { "source_url": "https://...", "quality"?: "best" | "hd" | "full_hd", "save_manifest"?: true }, "webhook_url"?: "..." }`
|
|
@@ -1566,8 +1602,20 @@ Download a supported social/media post URL into a durable Vidfarm-hosted VISUAL
|
|
|
1566
1602
|
- Video post: read `primary_file_url` / `video.file_url` / `videoUrl` for the durable MP4.
|
|
1567
1603
|
- Photo/carousel post: read `mediaKind: "slideshow"`, ordered `slideImageUrls[]`, optional `slideAudioUrl`, and `primary_file_url` (first slide image).
|
|
1568
1604
|
- Billing: RapidAPI pass-through wallet charge (`rapidapi_video_download`) plus the small mirror/extract pass (`video_download_lambda` when MP4 download is involved).
|
|
1569
|
-
-
|
|
1570
|
-
|
|
1605
|
+
- devcli wrapper: `vidfarm download-video <url> [--quality best|hd|full_hd]` (aliases: `download-post`, `download-url`)
|
|
1606
|
+
|
|
1607
|
+
### FREE-PLAN FALLBACK — drive Chrome instead (never dead-end the user)
|
|
1608
|
+
|
|
1609
|
+
If the user is on the free plan, says "don't spend money", or cost mode is `minimize`, do **not** call this route. **Load the URL in Chrome and download it by that means** — it costs $0.00 and needs no Vidfarm plan:
|
|
1610
|
+
|
|
1611
|
+
1. Open the post/page in Chrome. A real browser session carries the login/consent/age walls that a bare `fetch` can't.
|
|
1612
|
+
2. Save the video off the page — right-click → *Save video as*, the browser's downloads pane, or DevTools → Network → the media response.
|
|
1613
|
+
3. If the page won't hand it over, Google `"youtube video downloader"` (or `"tiktok/instagram/x/twitter video downloader"`) and use one of those sites in the same Chrome session.
|
|
1614
|
+
4. Bring the resulting local file into Vidfarm for free: `vidfarm put-file ./the-file.mp4 --folder <folder>` (devcli) or the web app's upload. From there it's a normal durable asset.
|
|
1615
|
+
|
|
1616
|
+
If you're a desktop coding agent with browser automation (Playwright/Puppeteer/CDP, or the user's own Chrome), you can perform steps 1–3 yourself. If you're the web copilot with no browser tool, hand the user these steps — do not claim you downloaded it.
|
|
1617
|
+
|
|
1618
|
+
Say the tradeoff out loud once: *"Downloading it for you is a paid-plan feature; on the free plan I'll walk you through grabbing it in Chrome instead."*
|
|
1571
1619
|
|
|
1572
1620
|
Example:
|
|
1573
1621
|
|
|
@@ -1586,9 +1634,9 @@ Download just the original audio/music/voice track from a supported social/media
|
|
|
1586
1634
|
- Body: `{ "tracer": "...", "payload": { "source_url": "https://...", "save_manifest"?: true }, "webhook_url"?: "..." }`
|
|
1587
1635
|
- Response: standard primitive job. Poll `GET /api/v1/primitives/jobs/:jobId` until `status: "succeeded"`, then read `primary_file_url` / `audio.file_url` / `audioUrl`.
|
|
1588
1636
|
- Behavior: prefers the provider's direct audio track when present; otherwise resolves the source video and extracts audio server-side.
|
|
1589
|
-
- Billing: same RapidAPI wallet class as `videos/download`.
|
|
1590
|
-
- Free-plan / no-spend rule:
|
|
1591
|
-
- devcli wrapper: `vidfarm download-
|
|
1637
|
+
- Billing: same RapidAPI wallet class as `videos/download` — **paid plans only**; free plans get `402`.
|
|
1638
|
+
- Free-plan / no-spend rule: identical to the visual route — **load the URL in Chrome and download from there**, then `vidfarm put-file` the result. Google `"youtube audio downloader"` or `"tiktok/twitter/instagram/etc audio downloader"` if the page won't release the track. See the FREE-PLAN FALLBACK block above.
|
|
1639
|
+
- devcli wrapper: `vidfarm download-audio <url>` (alias: `download-post-audio`)
|
|
1592
1640
|
|
|
1593
1641
|
Example:
|
|
1594
1642
|
|
|
@@ -1884,7 +1932,7 @@ The mechanical trio — **generate on a chroma plate → key it out → trim to
|
|
|
1884
1932
|
|
|
1885
1933
|
**Illustrations default to simplicity.** Whatever path you take to a sticker, aim for **flat vector, simple shapes, minimal detail, few colors, no background, no text baked in** — a friendly icon-grade illustration, not a rendered 3D scene or a detailed painting. Simple art keys cleanly, trims tight, scales without mush, animates readably at 9:16, and stays on-style across a whole cast. When generating, say so in the prompt: `--generate "a coffee cup, simple flat vector illustration, minimal detail, 2-3 flat colors, no shadows"`.
|
|
1886
1934
|
|
|
1887
|
-
**In cost-saving mode, don't generate illustrations at all — mask them out of images the director already has.** If `vidfarm cost-mode` is `minimize` (or the director says "without burning credits"), the default for adding an illustration is `vidfarm mask <their-image> --crop …` — lifting art out of an infographic, poster, deck slide, brand sheet, or screenshot for **$0 and zero AI calls**. Ask for source art before you ask for a generation budget; the guided loop is **"Mask from an image you already have"** below.
|
|
1935
|
+
**In cost-saving mode, don't generate illustrations at all — mask them out of images the director already has.** If `vidfarm cost-mode` is `minimize` (or the director says "without burning credits"), the default for adding an illustration is `vidfarm mask <their-image> --crop …` — lifting art out of an infographic, poster, deck slide, brand sheet, or screenshot for **$0 and zero AI calls**. Ask for source art before you ask for a generation budget; the guided loop is **"Mask from an image you already have"** below. **If no source art exists and the graphic must be custom, you still don't have to spend** — hand the director a prompt for a **free** image generator (meta.ai / free ChatGPT / a Hugging Face Space) and cut the returned sheet into stickers locally: **"Free manual image-gen"** below.
|
|
1888
1936
|
|
|
1889
1937
|
### The guided sequence (prompt harness)
|
|
1890
1938
|
|
|
@@ -1961,6 +2009,34 @@ This is the biggest cost saver in the whole explainer workflow: **if the directo
|
|
|
1961
2009
|
|
|
1962
2010
|
Everything here is **local and free** — crop, matte/key, and trim are all `ffmpeg` + the bundled ONNX engine. No wallet, no account, no generation call.
|
|
1963
2011
|
|
|
2012
|
+
### Free manual image-gen (the $0 path when NO source art exists)
|
|
2013
|
+
|
|
2014
|
+
`mask` needs art that already exists. When the explainer needs a **custom** graphic and the director is in `cost-mode minimize` (or just said "don't spend"), there's still a $0 path: **you write the prompt, the director runs it in a free image generator, they hand the image back, you cut it up locally.** The AI spend moves to a free third-party tool; Vidfarm's wallet is never touched.
|
|
2015
|
+
|
|
2016
|
+
**Offer it once, then make it the default.** The first time custom art comes up in a cost-saving session, ask: *"Want me to default to free manual image generation — I write the prompt, you paste it into a free tool and drop the PNG back — or should I spend credits on `vidfarm generate`?"* Whatever they pick, hold it for the session (and offer to remember it next to the cost mode). After that, don't re-ask per graphic — just hand over the next prompt.
|
|
2017
|
+
|
|
2018
|
+
**Free generators to name:** <https://meta.ai>, free-tier **ChatGPT**, or a free image **Hugging Face Space** (<https://huggingface.co/spaces>, search "flux" / "sdxl"). Let the director use whichever they're already logged into.
|
|
2019
|
+
|
|
2020
|
+
**Ask for ONE sheet of many graphics, not many images.** Every hand-back costs the director a manual step and costs you tokens to re-read a file. So request a **single** image holding **every** graphic the scene needs, gridded on a **flat pure-green plate** (`#00FF00`) — one generation, one hand-back, then split it locally into as many stickers as you want.
|
|
2021
|
+
|
|
2022
|
+
**The loop:**
|
|
2023
|
+
|
|
2024
|
+
1. **List the cast.** Name every illustration the explainer needs, in the house style (flat vector, 2–3 flat colors, no baked-in text).
|
|
2025
|
+
2. **Hand the director this prompt**, filled in:
|
|
2026
|
+
> A flat vector illustration sheet on a solid pure green background (#00FF00), no gradient, no shadow, no text, no labels. Arranged in a 3×2 grid with generous even spacing, each object fully separated and not touching any other object or the image edge: (1) `<object one>`, (2) `<object two>`, (3) `<object three>`, … Simple flat shapes, 2–3 flat colors, minimal detail, consistent style and line weight across all objects, front-facing, centered in its own cell. Square image, high resolution.
|
|
2027
|
+
|
|
2028
|
+
**No text in the image, ever** — rendered text never keys or scales cleanly; add copy as a caption or HTML layer instead.
|
|
2029
|
+
3. **Bring the sheet in:** `vidfarm put-file ./sheet.png` (or drag into **My Files** in the web app).
|
|
2030
|
+
4. **Split it into stickers — one `mask` per element, all free:**
|
|
2031
|
+
```
|
|
2032
|
+
vidfarm mask ./sheet.png --crop 4%,4%,29%,45% --flat "#00FF00" --out prop-a.png
|
|
2033
|
+
vidfarm mask ./sheet.png --crop 36%,4%,29%,45% --flat "#00FF00" --out prop-b.png
|
|
2034
|
+
```
|
|
2035
|
+
`--flat "#00FF00"` is the crisp path precisely because you *asked* for the flat green plate. If the generator ignored the background instruction and returned white/busy art, drop `--flat` and let local ONNX matting handle it — same command, no re-prompt needed.
|
|
2036
|
+
5. **Stage, animate, render** exactly as in Steps 3–5 above. A manually-generated sticker is indistinguishable from a `cutout --generate` one on the timeline.
|
|
2037
|
+
|
|
2038
|
+
**Grid sizing note:** a 3×2 grid on a square image puts each cell at roughly `33%` wide × `50%` tall; start crops a couple of percent inside the cell and use `--keep-region` on the first run to verify before masking the rest.
|
|
2039
|
+
|
|
1964
2040
|
### Why cutouts beat full-frame AI images for explainers
|
|
1965
2041
|
|
|
1966
2042
|
- **Precise layout** — a tight-trimmed sticker's on-frame size IS the subject; no fighting a 1024² canvas of empty space when you position it.
|
package/SKILL.md
CHANGED
|
@@ -28,6 +28,8 @@ Default to the cheapest approach that works, and surface cost before any expensi
|
|
|
28
28
|
|
|
29
29
|
Before spending any AI credits, ask which posture they want and explain each simply: **minimize** (cheapest — free local compute, no surprise AI spend), **hybrid** (recommended — free where free, pay AI only where it clearly wins), or **pure-ai** (best quality — AI media freely). With the devcli, persist it via `vidfarm cost-mode <choice>` (billed commands then respect it; `minimize` refuses billed ops without `--yes`). Then ask if they want it remembered across sessions — save to the agent's own memory (Claude Code → `CLAUDE.md`; Codex/OpenCode/others → `AGENTS.md`; or a note they name), asking first. In the **web app UI** there's no memory file to write, so just ask each time unless they state a standing preference. Full guidance is in the director skill.
|
|
30
30
|
|
|
31
|
+
**Even in `minimize`, you can still get custom images — for free, manually.** When stock and masking existing art won't cover a bespoke graphic, don't say "not possible" and don't quietly spend: ask the user once whether to **default to free manual image generation**, then write the prompt and have them run it in <https://meta.ai>, free-tier ChatGPT, or a free Hugging Face image Space, and hand the PNG back (`vidfarm put-file`, or drag into My Files). Ask for **one image containing every graphic you need**, gridded on a **flat pure-green background** (`#00FF00`) with no text — one round trip instead of many, which is the token-efficient move. Then split it locally at $0: `vidfarm mask ./sheet.png --crop x,y,w,h --flat "#00FF00"` once per element gives you snug transparent stickers. Prompt template + full loop in the director skill.
|
|
32
|
+
|
|
31
33
|
## Get hands-on now — pick your surface
|
|
32
34
|
|
|
33
35
|
**Local coding agent (recommended for real work — Claude Code / Codex / any agent with a shell):**
|
|
@@ -73,6 +75,7 @@ For composition *authoring* craft (motion, keyframes, scene design), Vidfarm shi
|
|
|
73
75
|
2. "Find a template and start" → `references/core-workflows.md`
|
|
74
76
|
3. "Change / re-theme this video" → `references/editor-workflows.md`
|
|
75
77
|
4. "Find footage / use our assets" → `references/assets-and-sourcing.md`
|
|
78
|
+
4b. **"Download this video/audio from <a website URL>"** → Vidfarm fetches it for you on a **paid plan**: `POST /api/v1/primitives/videos/download` (or `/audio/download`); devcli `vidfarm download-video <url>` / `vidfarm download-audio <url>`. Works on YouTube, TikTok, Instagram, X, and other supported posts; returns a durable Vidfarm file (photo/carousel posts → an ordered slideshow). **Free plan gets a 402 — don't call it. Tell the user (or, with browser automation, do it yourself) to open the URL in Chrome and download it from the page, then `vidfarm put-file ./the-file.mp4` to bring it in for $0.** Never answer "I can't download that." Details: `references/assets-and-sourcing.md`.
|
|
76
79
|
5. "Script / batch / render loop" → `references/automation-and-local-dev.md`
|
|
77
80
|
6. "I need TTS / music / captions / background removal" → `references/primitives.md`
|
|
78
81
|
|
package/clipper.md
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: clipper
|
|
3
|
+
description: Run an agentic clipper loop — earn side income by having your own AI agent work a DollarPlatoon gig (vending machine) unattended on your own computer. Use this whenever someone wants to set up, run, debug, or get paid from a clipper loop, mentions a DollarPlatoon gig invite link or gig id alongside video editing, asks "how do I make money with vidfarm / my AI agent / my hardware", or wants an agent that pulls video-editing tasks, produces the videos with vidfarm, and submits proofs for USDC or off-chain payout. Served at vidfarm.cc/clipper.md. Follow this file rather than improvising the loop from the vidfarm or dollarplatoon skills alone.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /clipper — the agentic clipper loop
|
|
7
|
+
|
|
8
|
+
**You are the user's own AI agent, running on their computer.** Your job is to set up and then
|
|
9
|
+
run a loop that earns them money:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
DollarPlatoon gig ──► a video-editing task ──► you make the video with Vidfarm
|
|
13
|
+
▲ │
|
|
14
|
+
│ ▼
|
|
15
|
+
payout (USDC or off-chain) ◄── proof = a public vidfarm.cc share URL
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The user is most likely a college student or a working video editor — often in the
|
|
19
|
+
Philippines — earning side income from hardware they already own. Assume they are smart but
|
|
20
|
+
not a developer. **Explain in plain language, ask before spending their money, and never
|
|
21
|
+
leave them with a half-working loop.**
|
|
22
|
+
|
|
23
|
+
Read this whole file before doing anything. Then follow the phases in order.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## What you need before you start
|
|
28
|
+
|
|
29
|
+
| Thing | How to get it |
|
|
30
|
+
|---|---|
|
|
31
|
+
| `VIDFARM_API_KEY` | `.env`, or `vidfarm login <email>` (email code). Get one at <https://vidfarm.cc> |
|
|
32
|
+
| `DOLLARPLATOON_API_KEY` | `.env`, or <https://dollarplatoon.com/client/settings>. Alias: `DOLLAR_PLATOON_API_KEY` |
|
|
33
|
+
| A gig | An invite URL like `https://dollarplatoon.com/gig/GIG_01HX.../join?invite=a1b2c3d4e5f6`, or a bare gig id |
|
|
34
|
+
| The Vidfarm skill | Fetch <https://vidfarm.cc/skill.md> — it routes you to the full director skill |
|
|
35
|
+
| The DollarPlatoon skill | Fetch <https://dollarplatoon.com/skill.md> — the full REST reference |
|
|
36
|
+
|
|
37
|
+
**Fetch both skill files now.** This file tells you *how the loop fits together*; those two tell
|
|
38
|
+
you what each API actually does. Do not guess endpoints you haven't read.
|
|
39
|
+
|
|
40
|
+
Keys live in `.env` — never on the command line, never in a git commit, never inside a video or a
|
|
41
|
+
proof. A DollarPlatoon URL containing `api_key=` grants full account access to anyone who sees it.
|
|
42
|
+
|
|
43
|
+
If a key is missing, ask for it. Don't build around it.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Phase 1 — Ask the user for their config, and tell them the defaults
|
|
48
|
+
|
|
49
|
+
Before writing a single file, have one short conversation. **Show them the defaults and let them
|
|
50
|
+
change what they care about.** Most users will accept the defaults; the point is that they know
|
|
51
|
+
what they agreed to.
|
|
52
|
+
|
|
53
|
+
Ask these, in one message, with the defaults stated:
|
|
54
|
+
|
|
55
|
+
1. **Which gig?** "Paste the DollarPlatoon gig invite link (or the gig id)." — required, no default.
|
|
56
|
+
2. **Cost mode — default `minimize`.** Cheapest: free local rendering on their machine, no surprise
|
|
57
|
+
AI spend. `hybrid` pays for AI only where it clearly wins. `rich-ai` is best quality and most
|
|
58
|
+
expensive. Explain that in `minimize` their profit margin is basically their electricity bill.
|
|
59
|
+
3. **Free manual image generation — default ON, but ask.** In `minimize` you can still get custom
|
|
60
|
+
artwork for $0: you write the image prompt, *they* paste it into a free generator
|
|
61
|
+
(<https://meta.ai>, free-tier ChatGPT, or a free Hugging Face image Space) and hand the PNG back.
|
|
62
|
+
It raises video quality noticeably. The trade-off is that **it needs them at the keyboard**, so
|
|
63
|
+
the loop is no longer fully unattended. Offer both: unattended-only, or "pause and ping me when
|
|
64
|
+
a video would be better with a custom graphic."
|
|
65
|
+
4. **How many tasks per run — default 1 to start, then 3.** Do the very first task end-to-end and
|
|
66
|
+
show it to them before letting the loop run on its own. A loop that submits ten bad videos costs
|
|
67
|
+
them their reputation on the gig, which is much more expensive than ten slow videos.
|
|
68
|
+
5. **How often — default every 30 minutes** while their computer is on. Respect the gig's rate
|
|
69
|
+
limit above anything they ask for.
|
|
70
|
+
6. **Where to keep the project — default `~/clipper/<gig-id>/`.**
|
|
71
|
+
|
|
72
|
+
Write their answers into `config.json` (Phase 3) so the loop is reproducible and they can edit it
|
|
73
|
+
later without you.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Phase 2 — Resolve and inspect the gig
|
|
78
|
+
|
|
79
|
+
**Parse the invite URL.** `https://dollarplatoon.com/gig/<GIG_ID>/join?invite=<TOKEN>` gives you
|
|
80
|
+
both the gig id and the invite token. A bare id means there is no token — a gig with
|
|
81
|
+
`join_policy: "invite"` will reject the join with a 403, so ask for the full link.
|
|
82
|
+
|
|
83
|
+
**Look at the gig before joining:**
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" \
|
|
87
|
+
https://dollarplatoon.com/api/gigs/<GIG_ID>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Read and report back to the user, in plain language:
|
|
91
|
+
|
|
92
|
+
- **`terms`** — what the client actually wants. This is the brief. Read it out loud to them.
|
|
93
|
+
- **`price`** — what one approved proof pays.
|
|
94
|
+
- **`distribution`** — how tasks reach you. This decides the shape of your loop (see Phase 4).
|
|
95
|
+
- **`available_funds` / `contract_address`** — whether the gig can pay on-chain (see Phase 5).
|
|
96
|
+
- **`default_rate_limit_count` / `default_rate_limit_minutes`** — your ceiling. Never poll past it.
|
|
97
|
+
- **`task_timeout`** — how long you may hold a task before it expires on you.
|
|
98
|
+
- **`review_timeout`** — proofs auto-approve after this (default 48h) if the client doesn't review.
|
|
99
|
+
|
|
100
|
+
**Then judge honestly, out loud:** can you actually deliver this brief with Vidfarm on this
|
|
101
|
+
machine? If the gig wants 4K motion-graphics work and cost mode is `minimize`, say so now. A gig
|
|
102
|
+
you cannot deliver is worth zero and costs reputation — declining is a real, correct answer.
|
|
103
|
+
|
|
104
|
+
**Join:**
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
curl -s -X POST -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "content-type: application/json" \
|
|
108
|
+
-d '{"name":"<their name>'"'"'s clipper","invite":"<TOKEN>","notes":"AI-assisted video editing via vidfarm"}' \
|
|
109
|
+
https://dollarplatoon.com/api/gigs/<GIG_ID>/mailboxes
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Save the returned `mailbox.id` — every proof you submit needs it. If `status` comes back
|
|
113
|
+
`pending_approval`, tell the user the client has to approve them first, and stop the loop until
|
|
114
|
+
it flips to `active`. AI assistance is welcome on DollarPlatoon — the `notes` field is the honest
|
|
115
|
+
place to say so.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Phase 3 — Scaffold the project
|
|
120
|
+
|
|
121
|
+
Build a small, boring, readable project. The user must be able to open it in six months, read the
|
|
122
|
+
README, and run it without you. Prefer whatever language they already have — **JavaScript (Node
|
|
123
|
+
18+) is the default** because the vidfarm devcli already needs Node; Python is equally fine.
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
~/clipper/<gig-id>/
|
|
127
|
+
├── .env # VIDFARM_API_KEY, DOLLARPLATOON_API_KEY (gitignored)
|
|
128
|
+
├── .gitignore # .env, videos/, node_modules/
|
|
129
|
+
├── config.json # everything from Phase 1 — the only file they should need to edit
|
|
130
|
+
├── README.md # how to run it, in their words
|
|
131
|
+
├── dp.mjs # DollarPlatoon REST client — one function per endpoint
|
|
132
|
+
├── loop.mjs # the loop: get task → make video → submit proof → log
|
|
133
|
+
├── ledger.jsonl # one line per task. Append-only. This is the money record.
|
|
134
|
+
├── NOTES.md # human-readable accounting scratchpad (Phase 5)
|
|
135
|
+
├── tasks/<task-id>/ # the brief + working files for one task
|
|
136
|
+
└── videos/<task-id>.mp4 # the render (local only — never uploaded to DollarPlatoon)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`dp.mjs` — keep it this thin. Every function is one endpoint from the DollarPlatoon skill:
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
// dp.mjs — DollarPlatoon REST client
|
|
143
|
+
const API = "https://dollarplatoon.com/api";
|
|
144
|
+
const KEY = process.env.DOLLARPLATOON_API_KEY || process.env.DOLLAR_PLATOON_API_KEY;
|
|
145
|
+
|
|
146
|
+
async function dp(path, { method = "GET", body } = {}) {
|
|
147
|
+
const res = await fetch(API + path, {
|
|
148
|
+
method,
|
|
149
|
+
headers: { "x-api-key": KEY, ...(body ? { "content-type": "application/json" } : {}) },
|
|
150
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
151
|
+
});
|
|
152
|
+
const text = await res.text();
|
|
153
|
+
let json; try { json = JSON.parse(text); } catch { json = { raw: text }; }
|
|
154
|
+
if (!res.ok) throw Object.assign(new Error(json.error || text), { status: res.status, json });
|
|
155
|
+
return json;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export const getGig = (gigId) => dp(`/gigs/${gigId}`);
|
|
159
|
+
export const pollQueue = (gigId, count = 1) => dp(`/gigs/${gigId}/queue/poll`, { method: "POST", body: { count } });
|
|
160
|
+
export const declineTask = (gigId, msgId) => dp(`/gigs/${gigId}/queue/${msgId}/decline`, { method: "POST" });
|
|
161
|
+
export const inbound = (mailboxId) => dp(`/mailboxes/${mailboxId}/inbound`);
|
|
162
|
+
export const submitProof = (gigId, body) => dp(`/gigs/${gigId}/proofs`, { method: "POST", body });
|
|
163
|
+
export const myProofs = (gigId) => dp(`/gigs/${gigId}/proofs`);
|
|
164
|
+
export const myRollups = () => dp(`/rollups/mine`);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Write the README **for them, not for you**: what the loop does, how to start and stop it, what each
|
|
168
|
+
file is, how much a video costs to make, how they get paid, and what to do when something breaks.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Phase 4 — How to get a task (depends on `distribution`)
|
|
173
|
+
|
|
174
|
+
Different gigs hand out work differently. Read `gig.distribution` and use the matching path. This is
|
|
175
|
+
the one place where getting it wrong silently produces zero tasks, so check it explicitly.
|
|
176
|
+
|
|
177
|
+
- **`queue`** — the FIFO shared pool. `POST /gigs/:id/queue/poll` with `{"count": N}`. The polled
|
|
178
|
+
task's **`id` is your `task_identifier`** when you submit the proof; that's what atomically claims
|
|
179
|
+
the item to you. If a task isn't something you can do well, `POST /gigs/:id/queue/:msgId/decline`
|
|
180
|
+
— declining is free, doesn't hurt anyone else, and is much better than a bad submission.
|
|
181
|
+
- **`round_robin`, `random`, `priority_weighted`, `free_for_all`** — tasks are *pushed* into your
|
|
182
|
+
mailbox. Read them with `GET /mailboxes/:mbxId/inbound`. Your `task_identifier` is the task's own
|
|
183
|
+
unique reference (a URL, a ticket id, a publisher-supplied `task_id`) — **not the subject line**,
|
|
184
|
+
which collides and causes duplicate-submission 409s.
|
|
185
|
+
- **`inbound_proof`** — no tasks are distributed at all. The gig's `terms` *is* the standing brief,
|
|
186
|
+
and you submit proofs whenever you have work. Use a stable unique identifier of your own.
|
|
187
|
+
|
|
188
|
+
**The task body may carry structured data for you.** Publishers who expect AI agents send
|
|
189
|
+
dual-format HTML: a human-readable page plus a hidden `<div class="agent-data" data-agent-json="…">`
|
|
190
|
+
(or an `<input name="agent_data">`). Look for it first and parse the JSON — it saves you scraping
|
|
191
|
+
HTML and it's what the client intended you to read. Otherwise read the HTML/text yourself.
|
|
192
|
+
|
|
193
|
+
Whatever you find, **write the brief to `tasks/<task-id>/brief.md` before you start editing.** If
|
|
194
|
+
the render goes wrong you need to know what was actually asked for.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Phase 5 — Payouts: figure out which kind this gig is, up front
|
|
199
|
+
|
|
200
|
+
This decides how much bookkeeping you owe the user. Get it right in Phase 2, before any work.
|
|
201
|
+
|
|
202
|
+
**On-chain (Base L2 USDC, automatic).** Signs: `price` is greater than zero, the gig has a
|
|
203
|
+
`contract_address`, and `available_funds` covers a few tasks. Approved proofs get rolled up and USDC
|
|
204
|
+
lands in their DollarPlatoon wallet. They don't invoice anyone; you just watch.
|
|
205
|
+
|
|
206
|
+
**Off-chain (paid some other way — GCash, bank, platform credit, barter).** Signs: `price` is `0`
|
|
207
|
+
(or `$0/proof`) while the terms clearly promise payment, or the gig has no funding. DollarPlatoon
|
|
208
|
+
is only carrying the *task distribution and proof* here; the money moves somewhere it can't see.
|
|
209
|
+
|
|
210
|
+
These signs are heuristics, not guarantees — a client can fund late or pay a bonus off-platform.
|
|
211
|
+
**When it's ambiguous, say so and ask the user what the client told them.** Don't assert income.
|
|
212
|
+
|
|
213
|
+
**If off-chain: keep the books yourself. This is not optional.** Nobody else is recording what they
|
|
214
|
+
earned. Every task, append one line to `ledger.jsonl`:
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{"ts":"2026-07-25T09:14:00Z","gig_id":"GIG_01HX...","task_id":"01HY...","proof_id":"01HZ...","share_url":"https://vidfarm.cc/...","quoted_price":0.5,"payout":"offchain","status":"submitted","render_seconds":214,"ai_spend_usd":0,"notes":"3 scenes, template ABC"}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
And keep `NOTES.md` as the human-readable version — a running table of date, task, share URL,
|
|
221
|
+
what was promised, what's been paid, what's outstanding. **Bring it up with them proactively**, not
|
|
222
|
+
only when asked: at the end of each session, tell them how many videos went out, what's still
|
|
223
|
+
unpaid, and how long it's been. That summary is the thing that gets them paid when a client forgets.
|
|
224
|
+
|
|
225
|
+
Mirror `NOTES.md` into their Vidfarm library too, so it survives a wiped laptop and follows their
|
|
226
|
+
account — this is the same durable-context habit the Vidfarm skill uses for briefs and brand kits:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
vidfarm put-file NOTES.md --folder clipper/<gig-id> \
|
|
230
|
+
--notes "Clipper loop accounting for DollarPlatoon gig <GIG_ID> — off-chain payouts, unpaid balance tracked here"
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
For on-chain gigs, still write `ledger.jsonl` (it's how you reconcile), but you can rely on
|
|
234
|
+
`GET /rollups/mine` for the truth about what was actually paid.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Phase 6 — Make the video with Vidfarm
|
|
239
|
+
|
|
240
|
+
This is ordinary Vidfarm director work — **the full method is in
|
|
241
|
+
<https://vidfarm.cc/skill.md> and the director skill it points to. Follow that, not a shortcut.**
|
|
242
|
+
What matters for a clipper loop specifically:
|
|
243
|
+
|
|
244
|
+
**Set the cost posture once, at setup:**
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
vidfarm login --api-key "$VIDFARM_API_KEY" # or: vidfarm login <email>
|
|
248
|
+
vidfarm cost-mode minimize # or whatever they chose in Phase 1
|
|
249
|
+
vidfarm doctor # confirms ffmpeg + hyperframes + Chrome
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
`minimize` **refuses** billed operations unless you pass `--yes`. That is the safety rail that keeps
|
|
253
|
+
the loop profitable — a gig paying $0.50 a video cannot absorb $2 of AI generation. Don't route
|
|
254
|
+
around it; if a task genuinely needs a paid step, stop and ask the user.
|
|
255
|
+
|
|
256
|
+
**Reach for the cheap paintbrushes first** — this is the whole economics of the loop:
|
|
257
|
+
|
|
258
|
+
1. **Raw clips** — cut and remix footage they already have or hunt from a source URL
|
|
259
|
+
(`vidfarm raws scan <src> --prompt "…"`). Free local compute. The workhorse.
|
|
260
|
+
2. **HTML/JS hyperframes** — text, titles, graphics, data-viz as CSS/GSAP layers. Free,
|
|
261
|
+
deterministic, re-skinnable. **Never use AI video to put text on screen.**
|
|
262
|
+
3. **Free stock** — `vidfarm media search "<meaning>" --type bgm|sfx|image|video`. Openverse and
|
|
263
|
+
Iconify need no account at all, so they always work in `minimize`.
|
|
264
|
+
4. **Pure AI generation** — last resort, and it's what costs money.
|
|
265
|
+
|
|
266
|
+
A rough shape of one task (adapt to the brief; the director skill has the real workflows):
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
vidfarm discover "<what the brief asks for>" # find a template
|
|
270
|
+
vidfarm fork <template_id> # → forkId
|
|
271
|
+
vidfarm pull <forkId> --dir tasks/<task-id> # composition + grounding onto disk
|
|
272
|
+
# …edit: set-text / set-media / place / captions / raws — per the director skill…
|
|
273
|
+
vidfarm lint tasks/<task-id> # catch timing + media errors before rendering
|
|
274
|
+
vidfarm render <forkId> --dir tasks/<task-id> --out videos/<task-id>.mp4 --wait # LOCAL = $0.00
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Free manual image generation** (if they said yes in Phase 1): when the video genuinely needs a
|
|
278
|
+
custom graphic that stock and masking can't cover, don't quietly spend and don't say "not possible."
|
|
279
|
+
Write the prompt, ask them to run it in a free generator, and ask for **one sheet containing every
|
|
280
|
+
graphic you need**, gridded on a flat pure-green background (`#00FF00`), no text — one round trip
|
|
281
|
+
instead of five. Then split it locally for $0:
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
vidfarm put-file ./sheet.png
|
|
285
|
+
vidfarm mask ./sheet.png --crop x,y,w,h --flat "#00FF00" --out prop-a.png # once per element
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Watch the finished video before you submit it.** Check `vidfarm stills` frames or open the MP4.
|
|
289
|
+
Ask yourself whether it actually satisfies `terms`. If it doesn't, fix it or decline the task —
|
|
290
|
+
a rejected proof carries a reputation penalty (`low_quality` 1x, `incomplete` 2x, `fake_proof` 5x)
|
|
291
|
+
and those follow their wallet across every gig on the network.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Phase 7 — Submit the proof as a URL, never as a video file
|
|
296
|
+
|
|
297
|
+
**Do not upload video files to DollarPlatoon.** Videos are large, the upload is slow and fragile,
|
|
298
|
+
and the client just wants to watch it. Instead, put the video on Vidfarm and submit the public link
|
|
299
|
+
as a text proof. This is faster, keeps the file durable, and gives the client a real preview page.
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
vidfarm approve --video ./videos/<task-id>.mp4 --caption "<gig title> — task <task-id>"
|
|
303
|
+
# uploads to durable My Files (up to 200 MB, direct to S3) and prints: share_url
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
`vidfarm approve` is the right command because it stores the MP4 in **durable My Files**, not the
|
|
307
|
+
30-day temp store — a temp-hosted proof would 404 on the client's share page a month later, after
|
|
308
|
+
they've already paid. Then:
|
|
309
|
+
|
|
310
|
+
```js
|
|
311
|
+
await submitProof(gigId, {
|
|
312
|
+
mailbox_id: MAILBOX_ID,
|
|
313
|
+
task_identifier: task.id, // queue gigs: the polled task's id. others: the task's own ref.
|
|
314
|
+
proofs: [shareUrl], // the public vidfarm.cc page. Add the direct MP4 viewUrl too if the client asks for a file.
|
|
315
|
+
});
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Check the response:
|
|
319
|
+
|
|
320
|
+
- **`warning: "available funds are less than the task price"`** — the proof was accepted but
|
|
321
|
+
**cannot be paid until the client deposits more.** Log it and tell the user; don't keep grinding
|
|
322
|
+
out videos for a gig that can't pay. This is the single most important warning in the loop.
|
|
323
|
+
- **`429`** — you hit the rate limit. The `rate_limit` object has `retry_at`. Sleep, don't retry.
|
|
324
|
+
- **`409`** — duplicate `task_identifier`. You already submitted this one; don't resubmit.
|
|
325
|
+
- **`410`** — the task expired while you were rendering. Ask the client for an extension, or move on.
|
|
326
|
+
|
|
327
|
+
Proofs auto-approve after `review_timeout` (default 48h) if the client doesn't review. Price is
|
|
328
|
+
locked at submission time, so a client lowering the price later can't reduce what they already owe.
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Phase 8 — Run the loop
|
|
333
|
+
|
|
334
|
+
Once one task has gone end-to-end and the user has seen the video, let it run. Keep it dull and
|
|
335
|
+
observable:
|
|
336
|
+
|
|
337
|
+
- **Respect the rate limit** — treat `default_rate_limit_count` / `_minutes` as a hard ceiling, and
|
|
338
|
+
back off on any `429` until `retry_at`.
|
|
339
|
+
- **One task at a time** unless the user asked otherwise. Renders are CPU-heavy; a laptop running
|
|
340
|
+
three at once produces three late videos instead of one good one.
|
|
341
|
+
- **Never claim more than you can finish before `task_timeout`.**
|
|
342
|
+
- **Log every attempt to `ledger.jsonl`, including failures.** Silent failures are how a loop
|
|
343
|
+
quietly earns nothing for a week.
|
|
344
|
+
- **Stop the loop and tell the user** if: proofs start getting rejected, funds warnings appear, the
|
|
345
|
+
gig goes `paused`, or three tasks in a row fail. Don't burn their machine and their reputation
|
|
346
|
+
overnight on a broken pipeline.
|
|
347
|
+
- Their computer must be awake. Schedule it with `cron` / Task Scheduler / a `launchd` job, or just
|
|
348
|
+
a `while` loop with a sleep — whatever they'll actually be able to restart themselves.
|
|
349
|
+
|
|
350
|
+
**Report to the user each session** (and write the same into `NOTES.md`): tasks done, videos
|
|
351
|
+
submitted with their share URLs, proofs approved vs pending, anything the client rejected and why,
|
|
352
|
+
what they earned (or are owed, for off-chain), and what it cost — AI spend should be `$0.00` in
|
|
353
|
+
`minimize`, and if it isn't, that's the first thing to say.
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Honesty rules
|
|
358
|
+
|
|
359
|
+
These exist because the loop touches real customers, real reputation, and real money.
|
|
360
|
+
|
|
361
|
+
- **Never fake a proof.** Every submitted URL must point at a video you actually rendered for that
|
|
362
|
+
task. `fake_proof` is a 5x reputation penalty and it is permanent and wallet-anchored.
|
|
363
|
+
- **Never promise earnings.** Pay is per approved proof and demand-driven — quiet days pay nothing.
|
|
364
|
+
If the user asks "how much will I make", give them the gig's `price` and the honest answer that it
|
|
365
|
+
depends entirely on how many tasks the client posts.
|
|
366
|
+
- **Never spend their money silently.** In `minimize`, a billed step stops and asks. Report actual
|
|
367
|
+
spend, not estimates — `vidfarm wallet` has the truth.
|
|
368
|
+
- **Report what really happened.** If a render failed, a proof was rejected, or you skipped tasks,
|
|
369
|
+
say so plainly with the error. A loop the user can't trust is worse than no loop.
|
|
370
|
+
- **Don't work prohibited gigs.** If a gig's `terms` ask for something illegal, deceptive, or in a
|
|
371
|
+
prohibited vertical, refuse and tell the user why. DollarPlatoon has no dispute resolution — you
|
|
372
|
+
are their only check.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## When something breaks
|
|
377
|
+
|
|
378
|
+
| Symptom | Likely cause | Fix |
|
|
379
|
+
|---|---|---|
|
|
380
|
+
| Poll returns no tasks | Gig isn't `distribution: "queue"` | Check `gig.distribution`, use Phase 4's matching path |
|
|
381
|
+
| `403` on join | Missing or revoked invite token | Ask for the full invite URL again |
|
|
382
|
+
| Join returns `pending_approval` | Gig has `requires_approval` | Wait for the client; don't poll |
|
|
383
|
+
| `429` on poll or proof | Worker rate limit | Sleep until `rate_limit.retry_at` |
|
|
384
|
+
| `409` on proof | Duplicate `task_identifier` | You already submitted; check `GET /gigs/:id/proofs` |
|
|
385
|
+
| `410` on proof | Task expired (`task_timeout`) | Ask the client to `extend`, or take a fresh task |
|
|
386
|
+
| Proof accepted with a funds `warning` | Gig treasury is short | Tell the user; pause the loop |
|
|
387
|
+
| Render fails or hangs | Local toolchain | `vidfarm doctor`, then `vidfarm doctor --kill-orphans` |
|
|
388
|
+
| `402` on a vidfarm command | Free plan or `minimize` blocking a billed route | Use the free path the error names |
|
|
389
|
+
| Share URL 404s later | Video went to the temp store | Re-approve with `vidfarm approve --video` (durable My Files) |
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## More
|
|
394
|
+
|
|
395
|
+
- Explainer: <https://vidfarm.cc/blog/agentic-clipper-loops>
|
|
396
|
+
- Vidfarm skill (start here for anything video): <https://vidfarm.cc/skill.md>
|
|
397
|
+
- DollarPlatoon skill (full REST reference): <https://dollarplatoon.com/skill.md>
|
|
398
|
+
- Vidfarm marketplace: <https://vidfarm.cc/marketplace>
|
package/dist/src/cli.js
CHANGED
|
@@ -600,12 +600,19 @@ Files (multi-step flows the devcli handles for you):
|
|
|
600
600
|
--notes <text> Metadata notes (what it is / when to use it) — vector-embedded for search
|
|
601
601
|
e.g. vidfarm put-file About.md --folder acme-skincare
|
|
602
602
|
echo "..." | vidfarm put-file --stdin --as About.md --folder acme
|
|
603
|
-
download <url> [dest] Stream any Vidfarm/media URL to disk
|
|
604
|
-
download-
|
|
603
|
+
download <url> [dest] Stream any Vidfarm/media URL to disk (free — direct media URLs only)
|
|
604
|
+
download-video <url> PAID. Download a video FROM A WEBSITE (YouTube, TikTok, Instagram,
|
|
605
|
+
(aka download-post) X/Twitter, and other supported posts) into durable Vidfarm media.
|
|
606
|
+
Photo/carousel posts come back as an ordered slideshow.
|
|
607
|
+
→ POST /api/v1/primitives/videos/download
|
|
605
608
|
--quality <q> best | hd | full_hd (default: best)
|
|
606
609
|
--no-wait Return the queued job immediately instead of polling
|
|
607
|
-
download-
|
|
610
|
+
download-audio <url> PAID. Download just the AUDIO track (music/voice) from a website post
|
|
611
|
+
(aka download-post-audio) → POST /api/v1/primitives/audio/download
|
|
608
612
|
--no-wait Return the queued job immediately instead of polling
|
|
613
|
+
FREE PLAN: both bill the wallet via a paid resolver. If the user is
|
|
614
|
+
free/no-spend, don't call them — open the URL in Chrome and download
|
|
615
|
+
it from the page, then 'vidfarm put-file ./the-file' to bring it in.
|
|
609
616
|
tasks Cloud Status: imports · forks · renders · jobs → GET /api/v1/user/me/tasks
|
|
610
617
|
--running|--done|--error Filter (or --status <all|running|done|error>); --limit <n>
|
|
611
618
|
wallet Wallet cost log: balance + what each video cost → GET /api/v1/user/me/wallet
|
|
@@ -769,7 +776,10 @@ function loadDotEnvCredentials(cwd = process.cwd()) {
|
|
|
769
776
|
async function main() {
|
|
770
777
|
const argv = process.argv.slice(2);
|
|
771
778
|
loadDotEnvCredentials();
|
|
772
|
-
|
|
779
|
+
// `help` must be caught here too: without it the bare word falls through the
|
|
780
|
+
// dispatch switch and is treated as a TEMPLATE ID by the default `serve` case,
|
|
781
|
+
// which boots a local server on :3000 instead of printing help.
|
|
782
|
+
if (argv.length === 0 || argv[0] === "help" || argv[0] === "--help" || argv[0] === "-h") {
|
|
773
783
|
process.stdout.write(HELP);
|
|
774
784
|
return;
|
|
775
785
|
}
|
|
@@ -952,10 +962,14 @@ async function main() {
|
|
|
952
962
|
case "download":
|
|
953
963
|
await runDownloadCommand(rest);
|
|
954
964
|
return;
|
|
965
|
+
// Aliases: agents look for "download a video from a website", not "post".
|
|
955
966
|
case "download-post":
|
|
967
|
+
case "download-video":
|
|
968
|
+
case "download-url":
|
|
956
969
|
await runDownloadPostCommand(rest);
|
|
957
970
|
return;
|
|
958
971
|
case "download-post-audio":
|
|
972
|
+
case "download-audio":
|
|
959
973
|
await runDownloadPostAudioCommand(rest);
|
|
960
974
|
return;
|
|
961
975
|
case "files":
|
|
@@ -6877,6 +6891,27 @@ async function runDownloadCommand(argv) {
|
|
|
6877
6891
|
console.log(`${GREEN}Downloaded ${formatBytes(bytes)} → ${dest}${RESET}`);
|
|
6878
6892
|
}
|
|
6879
6893
|
}
|
|
6894
|
+
// The FREE fallback for the paid download primitives. Both routes ride a paid
|
|
6895
|
+
// RapidAPI resolver billed to the wallet, so a free-plan customer gets a 402.
|
|
6896
|
+
// Rather than dead-ending them, tell the agent to drive the user's own browser:
|
|
6897
|
+
// open the URL in Chrome and download it from there (no Vidfarm spend).
|
|
6898
|
+
// NOTE: a hoisted function, NOT a module const — `void main()` runs synchronously
|
|
6899
|
+
// until its first await, so a const declared this far down the file is still in
|
|
6900
|
+
// its TDZ when a command handler reads it (same gotcha as the *_HELP consts).
|
|
6901
|
+
function downloadFreeAlternative() {
|
|
6902
|
+
return "open the URL in Chrome and download it from the page yourself ($0.00 — no wallet spend)";
|
|
6903
|
+
}
|
|
6904
|
+
function printDownloadFreePathHint(ctx, kind) {
|
|
6905
|
+
if (ctx.json)
|
|
6906
|
+
return;
|
|
6907
|
+
const noun = kind === "video" ? "video" : "audio";
|
|
6908
|
+
console.log("");
|
|
6909
|
+
console.log(`${YELLOW}Free path (no Vidfarm spend):${RESET} load the URL in Chrome and grab the ${noun} from there.`);
|
|
6910
|
+
console.log(`${DIM} 1. Open the post/page in Chrome (a real browser session handles the login/consent walls).${RESET}`);
|
|
6911
|
+
console.log(`${DIM} 2. Save the ${noun} from the page — right-click → Save, the browser's downloads, or a downloader site.${RESET}`);
|
|
6912
|
+
console.log(`${DIM} 3. Google "youtube ${noun} downloader" or "tiktok/instagram/x ${noun} downloader" if the page won't give it up.${RESET}`);
|
|
6913
|
+
console.log(`${DIM} 4. Then bring the local file into Vidfarm for free: vidfarm put-file ./the-file --folder <folder>${RESET}`);
|
|
6914
|
+
}
|
|
6880
6915
|
async function runDownloadPostCommand(argv) {
|
|
6881
6916
|
const parsed = parseArgs({
|
|
6882
6917
|
args: argv,
|
|
@@ -6891,6 +6926,11 @@ async function runDownloadPostCommand(argv) {
|
|
|
6891
6926
|
throw new Error("download-post --quality must be one of: best, hd, full_hd.");
|
|
6892
6927
|
}
|
|
6893
6928
|
const ctx = commonContext(parsed.values);
|
|
6929
|
+
guardBilled(ctx, {
|
|
6930
|
+
label: "download a video from a website (paid plan — RapidAPI resolver)",
|
|
6931
|
+
estimate: "small per-download wallet charge",
|
|
6932
|
+
freeAlternative: downloadFreeAlternative()
|
|
6933
|
+
});
|
|
6894
6934
|
const tracer = String(parsed.values.tracer ?? `devcli-download-post-${Date.now().toString(36)}`);
|
|
6895
6935
|
const submit = await apiRequest({
|
|
6896
6936
|
method: "POST",
|
|
@@ -6899,6 +6939,9 @@ async function runDownloadPostCommand(argv) {
|
|
|
6899
6939
|
auth: ctx.auth,
|
|
6900
6940
|
body: { tracer, payload: { source_url: url, quality } }
|
|
6901
6941
|
});
|
|
6942
|
+
if (!submit.ok && (submit.status === 402 || submit.status === 401 || submit.status === 403)) {
|
|
6943
|
+
printDownloadFreePathHint(ctx, "video");
|
|
6944
|
+
}
|
|
6902
6945
|
assertApiOk(submit, "download-post");
|
|
6903
6946
|
const jobId = submit.json?.job_id;
|
|
6904
6947
|
if (!jobId || parsed.values["no-wait"]) {
|
|
@@ -6920,6 +6963,11 @@ async function runDownloadPostAudioCommand(argv) {
|
|
|
6920
6963
|
if (!url)
|
|
6921
6964
|
throw new Error("download-post-audio requires a source URL.");
|
|
6922
6965
|
const ctx = commonContext(parsed.values);
|
|
6966
|
+
guardBilled(ctx, {
|
|
6967
|
+
label: "download audio from a website (paid plan — RapidAPI resolver)",
|
|
6968
|
+
estimate: "small per-download wallet charge",
|
|
6969
|
+
freeAlternative: downloadFreeAlternative()
|
|
6970
|
+
});
|
|
6923
6971
|
const tracer = String(parsed.values.tracer ?? `devcli-download-post-audio-${Date.now().toString(36)}`);
|
|
6924
6972
|
const submit = await apiRequest({
|
|
6925
6973
|
method: "POST",
|
|
@@ -6928,6 +6976,9 @@ async function runDownloadPostAudioCommand(argv) {
|
|
|
6928
6976
|
auth: ctx.auth,
|
|
6929
6977
|
body: { tracer, payload: { source_url: url } }
|
|
6930
6978
|
});
|
|
6979
|
+
if (!submit.ok && (submit.status === 402 || submit.status === 401 || submit.status === 403)) {
|
|
6980
|
+
printDownloadFreePathHint(ctx, "audio");
|
|
6981
|
+
}
|
|
6931
6982
|
assertApiOk(submit, "download-post-audio");
|
|
6932
6983
|
const jobId = submit.json?.job_id;
|
|
6933
6984
|
if (!jobId || parsed.values["no-wait"]) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@officexapp/vidfarm-devcli",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.23",
|
|
4
4
|
"description": "Local bridge for the Vidfarm Trackpad Editor. `vidfarm serve <template_id>` boots the FULL editor on localhost (disk-backed records/storage, free in-process render); edit composition.html on disk (Claude Code, Codex, etc.) and the browser live-morphs it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"README.md",
|
|
51
51
|
"SKILL.md",
|
|
52
52
|
"SKILL.director.md",
|
|
53
|
+
"clipper.md",
|
|
53
54
|
"!readme.secret.md",
|
|
54
55
|
"!**/*.secret.*"
|
|
55
56
|
],
|