OUTPUT #689
PARÇA 5 / 6
TOPLAM: 218127 karakter | 2042 satır
BU PARÇA: 40000 karakter
ontaj_assets/render/node_modules/smart-buffer/.prettierrc.yaml | hits=1 =====
4: singleQuote: true
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/ansi-regex/readme.md | hits=4 =====
3: > Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
39: Returns a regex for matching ANSI escape codes.
48: Default: `false` *(Matches any ANSI escape codes in a string)*
50: Match only the first ANSI escape.
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/ansi-regex/package.json | hits=2 =====
4: "description": "Regular expression for matching ANSI escape codes",
34: "escape",
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/devtools-protocol/json/js_protocol.json | hits=38 =====
106: "description": "Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing\nbreakpoints, stepping through execution, exploring stack traces, etc.",
255: "block",
423: "description": "The maximum size in bytes of collected scripts (not referenced by other heap objects)\nthe debugger can hold. Puts no limit if parameter is omitted.",
490: "name": "timeout",
687: "description": "Restarts particular call frame from the beginning. The old, deprecated\nbehavior of `restartFrame` is to stay paused and allow further CDP commands\nafter a restart was scheduled. This can cause problems with restarting, so\
794: "description": "Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in\nscripts with url matching one of the patterns. VM will try to leave blackboxed script by\nperforming 'step in' several times, f
809: "description": "Makes backend skip steps in the script in blackboxed ranges. VM will try leave blacklisted\nscripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful.\nPositions array contains positions
879: "description": "Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this\ncommand is issued, all existing parsed scripts will have breakpoints resolved and returned in\n`locations` property. Further match
1000: "description": "Edits JavaScript source live.\n\nIn general, functions that are currently on the stack can not be edited with\na single exception: If the edited function is the top-most stack frame and\nthat is the only activation of that f
1066: "BlockedByActiveGenerator",
1067: "BlockedByActiveFunction",
1068: "BlockedByTopLevelEsModuleChange"
1080: "name": "setSkipAllPauses",
1084: "name": "skip",
1085: "description": "New value for skip pauses state.",
1128: "name": "skipList",
1129: "description": "The skipList specifies location ranges that should be skipped on step into.",
1148: "name": "skipList",
1149: "description": "The skipList specifies location ranges that should be skipped on step over.",
1211: "description": "Object containing break-specific auxiliary properties.",
1297: "description": "Embedder-specific auxiliary data likely matching {isDefault: boolean, type: 'default'|'isolated'|'worker', frameId: string}",
1401: "description": "Embedder-specific auxiliary data likely matching {isDefault: boolean, type: 'default'|'isolated'|'worker', frameId: string}",
1519: "description": "A single sample from a sampling profile.",
1688: "name": "captureNumericValue",
1719: "name": "captureNumericValue",
1950: "name": "isBlockCoverage",
1951: "description": "Whether coverage data for this function has block granularity.",
2029: "description": "Collect block-based coverage.",
2239: "description": "Set if value reference met more then once during serialization. In such\ncase, value is provided only to one of the serialized values. Unique\nper value in the scope of one CDP call.",
2706: "description": "Embedder-specific auxiliary data likely matching {isDefault: boolean, type: 'default'|'isolated'|'worker', frameId: string}",
2964: "description": "Whether execution should `await` for resulting value and return once awaited promise is\nresolved.",
3123: "description": "Whether execution should `await` for resulting value and return once awaited promise is\nresolved.",
3135: "name": "timeout",
3156: "name": "allowUnsafeEvalBlockedByCSP",
3157: "description": "The Content Security Policy (CSP) for the target might block 'unsafe-eval'\nwhich includes eval(), Function(), setTimeout() and setInterval()\nwhen called with non-callable arguments. This flag bypasses CSP for this\nevaluat
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/devtools-protocol/json/browser_protocol.json | hits=252 =====
62: "figcaption",
68: "tablecaption",
75: "description": "A single source for a computed AX property.",
174: "description": "A single computed AX property.",
1049: "ExcludeThirdPartyCookieBlockedInFirstPartySet",
1135: "MixedContentBlocked",
1215: "id": "BlockedByResponseReason",
1216: "description": "Enum indicating the reason a response has been blocked. These reasons are\nrefinements of the net error BLOCKED_BY_RESPONSE.",
1229: "id": "BlockedByResponseIssueDetails",
1230: "description": "Details for a request that has been blocked with the BLOCKED_BY_RESPONSE\ncode. Currently only used for COEP/COOP, but may be extended to include\nsome CSP errors in the future.",
1243: "name": "blockedFrame",
1249: "$ref": "BlockedByResponseReason"
1257: "HeavyAdBlocked",
1265: "NetworkTotalLimit",
1266: "CpuTotalLimit",
1267: "CpuPeakLimit"
1276: "description": "The resolution status, either blocking the content or warning.",
1281: "description": "The reason the ad was blocked, total network or cpu or peak cpu.",
1286: "description": "The frame that was blocked.",
1331: "name": "blockedURL",
1549: "description": "Details for issues about documents in Quirks Mode\nor Limited Quirks Mode that affects page layouting.",
1553: "name": "isLimitedQuirksMode",
1554: "description": "If false, it means the document's mode is \"quirks\"\ninstead of \"limited-quirks\".",
1620: "ResponseWasBlockedByORB"
1775: "ThirdPartyCookiesBlocked",
1916: "BlockedByResponseIssue",
1953: "name": "blockedByResponseIssueDetails",
1955: "$ref": "BlockedByResponseIssueDetails"
2182: "description": "Installs an unpacked extension from the filesystem similar to\n--load-extension CLI flags. Returns extension ID once the extension\nhas been installed.",
2419: "domain": "BackgroundService",
2420: "description": "Defines events for background web platform features.",
2425: "description": "The Background Service that will be associated with the commands/events.\nEvery Background Service operates independently, but they share the same\nAPI.",
2428: "backgroundFetch",
2429: "backgroundSync",
2433: "periodicBackgroundSync"
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/@tootallnate/quickjs-emscripten/README.md | hits=19 =====
52: a promise that resolves to a [QuickJS singleton](./doc/classes/quickjs.md) when
55: Once `getQuickJS` has been awaited at least once, you also can use the `getQuickJSSync`
56: function to directly access the singleton engine in your synchronous code.
68: memoryLimitBytes: 1024 * 1024,
113: The runtime has APIs for CPU and memory limits that apply to all contexts within
120: runtime.setMemoryLimit(1024 * 640)
121: // Limit stack size
146: `.dispose()` method to free the underlying resources. Once a handle has been
148: `.dispose()` on each handle once it is no longer needed.
190: // When the withScope block exits, it calls scope.dispose(), which in turn calls
261: gives your code maximum control to _schedule_ when QuickJS will block the host's
280: setTimeout(() => {
284: // IMPORTANT: Once you resolve an async action inside QuickJS,
336: asynchronously, and then resume execution once the data load completes. This is
337: a very handy superpower, but it comes with a couple of major limitations:
339: 1. _An asyncified WebAssembly module can only suspend to wait for a single
366: existing module; if you only need to wait for a single async action at a time,
367: you can create a single top-level module and create runtimes or contexts inside
501: ## Background
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/puppeteer-core/src/bidi/core/README.md | hits=2 =====
32: WebDriver BiDi doesn't have a concept of "nested navigation", but in
48: all edges and nodes required by a feature without skipping nodes and events
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/@puppeteer/browsers/README.md | hits=1 =====
40: ## Known limitations
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/socks/docs/migratingFromV1.md | hits=1 =====
13: - In v2, the factory SocksClient.createConnection function callback is called with a single object rather than separate socket and info object.
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/socks/docs/examples/typescript/bindExample.md | hits=1 =====
5: The bind command tells the SOCKS proxy server to bind and listen on a new TCP port for an incoming connection. It communicates the newly opened port back to the origin client. Once a incoming connection is accepted by the SOCKS proxy server
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/socks/docs/examples/javascript/bindExample.md | hits=1 =====
5: The bind command tells the SOCKS proxy server to bind and listen on a new TCP port for an incoming connection. It communicates the newly opened port back to the origin client. Once a incoming connection is accepted by the SOCKS proxy server
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/smart-buffer/docs/CHANGELOG.md | hits=1 =====
21: * rewind(), skip(), moveTo() have been removed.
===== /home/hermes/.hermes/tools/montaj/montaj_assets/render/node_modules/smart-buffer/docs/README_v3.md | hits=4 =====
328: ### SmartBuffer.skip( value )
329: > `Number` **The amount of bytes to skip ahead**
331: Skips the read position ahead by the given value.
343: > `Number` **The point to skip the read position to**
===== /home/hermes/.hermes/tools/montaj/skills/animation-sections/SKILL.md | hits=5 =====
46: - The JSX root element's CSS controls the entire frame — use background colors, gradients, patterns freely
47: - Do not call `background: transparent` — that is for regular overlays only
60: Use `tracks[1]` for the primary visual layer — opaque backgrounds and section slides:
92: Use `tracks[2+]` for **layered animations on top** — text, icons, motion graphics that sit above the background layer. Items in higher-numbered tracks render on top.
103: **Sections in this skill are almost always `opaque: true`, and that changes which item gets the keyframes.** An opaque item tells the renderer it covers the whole frame, so whatever is beneath it is skipped rather than composited — fading i
===== /home/hermes/.hermes/tools/montaj/skills/parallel/SKILL.md | hits=9 =====
13: For `foreach` steps on independent clips, use a **single Bash call with background jobs**:
29: **Do NOT use background jobs for encoding steps.** See Encoding steps below.
33: Encoding steps are memory-intensive per instance (full libx264 encode + frame buffers). Fanning them out unbounded across N clips will exhaust memory on 4K footage. Use batch mode with the built-in concurrency cap instead of background jobs
48: **`remove_bg` is long-running** (minutes per clip on MPS/GPU). Always run it in the background when using the Agent tool or HTTP API so the agent remains responsive.
52: Preferred over background jobs — pass all clips in a single call:
68: When each clip needs 3+ sequential per-clip steps, background jobs get unwieldy. Use **one subagent per clip**:
73: 4. Cap at **4 concurrent clip agents** to avoid resource contention
77: There is no join step. Nothing concatenates the per-clip outputs into one file: the surviving keeps become `tracks[0]` items with their own `inPoint`/`outPoint`, and the render engine assembles them in a single pass at the end.
97: Assembly is not a wave. The render engine reads the finished `tracks` and encodes once, at render time.
===== /home/hermes/.hermes/tools/montaj/skills/onboarding/SKILL.md | hits=5 =====
14: Montaj doesn't edit on its own. It provides discrete operations — trim, transcribe, remove fillers, caption, resize, composite overlays — and the agent decides which to call, in what order, with what parameters. The agent is the editor. Mon
26: - You need captions, overlays, and trim decisions made from the content itself
39: A project is one video being made. Everything lives in a single file: `project.json`.
82: A style profile captures the visual and editorial identity of a social media account — pacing, cut frequency, color palette, caption style, tone. Once created, it gets injected into every project for that account so editing decisions stay c
110: > **Style profile:** I'll analyze your existing content (or a URL you paste) and build an editing style that gets applied automatically to every project for that account — pacing, caption style, color palette, tone.
===== /home/hermes/.hermes/tools/montaj/skills/native/SKILL.md | hits=8 =====
64: # Single input
82: **Long-running steps** (transcribe, rm_fillers, resize, remove_bg) must run in the background so you stay available for conversation:
84: 1. **Single long step** — set `run_in_background: true` on the Bash tool call. You are notified on completion.
85: 2. **Multiple clips in parallel** — write a shell script with `&` + `wait` to `/tmp`, execute with `run_in_background: true`.
87: Never block the conversation waiting on ffmpeg. Log the step, fire it in the background, then tell the user what's running.
167: montaj caption clip.mp4 --style word-by-word
174: Not every step has a top-level command, and `montaj -h` is not the way to find out which do: about twenty step commands are deliberately hidden from that listing (`_HIDDEN` in `cli/main.py`), including `probe`, `transcribe`, `caption`, `nor
176: Fire long-running CLI steps in the background (`run_in_background: true` on the Bash call) for the same reasons as HTTP mode.
===== /home/hermes/.hermes/tools/montaj/skills/edit-session/SKILL.md | hits=8 =====
50: This is the single most important thing to know about editing a v4 draft: a cut, a split, a ripple delete and a trim are all rewrites of `tracks` and `captions` in `project.json`. No intermediate file is produced, no clip file changes, and
63: - **`end - start` must equal `outPoint - inPoint`** for a clip at normal speed, and `outPoint - inPoint === speed × (end - start)` for one with a `speed` set. Moving a timeline edge without moving the source point stretches the clip past th
66: - **Captions follow the primary track.** A cut that removes a span of `tracks[0]` must remove or shift the caption segments inside it, or the words desynchronise from the picture.
85: - **Transparent overlays** — float over footage. Position with `position: absolute`, leave root background alone.
110: // Track 1 — background layer (opaque sections, backgrounds)
127: - No time overlaps within a single track.
162: - **Font Awesome Solid** — fallback for anything Phosphor doesn't cover.
189: - Transparent root by default; opaque overlays set `background` on the root
===== /home/hermes/.hermes/tools/montaj/skills/image-search/SKILL.md | hits=5 =====
20: | `limit` | `10` | Max results, capped at 30 |
37: Run step `fetch_image` with the following args. Downloads one HTTPS URL to a workspace path. Private/internal IPs are blocked; non-image and oversized responses are rejected.
43: | `max-bytes` | 25 MiB | Size cap |
57: 3. **Clean frame — verify visually.** After fetching, **look at the file** (read it as an image, or run step `analyze_media` with a "is there burned-in text or a watermark?" prompt). **Reject** images with burned-in captions, news-chyron ba
70: 1. Run step `search_images` with {query:"Elon Musk portrait 2025", provider:"web", limit:6}
===== /home/hermes/.hermes/tools/montaj/skills/broll/REFERENCE.md | hits=4 =====
22: music-driven, across 9s and 67s runtimes. It is the single most reproducible number here.
118: All four use a **persistent small label**, not word-by-word captions:
126: This is a distinct artifact from `captions` and from JSX overlays. It's cheap to generate and
150: **The entire clean-cut chain is already audio-capable except `materialize_cut`.** That is the
===== /home/hermes/.hermes/tools/montaj/skills/broll/SKILL.md | hits=16 =====
61: - **`ILLUSTRATIVE`** — shows the concept rather than the named noun.
68: A protected beat gets **one unbroken shot** for its whole span, and **every shot-length limit in step 4 is suspended for it.**
70: This is not a corner case. In the reference set, the longest video holds a single locked-off tripod shot for **12.90 seconds** inside an edit whose median shot is 1.0 second — a 13× pacing inversion at the emotional peak. Cutting that momen
93: The median holds across VO-driven and music-driven references and across 9s and 67s runtimes. It is the single most reproducible number in the reference set.
98: - A beat longer than the working range is filled with **multiple shots of the same subject**, not one long hold — and this is the main lever for keeping shots short. The references show a waterfall across three angles for one 2.5s clause. O
100: - **Lean away from reusing a shot.** Repeats read as running out of material, so reach for a fresh shot first and let each one appear once where the library allows it. This is guidance, not a prohibition — reuse is available when it genuine
124: For each distinct source video behind `tracks[0].items`, call the `reframe` step once and write the returned fields verbatim onto every item cut from that source:
130: `--target` should match the project canvas (`settings.resolution`) — 9:16 for a vertical edit. The step returns `{sourceCrop, sourceWidth, sourceHeight, source}`. Write `sourceCrop`, `sourceWidth`, and `sourceHeight` onto the item exactly a
132: **Rotated iPhone footage codes as landscape (e.g. 1920x1080) but displays portrait.** Never decide orientation from the probe's coded `width`/`height` — a clip whose DISPLAY aspect is already at or narrower than the target gets no crop at a
140: Both work — render and preview both compute `muted = track.muted === true || item.muted === true` (`montaj_assets/render/project-tracks.js:260`, mirrored in `timeline-model.ts:612`) — but the track flag is the one to use, for three reasons.
146: Dropping it does three things, none of them obvious from the editor: the preview falls back to decoding the full-resolution master (on 4K HDR footage that is roughly 700ms per seek instead of ~50ms, so scrubbing feels broken), the WebCodecs
147: - **`audio.tracks`** — the cleaned voiceover, emitted as **one track per recorded take, never a single consolidated track.**
149: **This is a standing directive, not a preference.** The operator edits the narration section by section: re-timing one sentence, nudging a pause, muting a beat, replacing a take. A single 36-second track makes every one of those a destructi
159: **Single-take projects** get exactly one track, same six fields. The rule is "one track per take", not "always split" — do not carve a single continuous read into invented sections.
182: **List the footage you did not use, without apologising for it.** A short "unused" section naming each skipped clip and the one-line reason — wrong subject, weaker angle on a beat that was already covered, redundant with a stronger take, te
195: - **Putting the voiceover on a visual track.** It is audio only. This is the single most common way to get a talking-head video when the user asked for B-roll.
===== /home/hermes/.hermes/tools/montaj/skills/waveform-silence/SKILL.md | hits=5 =====
3: description: "Agent-authored workflow task: generate waveform images per clip and reason visually about silence vs. speech to produce trim specs. Use when waveform_trim's fixed threshold fails due to inconsistent background noise."
15: - Background music or ambient noise makes a fixed silence threshold unreliable
31: Run `waveform_image` for each clip. One call per clip; use background jobs for true parallelism:
54: For a 45s clip you'll have 5 chunk images covering 0–10s, 10–20s, 20–30s, 30–40s, 40–45s. **Read all five before marking a single boundary.** The noise floor reference is the flattest region across the whole clip — you can't identify it fro
68: Short spikes (single transients, mouth sounds) are not speech. Sustained amplitude that rises and falls with a voice pattern is speech.
===== /home/hermes/.hermes/tools/montaj/skills/carousel/SKILL.md | hits=9 =====
51: "base_color": "#ffffff", // background fill shown wherever no image covers
92: - A "background" image is just an image element sized to the slide at index 0. No special background type exists.
106: --prompt "soft pastel background, skincare product flat lay, minimalist" \
132: - For **charts (`bar-chart`, `line-chart`, `pie-chart`)** — single-series bar, multi-series line, pie/donut. SVG-rendered via Recharts. Sized from the overlay element's w/h.
140: - **Pick the static frame explicitly.** Carousels render a single still frame from the overlay's animation. If the JSX module exports `staticFrame`, use that value. Otherwise default to `duration - 1` (the settled pose after any entrance an
153: | Body / answer text (FAQ, captions in cards) | 28–34px | 24–28px | 22–26px |
154: | Eyebrows, kickers, all-caps labels | 18–26px | 18–22px | 18–22px |
160: - **Card-bound body text** (text inside a solid background card with padding) can run smaller — the card provides contrast, so 22–24px reads cleanly. Free-floating text on top of a base color needs more weight — 26–30px.
162: - **Letter-spacing** stays near `normal` for body, slightly negative (`-0.5px` to `-1.5px`) for large headlines, slightly positive (`2–6px`) for small all-caps labels.
===== /home/hermes/.hermes/tools/montaj/skills/ai-video-generate/SKILL.md | hits=43 =====
17: | `eval-scenes` | `skills/eval-scenes/SKILL.md` | After generating scenes in Phase 6 — quality evaluation + retry loop |
68: ### Once the guard passes, start generating.
74: - **Single-shot origin**: `tracks[0].items.some(c => c.generation?.sceneId === scene.id)`.
79: - Clip exists → **skip** (user is re-approving after editing only a subset).
80: - `scene.lastError` set AND no clip → **retry**.
97: Each scene is a separate `kling_generate` call, self-contained. **You MUST fire these in parallel** — call all scenes' `kling_generate` tool calls in a single response so they execute concurrently. Cap at 4 concurrent calls; if there are mo
101: **How to fire in parallel:** Include multiple tool calls in one assistant message. For example, if you have 5 scenes and are capping at 4 concurrent:
114: Group up to 6 scenes into ONE `kling_generate` call using `--multi-shot --shot-type customize --multi-prompt '<json>'`. Kling returns a single concatenated video. Cheaper (1 billing unit per batch vs N), stronger visual consistency across s
117: - **Per-shot prompt cap is 512 chars**, not 2500. Write tighter per-scene prose.
119: - **All-or-nothing failure.** If the batch fails on one scene, the whole batch is lost. Regenerating a single scene from a completed batch runs as a single-shot call spliced into `tracks[0].items`.
129: State your chosen mode in chat once at the start — the user can redirect if wrong.
173: - **Length caps (enforced by connector):**
174: - **Single-shot: silently truncates at 2500 chars.** Keep scene prompts under ~100 words to stay safe.
177: - Resolve `scene.refImages` IDs against `storyboard.imageRefs` (use `imageRefs[i].refImages[0]` as the primary path). Enforce the API cap of 7 refs per scene.
179: - Respect Kling's length cap: 2500 chars in single-shot, **512 chars per shot in multi-shot**.
183: #### Single-shot (independent or chained)
227: **Write `project.json` back IMMEDIATELY after each scene completes** — do not batch writes. The UI watches for changes via SSE and flips scene chips from "pending" → "done" in real time. If you wait until all scenes finish to write, the use
231: **On retry after failures:** Before retrying failed scenes, clear `lastError` on each scene you're about to retry — set `storyboard.scenes[i].lastError = undefined` and write `project.json`. This resets the UI's red "failed" chips back to "
245: Each `prompt` is the combined styleAnchor + scene prose + inline `<<<image_N>>>` tokens (SAME composition as single-shot, but respect the 512-char per-shot cap). Call:
258: Refs passed apply to any shot in the batch. Cap still 7 total.
286: Same proxy caveat as the single-shot clip above: a batched clip carries no `proxySrc` either. Step E.2 covers both.
290: **On failure (batch-level):** the whole batch is lost. Record `storyboard.scenes[i].lastError = {ts, message, batchId}` on EVERY scene in the batch. Do NOT append to `tracks[0].items`. The user can re-click Approve (Step A skips scenes with
369: **Step 2 — call the step (with Kling→Gemini fallback):**
394: # Kling TTS failed (likely due to placeholder voice IDs) — retry with Gemini.
395: agent_log(f"Kling TTS failed ({e}); retrying with Gemini TTS")
423: **Error handling:** If `generate_music` or `generate_voiceover` fails, skip the failed track — do not abort the whole project. Surface the error to the user. Continue with the other track if available.
429: - **When every `storyboard.scenes[i]` has a matching clip** (by sceneId OR batchShots sceneId) AND audio generation is complete (or skipped if no intake fields): **first backfill the editing proxies, then** set `project.status = "draft"`. T
435: Every clip on `tracks[0]` was written without a `proxySrc` — neither `kling_generate` nor the hand-written batched and subcut shapes add one. Without them the WebCodecs playback engine refuses the project (`montaj_assets/editor/src/engine/e
438: - **If some scenes failed:** leave status at `storyboard_ready`. The user sees partial progress (some cards "done," some showing error). They may re-click Approve (idempotency handles retry) or ask in chat for tweaks.
451: **When to skip:** If the user says they're happy with the clips, want to iterate manually, or are cost-sensitive (each eval = 1 Gemini call + potentially N Kling calls per scene).
453: **Note:** The eval loop does NOT revise prompts — it re-rolls generation with the same prompt, relying on Kling's non-determinism to produce a better draw. Prompt revision based on Gemini feedback is a future enhancement.
461: Don't touch the `generation` block on `tracks[0].items` clips unless explicitly asked ("regenerate scene 3 with a different prompt"). That block is a frozen snapshot of what produced the clip.
513: - Replace the single `tracks[0].items` entry with the non-degenerate pieces in order. Ripple subsequent clips.
526: - Don't drop bad entries silently. Record `lastError` so the user can fix and retry.
528: - Don't skip the snapshot step when `useFirstFrame` / `useLastFrame` is set. Those toggles are the user's explicit continuity request; honor them.
===== /home/hermes/.hermes/tools/montaj/skills/ai-video-plan/SKILL.md | hits=11 =====
54: - `storyboard.music` — `{ mode: 'upload', path }` or `{ mode: 'describe', prompt }`. Project-wide background music. Processed at Phase 6.
86: - **No cap on the number of questions.** Ask as many as you need to get the story right.
91: - **Bias toward asking when unsure.** A single clarification turn is cheaper than writing the wrong 8-scene storyboard and regenerating all of them.
106: - Your job: write `anchor` — a **detailed character/object spec** (60-120 words). This is appended verbatim to every Kling prompt that references this character as a `[LABEL] spec` block in the CHARACTER/OBJECT SPECS section, so specificity
124: **Idempotency.** Skip any imageRef whose `refImages` is already populated (from a prior run). Never regenerate silently.
136: Fold all outputs into a SINGLE `storyboard.styleAnchor` string — one cohesive anchor, not per-ref anchors. If there are no styleRefs, derive `styleAnchor` from the prompt alone (one concise style sentence) or leave it unset if the scenes do
182: **Setting** is NOT a section — put environment details in `storyboard.styleAnchor` once. If a scene needs specific lighting, include it in `## Camera` (e.g. "Golden hour lighting, wide shot").
193: - **`refImages`** — IDs into `storyboard.imageRefs[]` (NOT paths). Pick refs by matching natural-language mentions in the prompt. Hard cap of 7 refs per scene (Kling API limit).
211: 2. **Min 1 scene per project, no upper cap from the API.** In multi-shot mode, max 6 shots per call — split into multiple batches if the storyboard has more.
286: - **Don't skip Phase 0.** If intake is thin or ambiguous, ASK before writing scenes. A wrong 8-scene storyboard costs more than one clarification turn.
287: - **Don't bombard the user with multiple questions at once.** One question per turn, wait for the answer.
===== /home/hermes/.hermes/tools/montaj/skills/select-takes/SKILL.md | hits=6 =====
15: Every repeated take of the same line is wasted runtime in the final video. Your job is to identify every section of the script, find all takes of that section across all clips, select the single best delivery, and discard everything else. I
59: After picking a take, re-read its SRT segments carefully. Look for the **same phrase (3+ words) appearing more than once** within the selected window — this is a mid-take stutter where the speaker restarted a clause without a long enough pa
91: **Never encode an intermediate video file here.** There is no `trim` step to call, and reaching for `materialize_cut` at this point would break the single-encode chain for no gain. Cropping the spec keeps `tracks[0].items[*].src` pointing a
95: Run step `crop_spec` with `{"input": "/path/IMG_4893_spec.json", "keeps": [[8.5, 34.1]]}` → returns `{"path": "/path/IMG_4893_spec_cropped.json"}` (single window).
97: Run step `crop_spec` with `{"input": "/path/IMG_4893_spec.json", "keeps": [[0, 2.4], [13.84, 18.33]]}` → returns `{"path": "/path/IMG_4893_spec_cropped.json"}` (multiple windows — skip rejected content in between).
153: **Skipping the seam check.** Each section is picked independently, but the seams are where edits fall apart. A hook that ends "the source code got leaked" followed by an opener that says "they had leaked the entire source code" is the same
===== /home/hermes/.hermes/tools/montaj/skills/find_clips/SKILL.md | hits=15 =====
15: The source project has already been probed and transcribed. Your job is to find the N best self-contained moments, decide a vertical framing mode for each, and create a child vertical (9:16) project for each clip so the downstream editing w
27: Read the probe step's output for `duration`, `display_width`, and `display_height` — the rotation-corrected dimensions probe reports, not the coded `width`/`height`. `find_clips` assumes the source is horizontal (16:9 or similar wide format
45: - **zoom** — single speaker centered in frame, talking-head or walk-and-talk. Use when one subject dominates the frame and a tight crop will contain them throughout.
46: - **thirds** — source video floated in the top half of the 9:16 canvas with a background fill below. Use when the source needs spatial context (demo, screen share, two-shot, reaction with wide framing).
47: - **mix** — cropped source occupies roughly the top half as an overlay item (scale ~0.5), leaving the bottom for captions or overlays. Use for content where some cropping + extra overlay space improves the layout.
53: Call the `reframe` step against the original source file once — not per clip, the crop is the same for every window cut from this source:
70: `display_ar` here is `display_width / display_height` — the rotation-corrected dimensions `reframe` reads internally, never the probe's coded `width`/`height`. That distinction is the whole reason to call the step instead of running this ma
99: **Repeat this call once per clip.** There is no batch-create — one invocation per clip window.
145: **For thirds mode:** add the source as an overlay-track video item with `offsetY` into the top region (e.g. `y: 0`, `h: 0.5` in canvas-fraction terms) over a solid background. Set `sourceCrop` on the overlay item only if you want to crop wi
163: The command prints the cache path to stdout. Capture it, then write it into `tracks[0].items[0].normalizedSrc` in the child project (either in the same PUT that sets inPoint/outPoint, or as a follow-up PUT):
166: # Example: capture the cache path and merge it into the PUT
193: The source project is scaffolding: it exists only so this skill can probe, transcribe, and sample. Once the child clips exist, the user should **not** be left with a project for the raw source. After all child projects and their `normalized
227: The child clips are created **pending** in the `overlays` workflow — they are **not finished videos yet**. Each still needs its own editing pass (clean-cut → transcribe → captions → graphic overlays). `find_clips` ends at the fan-out bounda
232: - **(a) Finish now** — you continue and run the `overlays` workflow on each clip (clean-cut → transcribe → captions → overlays), advancing each `pending → draft`. Only do this when the user explicitly says yes.
266: **Skipping `--derived-from`.** This field is what links child clip projects back to the parent source project. Always pass the source project's `id`.
===== /home/hermes/.hermes/tools/montaj/skills/eval-scenes/SKILL.md | hits=7 =====
3: description: "Quality evaluation rubric + retry loop for ai_video generated clips. Load after generating scenes in Phase 6 to evaluate and optionally regenerate clips that fail quality checks."
9: Evaluate generated scene clips against a 5-dimension quality rubric using Gemini. If a clip fails, regenerate it via `kling_generate` (non-deterministic re-roll with the same composed prompt) and re-evaluate. Repeat up to a retry budget.
127: ## Retry budget
131: Each retry is a non-deterministic re-roll — same prompt, same refs, Kling just generates a different result. The eval loop does NOT revise prompts. If the same prompt consistently fails, the issue is editorial (bad prompt) not luck — tell t
137: On the clip's `generation` block:
161: - **Don't revise prompts in the eval loop.** Re-roll only. Prompt revision is an agent editorial decision, not a mechanical retry. If repeated re-rolls fail, tell the user.
164: - **Don't eval every project.** This is optional. Skip if the user is happy, iterating manually, or cost-sensitive.
===== /home/hermes/.hermes/tools/montaj/skills/style-profile/SKILL.md | hits=10 =====
8: A creator profile captures the visual and editorial identity of a single social media account. Once created, it gets injected into the agent context for every project that account produces — shaping every editing decision automatically.
58: For a single profile or channel URL with `--limit`, one fetch call is sufficient.
60: montaj fetch <url> --out ~/.montaj/profiles/<name>/videos/current/ --limit 15
69: Ask: **"Do you have any accounts you want to draw inspiration from? These help build a gap analysis — what your current style is vs. what you're aiming for. (Skip this if you just want to capture your current style.)"**
104: ### Step 5 — Conversational vibe capture
106: This is the part analysis alone can't do. Ask targeted questions to capture the subjective aesthetic. Pick 2–4 of these based on what the data already revealed — don't ask all of them.
116: Synthesize the answers into a 2–4 sentence editorial direction. Read it back: **"Here's what I'll put in the style profile: [synthesis]. Does that capture it?"**
186: - Color extraction requires Pillow (`pip install Pillow`). If not installed, colors will be skipped but everything else works.
188: - For TikTok/Instagram, some accounts require authentication. If `fetch` fails, ask the user to log in with `yt-dlp --cookies-from-browser chrome` and retry.
189: - Large channels: suggest `--limit 15` for initial analysis. Users can always add more later.
===== /home/hermes/.hermes/tools/montaj/skills/lyrics-video/SKILL.md | hits=40 =====
28: montaj lyrics-sync --input /tmp/stems/htdemucs/song/vocals.wav --lyrics lyrics.txt --model medium.en --out captions.json
31: Output: `captions.json` with shape `{ segments: [{ text, start, end, words: [{word, start, end}] }], audioInPoint: <seconds> }`.
41: - `Background video: /path/...` → background video provided (optional)
49: > "Do you want **simple captions** — text burned straight into the video, ready to export immediately — or **custom animated captions** that you can preview and adjust in the UI before rendering?"
53: | No background video | **JSX** always — hard rule, never use ffmpeg |
54: | "fast", "quick", "export now", "just burn it in" | **ffmpeg** (needs background video) |
56: | Background video provided, no other signal | **ffmpeg** (default — simpler) |
57: | Ambiguous with background video | Ask |
63: **ffmpeg — burned-in captions (requires background video)**
64: At render time, `render.js` sees `renderMode: "ffmpeg-drawtext"` and bypasses Puppeteer entirely — calls `lyrics_render.py` directly. Fast, no Puppeteer, output is a finished MP4. Style limited to font/size/color/position. The overlays in `
67: - `transparent: true` — text over video, no background
69: - `wordsPerLine` — match `captions.wordsPerLine` (e.g. `3`); omit if `captions.wordsPerLine` is not set
70: - `textColor` — match `captions.color` (e.g. `"white"`); use `"white"` when `captions.color` is `"auto"`
71: - `fontSize` — match `captions.fontsize` (e.g. `72`)
72: - `position` — match `captions.position`
79: At render time, Puppeteer composites `lyric-phrase.jsx` overlays over `tracks[0]`. Supports animated variants (`pop`, `fade`, `typewriter`), color-flash backgrounds, per-phrase styling. Good when the user wants control or is iterating on th
85: Requires a background video in `tracks[0]`. Both paths always build `lyric-phrase.jsx` overlays in `tracks[1]` for UI preview first.
99: "src": "/abs/path/to/background.mov",
113: "captions": {
129: The overlays in `tracks[1]` serve as the UI preview — word-sync is visible in the browser before render. At render time, `render.js` sees `renderMode` and bypasses Puppeteer, calling `lyrics_render.py` directly with the captions params abov
131: ### captions ffmpeg params
145: --captions captions.json \
147: --input background.mov \
183: `tracks[0].items` = background video loop OR empty array
188: A `lyrics_video` project has `requires_clips: false`, so its background video arrives through the prompt (`Background video: /path/…`) rather than through `montaj init`. That means nothing has encoded an editing proxy for it, and unlike a n
190: **Carrying `proxySrc` still matters.** The WebCodecs playback engine refuses the whole project when any track-0 video item lacks it (`montaj_assets/editor/src/engine/eligibility.ts:69`), so preview falls back to decoding the full-resolution
198: It computes the proxy path itself, encodes in the background, and writes `proxySrc` back onto the item over SSE. `202` means work was queued; `200` means everything was already fresh. Do not compute the path yourself and do not invent a val
202: With no background video (`tracks[0].items` is `[]`) none of this applies — there is no track-0 video item to proxy.
206: After setting up `project.json`, **open the project in the montaj UI and preview before re