@mevdragon/vidfarm-devcli 0.20.2 → 0.20.4

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.
@@ -49,7 +49,7 @@ This mints a new fork and opens it in the editor — the same **New fork** actio
49
49
 
50
50
  The most common intent: the user opens a template to reuse its structure and says *"make this for X"* (e.g. a book-recap template → "The Richest Man in Babylon", or a listicle → "my coffee brand"). Treat it as first-class:
51
51
 
52
- 1. **Read the DNA first.** `composition_context` carries the format/genre + arc (trend_tagline, hook, retention, payoff, preserve, avoid). For the scene beats/transcript, call the `video_context` tool. Match the template's *voice* — a text-message template's captions read like chat, a story-time template reads like first-person narration; don't default to generic ad copy.
52
+ 1. **Read the DNA first.** `composition_context` carries the format/genre + arc (trend_tagline, hook, retention, payoff, preserve, avoid) **plus `emotional_punch`** — the FEELING the format delivers (`core_emotion`, `tone`, `arc`, `peak_moment`, `mechanism`, `humor`, `delivery`, `preserve`): the vibe/joke/intonation a remix most often flattens. Rebuild `humor`'s joke around the new subject rather than dropping it, match `tone`/`delivery` so timing and intonation survive, and never trade the `peak_moment` payoff for a flat product plug. For the scene beats/transcript, call the `video_context` tool (whose `viral_dna` also carries the full `emotional_punch`). Match the template's *voice* — a text-message template's captions read like chat, a story-time template reads like first-person narration; don't default to generic ad copy.
53
53
  2. **Propose, then ask only what you can't infer.** One concise plan plus a couple of questions: which specifics of the new subject to feature (offer to pick the strongest N to match the scene count), keep the current narrator voice?, any brand assets/images to use (else you'll generate), a target length if different.
54
54
  3. **Execute axis by axis, preserving the DNA:**
55
55
  - TEXT → rewrite every caption/title layer in the template's voice (`set_layer_text` / `set_captions`), keeping caption animation + timing.
@@ -142,9 +142,10 @@ You usually already know a clip's aspect from how you sourced it (a hunted raw's
142
142
  - `transitions` — `default`/`intro`/`outro` (map to one `set_transitions` call), `usage`.
143
143
  - `broll` — `reliance`, `sourcing`, `shot_kinds`, `cadence`. Drives whether you HUNT raws (`/clips/scan`) vs `generate_layer`, and at what cadence.
144
144
  - `audio` — `voiceover`, `music`, `sfx`, `captions_from`.
145
+ - `emotional` — HOW to edit so the FEELING survives: `target_feeling`, `tone`, `comedic_timing` (the beat/pause/hard-cut that sells the joke), `intonation` (vocal cadence to preserve when you re-voice), `vibe_anchors` (the concrete edit moves that carry the emotion — often "keep the trending sound and land the beat drop on the reveal cut"). The vibe/joke/intonation/sound are the first things a remix flattens, so treat these as must-dos.
145
146
  - `scenes[]` — each beat's `role` + `importance` + `must_keep` + `edit_bias`. `important_scenes`, `editing_bias`, `do`, `dont`.
146
147
 
147
- **How to use it:** map `caption_style` → `set_captions`, `transitions.*` → `set_transitions`, honor `pacing`, follow `broll` for footage sourcing, lay `audio`. **PROTECT** any beat in `important_scenes` or with `must_keep:true` / `importance:"critical"` — swap its subject if needed but preserve its timing, role, and caption cadence; that's where the style lives. Treat `editing_bias`/`do`/`dont` as hard constraints for this composition. It sets defaults, not a straitjacket — an explicit user instruction wins. **In local devcli** the same brief is on disk as `editor-harness.json` (under `.harness`, pulled by `vidfarm pull`/`sync`); read it there before a big edit. If `editor_harness` is absent, the fork wasn't decomposed with the harness pass — fall back to `composition_context` + the `video_context` tool.
148
+ **How to use it:** map `caption_style` → `set_captions`, `transitions.*` → `set_transitions`, honor `pacing`, follow `broll` for footage sourcing, lay `audio`, and honor `emotional` (preserve `comedic_timing`, keep `intonation` when re-voicing narration, execute every `vibe_anchors` entry). **PROTECT** any beat in `important_scenes` or with `must_keep:true` / `importance:"critical"` — swap its subject if needed but preserve its timing, role, and caption cadence; that's where the style lives. Treat `editing_bias`/`do`/`dont` as hard constraints for this composition. It sets defaults, not a straitjacket — an explicit user instruction wins. **In local devcli** the same brief is on disk as `editor-harness.json` (under `.harness`, pulled by `vidfarm pull`/`sync`); read it there before a big edit. If `editor_harness` is absent, the fork wasn't decomposed with the harness pass — fall back to `composition_context` + the `video_context` tool.
148
149
 
149
150
  ## Web-editor motion rule (hard constraint)
150
151
 
package/SKILL.director.md CHANGED
@@ -200,7 +200,7 @@ Content-Type: application/json
200
200
 
201
201
  Two modes:
202
202
 
203
- - **`smart`** — uses the caller's Gemini/OpenAI/OpenRouter key. Samples frames, extracts scenes with labels, literal visual **descriptions**, and viral notes, extracts on-screen captions with positions, **transcribes the audio track verbatim** (timestamped segments; Gemini first, OpenAI Whisper fallback; skipped when the video has no audio), and detects viral DNA (hook, retention, payoff). Takes 30-60 seconds. Auto-fires GhostCut for subtitle removal in the background.
203
+ - **`smart`** — uses the caller's Gemini/OpenAI/OpenRouter key. Samples frames, extracts scenes with labels, literal visual **descriptions**, and viral notes, extracts on-screen captions with positions, **transcribes the audio track verbatim** (timestamped segments; Gemini first, OpenAI Whisper fallback; skipped when the video has no audio), and detects viral DNA (hook, retention, payoff, plus **`emotional_punch`** — the vibe/joke/intonation that makes it FEEL, reasoned over BOTH the frames and the transcript so the trending sound and vocal delivery are captured, not just the visuals). Takes 30-60 seconds. Auto-fires GhostCut for subtitle removal in the background.
204
204
  - **`time-slice`** — deterministic equal-duration split. Instant. No AI provider needed.
205
205
 
206
206
  **Source length cap.** Vidfarm caps auto-decompose (and all inspiration ingest) at **120 seconds** of source video. If the source is longer, the API responds with `400 { ok: false, code: "source_too_long", duration_seconds, max_duration_seconds }` and no scenes are written. Trim the source before forking / ingesting.
@@ -239,12 +239,25 @@ Read-only state (does **not** advance the job or bill): `GET /api/v1/composition
239
239
  "viral_note": "...",
240
240
  "transcript_excerpt": "what is spoken during this scene"
241
241
  }],
242
- "viral_dna": { ... }
242
+ "viral_dna": {
243
+ "trend_tagline": "...", "hook": "...", "retention": "...", "payoff": "...",
244
+ "emotional_punch": {
245
+ "core_emotion": "smug relief-laugh", "tone": "deadpan comedic",
246
+ "arc": "flat setup → mounting absurdity → sudden turn", "peak_moment": "the reveal at ~0:07",
247
+ "mechanism": "subversion + trending-sound beat drop synced to the cut",
248
+ "humor": "the joke is X — it works because Y (rebuild the SAME joke around a new subject)",
249
+ "delivery": "flat VO cadence, hold the beat before the punch, beat drop lands on the reveal",
250
+ "preserve": ["keep the beat drop on the reveal cut", "keep the flat unbothered delivery"]
251
+ },
252
+ "preserve": ["..."], "avoid": ["..."], "promotions": ["..."], "keywords": ["..."]
253
+ }
243
254
  }
244
255
  ```
245
256
 
246
257
  `status: "none"` means the fork was never smart-decomposed — run `POST /auto-decompose` with `mode: "smart"` first. `transcript` is `null` when the source has no audio track or transcription failed.
247
258
 
259
+ **`viral_dna.emotional_punch`** is the FEELING of the format and what makes it land — the part a remix most often flattens. Where hook/retention/payoff are the mechanical structure, this captures the vibe, the joke, and the intonation. It is now **audio-aware**: the decompose feeds the transcript into the reasoning, so `mechanism`/`delivery` account for the trending sound, the music-bed drop, and vocal cadence (on short-form the sound is frequently the biggest driver of the punch). When you re-theme or remix, rebuild `humor`'s joke around the new subject rather than dropping it, match `tone`/`delivery` so intonation and comedic timing survive, and never trade the `peak_moment` payoff for a flat product plug.
260
+
248
261
  Use it whenever you need to know what the video says or shows: writing/translating captions, matching hooks or dubs to spoken audio, or planning scene-level edits.
249
262
 
250
263
  - **Editor chat (frontend AI)** exposes this as the optional `video_context` tool — the copilot calls it on demand.
@@ -267,13 +280,14 @@ Use it whenever you need to know what the video says or shows: writing/translati
267
280
  "broll": { "reliance": "heavy", "sourcing": "screen-recording", "shot_kinds": ["b_roll"], "cadence": "new visual ~every 2s" },
268
281
  "transitions": { "default": "cut", "intro": "fade", "outro": "none", "usage": "hard cuts only" },
269
282
  "audio": { "voiceover": "first-person narration", "music": "upbeat lofi bed, low", "sfx": "whoosh on cuts", "captions_from": "voiceover" },
283
+ "emotional": { "target_feeling": "smug relief-laugh", "tone": "deadpan comedic", "comedic_timing": "hold a beat, then hard cut on the punch word", "intonation": "flat unbothered VO, no upspeak", "vibe_anchors": ["keep the trending sound, land the beat drop on the reveal cut", "hold silence before the payoff"] },
270
284
  "scenes": [{ "role": "hook", "importance": "critical", "must_keep": true, "note": "...", "edit_bias": "swap subject, keep timing+caption cadence" }],
271
285
  "important_scenes": ["..."], "editing_bias": ["..."], "do": ["..."], "dont": ["..."]
272
286
  }
273
287
  }
274
288
  ```
275
289
 
276
- **Use it to pick concrete moves:** `typography.caption_style` maps to a `set_captions` preset; `transitions.*` to a `set_transitions` call; keep `pacing` (cut rhythm / avg_scene_seconds) when adding or splitting scenes; follow `broll.reliance`/`sourcing` to decide HUNT raws (`/raws/scan`) vs generate; lay `audio.*`. **Protect** any beat in `important_scenes` or with `must_keep:true` / `importance:"critical"` — swap the subject but preserve its timing, role, and caption cadence. Treat `editing_bias`/`do`/`dont` as hard constraints; an explicit user instruction still wins. `status:"none"` → run `POST /auto-decompose` first.
290
+ **Use it to pick concrete moves:** `typography.caption_style` maps to a `set_captions` preset; `transitions.*` to a `set_transitions` call; keep `pacing` (cut rhythm / avg_scene_seconds) when adding or splitting scenes; follow `broll.reliance`/`sourcing` to decide HUNT raws (`/raws/scan`) vs generate; lay `audio.*`. **`emotional`** is HOW to keep the FEELING while you swap the subject — the vibe/joke/intonation/sound are the first things a remix flattens, so honor `emotional.comedic_timing` (the held beat / hard cut that sells the joke), preserve `emotional.intonation` when you re-voice narration, and treat every `emotional.vibe_anchors` entry as a must-do (on short-form the trending sound / beat drop is often the biggest carrier of the punch — keep it and land it on the same cut). **Protect** any beat in `important_scenes` or with `must_keep:true` / `importance:"critical"` — swap the subject but preserve its timing, role, and caption cadence. Treat `editing_bias`/`do`/`dont` as hard constraints; an explicit user instruction still wins. `status:"none"` → run `POST /auto-decompose` first.
277
291
 
278
292
  - **Editor chat (frontend AI)** already receives the harness inline in `editor_context.editor_harness` (no tool call needed); it can also fetch this route via `http_request`.
279
293
  - **Desktop agents (Claude Code / Codex)**: `vidfarm pull` writes `editor-harness.json` to the fork dir (the brief is under `.harness`) alongside `video-context.json`; read it before a big edit. The `pull` grounding line reports whether it's present.
package/SKILL.platform.md CHANGED
@@ -160,7 +160,7 @@ A composition is a single HTML document plus a JSON sidecar.
160
160
  "summary": "...",
161
161
  "scenes": [{ "slug": "hook_reveal", "start": 0, "duration": 1.5, "label": "...", "viral_note": "..." }],
162
162
  "captions": [{ "slug": "caption_1", "text": "...", "start": 0, "duration": 1.5, "x": 5, "y": 60 }],
163
- "viralDna": { "hook": "...", "retention": "...", "payoff": "...", "preserve": [...], "avoid": [...] },
163
+ "viralDna": { "hook": "...", "retention": "...", "payoff": "...", "emotional_punch": { "core_emotion": "...", "tone": "...", "mechanism": "...", "humor": "...", "delivery": "...", "preserve": [...] }, "preserve": [...], "avoid": [...] },
164
164
  "width": 1080,
165
165
  "height": 1920,
166
166
  "durationSeconds": 10.5,