{"id":"a9062b4e-2054-42c6-a4fd-8b254a8dc523","slug":"fablecut","kind":"mcp","name":"FableCut","summary":"Zero-dependency browser video editor that AI agents can drive — JSON timeline, MCP + REST, live-reloading UI","owner":"ronak-create","repoUrl":"https://github.com/ronak-create/FableCut","license":"MIT","licenseTier":"permissive","trust":"community","stars":725,"match":null,"fewStars":false,"format":"mcp","createdAt":null,"addedAt":"2026-10-14T05:37:22.484Z","logoUrl":"https://avatars.githubusercontent.com/u/84374383?u=5effe7ac04ef71067b2e299320319b3c844e5191&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["design-media","browser-web","utilities"],"tags":["ai-agent","canvas","claude","ffmpeg","javascript","llm","nle","reels"],"runtime":"node","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-14T05:43:32.670Z","sample":false,"url":"https://conduits.dev/tools/fablecut","language":"JavaScript","transports":["stdio"],"install":{"npm":"fablecut"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<div align=\"center\">\n\n<img src=\"docs/fablecut-banner.png\" alt=\"FableCut\" width=\"800\">\n\n\n**A browser video editor that AI agents can drive.**\n\n<a href=\"https://trendshift.io/repositories/77702?utm_source=trendshift-badge&amp;utm_medium=badge&amp;utm_campaign=badge-trendshift-77702\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"https://trendshift.io/api/badge/trendshift/repositories/77702/daily?language=JavaScript\" alt=\"ronak-create%2FFableCut | Trendshift\" width=\"250\" height=\"55\"/></a>\n\n[![Hacker News — front page](https://img.shields.io/badge/Hacker%20News-front%20page-ff6600?logo=ycombinator&logoColor=white)](https://news.ycombinator.com/item?id=48845422)\n[![DEV — Top 7 of the week](https://img.shields.io/badge/DEV-Top%207%20of%20the%20week-0A0A0A?logo=devdotto&logoColor=white)](https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-815)\n[![Official MCP registry](https://img.shields.io/badge/MCP%20registry-io.github.ronak--create%2Ffablecut-7b6cff?logo=modelcontextprotocol&logoColor=white)](https://registry.modelcontextprotocol.io/v0/servers?search=fablecut)\n[![Mentioned in Awesome MCP Servers](https://awesome.re/mentioned-badge.svg)](https://github.com/punkpeye/awesome-mcp-servers)\n[![Glama score](https://glama.ai/mcp/servers/ronak-create/FableCut/badges/score.svg)](https://glama.ai/mcp/servers/ronak-create/FableCut)\n[![Glama — #18 Best Browser Automation MCP Servers](https://img.shields.io/badge/Glama-%2318%20Best%20Browser%20Automation-0e1618)](https://glama.ai/mcp/best/browser-automation)\n[![Docs](https://img.shields.io/badge/Docs-fablecut.space%2Fdocs-7b6cff)](https://fablecut.space/docs/)\n[![Discord](https://img.shields.io/badge/Discord-join%20the%20community-5865F2?logo=discord&logoColor=white)](https://discord.gg/EFMQH7d6Tv)\n\n**English** · [简体中文](docs/i18n/README.zh-CN.md) · [日本語](docs/i18n/README.ja.md) · [Español](docs/i18n/README.es.md) · [Português (BR)](docs/i18n/README.pt-BR.md)\n\n</div>\n\n<https://github.com/user-attachments/assets/2430b854-168b-4a9a-af2e-489e5efa7543>\n\nFableCut is a Premiere-style non-linear video editor that runs entirely in your\nbrowser — and exposes its whole timeline as one JSON document. Edit it by hand,\nfrom the UI, or let an AI agent (Claude Code, Claude Desktop, or anything that\nspeaks MCP/REST) cut your video for you while you watch the timeline update\nlive.\n\nZero npm dependencies. One `node server.js`. That's it.\n\n![FableCut editor](docs/screenshot.png)\n\n## Why it's interesting\n\nMost \"AI video\" tools hide the edit behind an API. FableCut flips that: the\n**project file is the interface**. `project.json` describes media, clips,\ntracks, effects, keyframes and transitions — any process that can write JSON\ncan edit video, and the open browser UI hot-reloads within ~150 ms via\nserver-sent events. A human and an agent can work on the same timeline at the\nsame time.\n\n## Features\n\n**Editing**\n\n- Video + audio tracks (default 3+4; add more with **+V** / **+A** in the track\n  header; right-click an empty header → **Remove track**), drag/trim/split/snap,\n  undo/redo\n- **Settings** (cog in the top bar) — optional prefs stored in this browser via\n  `localStorage`. Enable **Link timeline and Project bin selection** so picking a\n  timeline clip highlights its media in Project, and clicking a Project item\n  selects every timeline clip that uses it (off by default).\n- Video + audio tracks (default 3+4), drag/trim/split/snap, undo/redo\n  - **+V** / **+A** in the track header add a video or audio lane (up to 16 each)\n  - Right-click an empty track header → **Remove track** (disabled if the lane\n    has clips, or if it would leave you with zero video/audio tracks)\n  - Track header **S** solos that lane (mutes all others); click again to restore\n    the previous mute state. Using the mute toggle while soloed exits solo.\n  - **Track targeting** — click a track's name to target / untarget it (lit =\n    targeted). Split, insert, ripple, close gap and jump-to-cut touch targeted\n    tracks only; the eye / speaker toggle is output-only (hide from preview and\n    export) and no longer blocks edits. A selected clip is edited wherever it sits.\n  - **Track lock** — the padlock in the track header. Nothing on a locked track\n    can be moved, trimmed, split or deleted, and ripples leave it in place while\n    the other tracks shift — lock the music bed and re-cut the picture freely.\n- **Clip lock, disable and unlink** — right-click a clip (or use the toggles at\n  the top of the inspector): **Lock** pins it like a locked track; **Disable**\n  (<kbd>⇧E</kbd>) keeps it on the timeline but hides it from preview and export;\n  **Unlink** (<kbd>Ctrl/Cmd+L</kbd>) splits a video from its audio so they move\n  separately, and **Link** re-joins them once they line up again. Agents see\n  locks too: `fablecut_patch_project` refuses to edit locked clips unless the\n  op says `force: true`.\n  - Dropping a video with more audio channels than A-tracks **adds the missing\n    lanes automatically** (up to 16) and toasts how many were added; each channel\n    becomes a linked stem on its own A-track\n- **Direct manipulation on the monitor** — click a clip or title on the preview to\n  move, resize (corner handles), or rotate (top handle, Shift-snap) it directly\n- **Timeline multi-select** — rubber-band marquee (drag on empty track area),\n  <kbd>Ctrl/Cmd/Shift+click</kbd> to add/remove clips, <kbd>Ctrl+A</kbd> to\n  select all, <kbd>Esc</kbd> to deselect. Drag any selected clip to move the\n  whole group; <kbd>Delete</kbd> removes all selected; <kbd>S</kbd> splits all\n  selected at the playhead. Inspector shows an \"N clips selected\" banner.\n- Beat & cue markers (tap <kbd>m</kbd> on the beat during playback) — name and colour them, drag them on the ruler, jump with <kbd>⇧m</kbd> / <kbd>Alt+⇧m</kbd> or the **Markers** list; snapping targets (clip edges, playhead, markers, IN/OUT, keyframes, frame grid) are picked from the **▾** beside Snap\n- Press <kbd>Alt+t</kbd> to add an in/out transition based on the playhead position over the selected clip. The last used transition is remembered as the default. Drag the overlay triangle to adjust duration; <kbd>Delete</kbd> clears the focused transition.\n- Real decoded audio waveforms on clips\n- **Mixer** — the **Mixer** tab beside the Inspector has a strip per audio\n  track (fader, pan, mute, solo, meter) and a master fader with a live LUFS\n  readout. Preview and export run through the same mix, so what you hear is\n  what renders.\n- **Clip gain, channels and Normalize** — each audio clip has a **Gain** (dB,\n  before volume and keyframes), a **Channels** mode (stereo, mono, left,\n  right, swap) and **Normalize**: measure the selected clips (ITU-R BS.1770\n  loudness or sample peak) and set their gain to hit −14 / −16 / −23 LUFS or\n  −1 dBFS. Linked stems share one gain so a stereo pair stays balanced.\n- **Volume line, fades and crossfades** — every audio clip shows its volume as\n  a line you drag; Ctrl/Cmd-click adds a keyframe, Alt-click removes one. Corner\n  grips drag fades in and out, drawn with their real curve (constant power,\n  constant gain or exponential). **Shift+D** crossfades the cut next to the\n  selection, borrowing spare media from both sides so nothing else moves.\n- **Auto-duck** — select the music, pick the dialogue track and an amount, and\n  the music dips wherever someone speaks (ramping down just before, back up\n  after). It rides on top of the music's own volume, so re-running or clearing\n  it never touches your levels. Agents use `fablecut_auto_duck`.\n- **Audio effects and presets** — EQ, high/low-pass, compressor, limiter,\n  noise gate, delay, reverb, distortion, stereo width and pitch shift, chained\n  per clip, per track (Mixer → **FX**), per bus and on the master. Presets:\n  Clean voice, Podcast, Radio, Deep voice, Telephone, Cinematic, Wide and\n  Muffled, all tweakable afterwards. Preview and export run the same effects.\n  Agents use the `setFx` patch op.\n- **Effect automation** — the ◆ beside an effect setting keys it at the\n  playhead, like clip keyframes: sweep a filter into the drop, open up a\n  reverb at the end. Agents use `setFxKeys`.\n- **Submix buses** — **+ Bus** in the Mixer adds a bus with its own effects,\n  fader, pan, mute and meter; route tracks into it from the menu under each\n  track's name (all the dialogue through one compressor and one fader).\n- **Noise reduction** — the inspector's **Noise** control (Light / Medium /\n  Strong) measures the file's noise floor and renders a cleaned copy with\n  ffmpeg; the clip's audio switches to it and **Off** switches back. Agents\n  use `fablecut_denoise`.\n- **Project bin folders** — tree view with expand/collapse; drag media or folders to nest; right-click the **Project** tab → New folder; drop files onto a folder to import into it\n- **Import from URL** — **+ URL** downloads an HTTPS video/audio/image into\n  `./media/` (same-origin after import). Remote SVG is refused. Agents use\n  `fablecut_import_media` with an `https://` path. The URL is not kept as\n  `media.src` — that would taint the canvas and break export.\n- **Audio Hold** — timeline toolbar toggle: while paused, loops **one frame** of\n  audio at the playhead (useful when stepping frame-by-frame). Scrubbing or\n  frame-step retargets the held slice; meters stay live. **Play** / **Pause**\n  turns it off.\n- Canvas aspect presets (16:9, 9:16 reels, 4:5, 1:1) + project FPS select\n  (24 / 25 / 30 / 50 / 60; non-preset rates show as Custom) + safe-area guides\n- **Export frame / reframing** — composition canvas can be larger than the delivery\n  crop (`exportFrame` in `project.json`). Preview dims the overscan; drag the\n  **Export frame** handle to reframe (e.g. 16:9 canvas → 9:16 export). Fast export\n  crops to the frame; WebCodecs and Realtime export are disabled while a frame is set\n- **Program Monitor zoom** — mouse-wheel over the preview zooms the composition\n  toward the cursor (fit → up to **2 screen pixels per canvas pixel**). Magnified\n  view uses **native scrollbars** so overflow stays reachable; middle-click or\n  <kbd>Alt</kbd>+drag pans. The **Fit** button (shown while zoomed) resets to the\n  fit-to-stage baseline\n- Full **J**/**K**/**L** shuttle — <kbd>L</kbd> plays forward, <kbd>J</kbd> in reverse; tap\n  again for 1.5×/2×/4×, the other key turns around, <kbd>K</kbd> stops. Hold <kbd>K</kbd> and\n  tap <kbd>J</kbd>/<kbd>L</kbd> to step a frame, or hold both to crawl at ¼ speed. Preview\n  only, never the export\n- Typed timecode — click the playhead readout (or type digits) to jump: `01:15:00`,\n  `1500`, `+30`, `12.5`; the IN / OUT readouts take typed times too\n- Resizable workspace: drag the divider between monitor and timeline (double-click resets), plus S/M/L timeline track-density presets (S hides thumbnails for compact tracks)\n- **Zoom to selection** (<kbd>⇧Z</kbd>) frames all selected clips, not just one\n- **IN/OUT work area** — set markers with <kbd>i</kbd> and <kbd>o</kbd> (<kbd>⇧I</kbd> / <kbd>⇧O</kbd> to clear). The Program Monitor shows playhead as `current / sequence duration`; when markers are set, IN, marked duration, and OUT stack on the right. **Export** has a Range dropdown (Entire timeline / IN–OUT; defaults to IN–OUT when markers exist) so you can keep markers for split/trim and still export the full sequence. Enabling **Limit** constrains playback to the marked range and maps <kbd>Home</kbd> / <kbd>End</kbd> to the IN and OUT positions rather than the full timeline. <kbd>t</kbd> splits clips at the markers; <kbd>⇧t</kbd> trims clips to the work (between marker in and marker out) area.\n- **Find & close gaps** — a gap is a stretch where every targeted track is empty (black frames). <kbd>g</kbd> jumps the playhead to the next shared gap (wraps; respects IN/OUT when both are set). <kbd>⇧G</kbd> closes the gap under the playhead by pulling later clips left on all targeted tracks (locked clips stay put).\n- **Trim tools** — a tool picker in the timeline toolbar (or <kbd>V</kbd> <kbd>B</kbd> <kbd>R</kbd> <kbd>Y</kbd> <kbd>U</kbd>): **Selection**, **Ripple edit** (drag a clip edge and everything after it follows, so no gap opens), **Rolling edit** (drag a cut between two clips; nothing else moves), **Slip** (change which part of the source a clip shows without moving it) and **Slide** (move a clip while its neighbours trim to make room). Every tool respects source length, targeting, locks and linked audio, and shows the offset beside the pointer while you drag. Agents run the same edits — split, ripple delete, lift / extract, insert / overwrite, ripple / roll / slip / slide and crossfade — as `fablecut_patch_project` ops, on the same code.\n- **Lift / Extract** — <kbd>;</kbd> removes the IN→OUT range on the targeted tracks and leaves the gap; <kbd>'</kbd> removes it and closes the gap. Both also sit in the timeline toolbar.\n- **Jump to cut** — <kbd>↑</kbd> / <kbd>↓</kbd> move the playhead to the previous / next edit (clip In or Out). With a clip selected, the first taps land on that clip’s start then end (Premiere-style); with no selection they walk cuts on targeted tracks. In the Source monitor they jump among 0, In, Out, and duration. Left/right still step frames; Home/End still go to the sequence (or IN/OUT with Limit).\n- **Ripple delete** — the timeline **Ripple delete** button (or <kbd>⇧Del</kbd>) removes the selection and pulls later clips left on each **targeted** track to close the gap; plain <kbd>Del</kbd> still lifts (leaves a gap). Linked AV partners always move together, even on untargeted tracks (sync lock); locked clips are never deleted or moved.\n- **Reset a property** — <kbd>Ctrl/Cmd+click</kbd> an inspector **label** or **slider** restores that effect/prop to its default *and* clears every keyframe on the channel (scale → 1, opacity → 1, paired fields like Crop L/R reset together; transition labels clear the in/out transition). <kbd>Shift+click</kbd> a label is playhead-local: if you are parked on a keyframe it removes **that** keyframe only; otherwise it sets the value at the playhead to the default (auto-keys if the channel is already animated).\n- **Replace media** — the inspector's **Source** button (any video/audio/image/svg\n  clip) swaps the underlying file while keeping position, trim, keyframes,\n  transitions and every effect. Pick another item already in the bin or\n  **Browse file…** to import and replace in one step. A video's linked L/R\n  audio companions are swapped along with it; a shorter replacement clamps the\n  trim to fit and toasts that it did so.\n- **Multi-channel video audio** — a video with more than 2 audio channels gets\n  a linked audio clip per channel, not just L/R (5.1, 7.1…). Extra audio\n  tracks (A5, A6, …, capped at 16) are created automatically as needed;\n  replacing a clip's media re-syncs the linked channel clips to the new\n  source's channel count, adding/dropping extras and new tracks as needed.\n\n**Look**\n\n- 14 one-click filter presets (cinematic, teal-orange, noir, vintage, cyberpunk, sunset, midnight…)\n- **Adjustment layers** — one clip grades everything below it, Premiere-style\n- **Color workspace** (top bar → **Color**): live **waveform, RGB parade,\n  vectorscope and histogram** beside the program monitor, and a **Color** tab\n  that grades the selected clip on the GPU — **lift / gamma / gain / offset\n  wheels**, exposure, white balance with a **picker** (click something white),\n  blacks / shadows / midtones / highlights / whites, log-style contrast with a\n  pivot, soft rolloff and saturation, plus **curves** — luma and R / G / B,\n  hue vs hue, hue vs saturation, hue vs luma and saturation vs luma, with a\n  picker that marks a colour from the monitor, and **layers** (secondaries):\n  a correction limited by an HSL **qualifier** and / or an ellipse, rect,\n  polygon, bezier or free-hand **mask** (feathered, invertible, keyframable,\n  dragged on the monitor), with a matte view. Copy / paste a grade across shots.\n  Agents grade with the `setGrade` patch op and read the result as numbers\n  with `fablecut_scopes` (levels, clipping, colour cast)\n- Quick filter sliders: brightness/contrast/saturation/hue, **temperature & tint**,\n  blur, grayscale/sepia/invert, **vignette**, animated **film grain**\n- 17 blend modes (screen, multiply, overlay, color-burn, exclusion, hue,\n  luminosity…), fit modes (contain/cover/stretch),\n  per-edge cropping, corner radius, flip H/V\n- **Masks** — isolate any part of a clip (video, image, SVG, text or an\n  adjustment layer): rectangle, ellipse, **bezier pen** and **free-hand**\n  shapes, several per clip, combined with add / subtract / intersect /\n  difference, each with feather, expansion, invert and opacity, all\n  keyframable (outlines morph). Draw and edit them on the monitor, with a\n  matte view. Agents use the `setMask` patch op and measure with `fablecut_scopes`\n- **Shapes and motion graphics** — shape layers of rectangles, ellipses,\n  polygons, stars, lines and pen-drawn bezier paths in groups, with fill,\n  stroke, dashes and trim paths for draw-ons; null objects, parenting and an\n  anchor point on every clip; every value keyframes, edited right on the\n  monitor. Agents use the `setShape` and `setParent` patch ops\n- **Motion paths, motion blur and text on a path** — bend a clip's travel into\n  a curve with handles on the monitor, turn it along the way, blur fast moves\n  with a shutter angle (preview and export), and set titles along lines, arcs,\n  circles or drawn paths. Agents use the `setMotionPath` and `setTextPath`\n  patch ops\n- **Compositions** — nested sequences: build a lower third, a logo sting or a\n  scene once and place it anywhere as one clip that moves, masks, grades and\n  blends like a picture, while its video and audio play and export as usual.\n  Open one to edit it on the timeline, or precompose a selection. Agents use\n  the `addComp`, `inComp` and `precompose` patch ops\n- **Animation presets and templates** — 33 ready-made entrances, exits,\n  emphases and loops that fit any clip where it sits, and templates (lower\n  thirds, logo animations, 9:16 / 1:1 / 16:9 social layouts) whose text,\n  colours and logo you fill in, each placed as its own comp. Save your own\n  animations and comps to the library for every project. Agents use the\n  `applyPreset`, `addTemplate` and `setTemplate` patch ops\n- **Motion tracking** — follow a point or a region (with its scale and\n  rotation) through a video clip, then make a mask follow it or pin a title,\n  sticker or any clip to it; the result is ordinary editable keys. Agents use\n  `fablecut_track`\n- **Track mattes** — cut a clip with the picture on the track above by its\n  alpha or its luma (inverted or not): text filled with video, shape reveals,\n  texture cut-outs. The matte track hides itself. Agents use `setMatte`\n- **Chroma key** (green screen) with tolerance/softness + spill suppression\n- **AI background removal** (person cut-out, in-browser via MediaPipe)\n\n**Motion**\n\n- Keyframe animation on ~25 properties with easing\n- **Keyframe markers on clips** — diamonds on the clip body at each unique\n  keyframe time (tooltip lists channels; a count badge when several share a\n  time). <kbd>Ctrl/Cmd+←</kbd> / <kbd>Ctrl/Cmd+→</kbd> jumps the playhead to\n  the previous / next keyframe (selected clips first, else clips under the\n  playhead). Inspector fields show the interpolated value at the playhead;\n  changing one updates the keyframe you’re on, or inserts one if that channel\n  is already keyed. Dragging a clip in the program monitor (move / scale /\n  rotate) writes the same way. The ◆ button adds a keyframe at the playhead, or removes\n  the one you’re parked on; ✕ clears the whole channel. When the playhead is\n  outside the selected clip, keyframed fields and ◆ buttons are disabled (they\n  show the nearest edge value) — keyframe edits only apply where the playhead\n  actually is; unanimated properties stay editable anywhere\n- **Keyframe graphs** — toggle a property’s curve in the inspector to show an\n  interpolated value graph beside the program monitor; click the graph to seek\n- **Speed ramps** — keyframe `speed` and the engine time-remaps video *and* the\n  export audio mix (the fast-into-slow-mo reel move)\n- **Camera shake** and **RGB-split/chromatic aberration**, both animatable\n- 17 transitions: fades, slides, wipes (4 directions), zoom, iris, spin, blur,\n  whip-pan, **glitch**, **pop**\n\n**Text**\n\n- **Title styles** — one-tap cohesive looks (Impact, Elegant, Kinetic cut, Neon,\n  Handwritten, Luxury, and more); new titles vary the font, placement and animation\n  automatically instead of defaulting to one flat style\n- Kinetic captions: typewriter, word-pop, word-slide, karaoke, **letter-pop**,\n  **wave**, **bounce**, **shake**, **clip-reveal**, **zoom-in**, **font-cut**\n  (rhythmic typeface cuts), **rise-mask**\n- **Neon glow** for that TikTok caption look\n- Font editor: system fonts, drop-in custom fonts (`library/fonts/`), and **any\n  Google Font by name** — loaded automatically\n- Gradient fills, outline, background pills, letter-spacing, line-height,\n  weights, italic, uppercase, soft shadows\n- **Text layout** — horizontal Align: left / center / right / **justify**\n  (extra spaces between words). Drag a title’s corner handles to create a\n  **text box** (`boxW` / `boxH`); further corner drags resize it (opposite\n  corner stays fixed; <kbd>Ctrl/Cmd</kbd> resizes from center; <kbd>Shift</kbd>\n  locks aspect). Inside a box, text wraps at the fixed font size by default;\n  enable **Scale to fit** to shrink the font so the whole block fits. **V-align**\n  (top / middle / bottom) places the text block vertically in the box. Set Box\n  W/H to `0` to return to hug-content sizing.\n\n**Animated SVG clips**\n\n- A first-class `svg` clip kind: CSS-`@keyframes`-animated SVGs render\n  **frame-accurately** in preview and export (the compositor freezes the\n  animation at any time). Agents can author their own vector overlays —\n  lower-thirds, confetti, sparkles — as plain `.svg` files. Starters included.\n\n**Remake a reference video**\n\n- Give it a reference edit (a reel you like) and get back an **edit blueprint**:\n  shot boundaries, music beats + BPM, a loudness curve, per-shot energy, the\n  drop — plus the reference's **music track extracted** into your media, ready\n  to rebuild the same idea with your own footage. Zero extra dependencies\n  (ffmpeg does the decoding; onset/tempo detection is plain Node).\n  `node analyze.js ref.mp4`, `POST /api/analyze`, or the\n  `fablecut_analyze_reference` MCP tool.\n\n**Look at the footage**\n\n- An agent (or you, over REST) can fetch an actual **image** of any moment:\n  `GET /api/frame?src=/media/x.mp4&t=3.2` returns a JPEG of that frame, and\n  `&frames=12` returns a 4×3 **contact sheet** across the clip — a cheap survey\n  of everything a 3-minute take holds. Grabs are cached under `analysis/frames/`.\n- The `fablecut_frame` MCP tool wraps it and returns the image inline, so a\n  multimodal model can *look*. Pass a `time` instead of a `path` and it renders\n  the **composed timeline** through the editor's own compositor — graded, all\n  tracks, identical to what export produces — so \"is this grade right?\" and \"what\n  did I actually build?\" have a visual answer.\n- Together with the analyzer above, agents pick footage by looking at it instead\n  of guessing from an energy number.\n\n**Asset library**\n\n- `library/` folders surface as tabs in the UI: **Elements** (overlay art),\n  **Sound FX**, **SVG** — drop files in, the open editor refreshes live\n\n**Export**\n\n- Fast export: browser renders every frame + an offline audio mix; ffmpeg\n  encodes **JPEG frames** via an **encoding profile** from\n  `encoding-profiles.json` (keeps rendering if you switch tabs). Encode and\n  upload run ahead of the compositor so a fast timeline is not stalled by\n  `toBlob`. The Export dialog has a profile selector; pin a project default\n  with `encodeProfile` in `project.json`\n- WebCodecs export: the browser HW-encodes Annex-B H.264; the server\n  stream-copies and muxes audio. Faster uploads; bitrate/VBR-CBR in the\n  Export dialog. Unavailable while an export frame is set (use Fast)\n- Realtime MediaRecorder fallback when ffmpeg or WebCodecs isn't available\n- Agents export too: `fablecut_export` runs the Fast export in the open editor,\n  or in a headless Chrome / Edge the server starts, and returns the file path\n- Export **Range** dropdown: Entire timeline or IN–OUT (defaults to IN–OUT when\n  markers are set). Effective IN/OUT export bounds are clamped to `projDur()`.\n\n## Quick start\n\n```bash\nnpx -y fablecut       # → http://localhost:7777\n```\n\nYour projects, media and exports go to `~/FableCut`. Or run it from a clone:\n\n```bash\ngit clone https://github.com/ronak-create/FableCut.git\ncd FableCut\nnode server.js        # → http://localhost:7777\n```\n\nRequirements: **Node 18+** and a Chromium-based browser. **ffmpeg on PATH** is\noptional but recommended (fast export + upload remuxing). AI background\nremoval fetches its model from a CDN on first use.\n\nThe server binds **127.0.0.1 only** (v1.3.1+). To use it from another device on\nyour LAN, opt in explicitly: `HOST=0.0.0.0 FABLECUT_ALLOWED_HOSTS=<your-ip> node server.js`.\n\nDrop media into the window (or `./media/`), paste an HTTPS URL via **+ URL**,\ndrag clips onto the timeline, edit, export.\n\nTo keep your work outside the checkout, set **`FABLECUT_DATA_DIR`** — it moves\n`project.json`, `media/`, `exports/`, `analysis/` and `library/` to a directory\nyou choose. Leave it unset and everything stays in the repo, exactly as before.\n\n### Or install it as a Claude Code plugin\n\n```\n/plugin marketplace add ronak-create/FableCut\n/plugin install fablecut@fablecut\n```\n\nThat registers the MCP server for you and adds three skills — `edit-video`,\n`remake-reel` and `motion-graphics`. Your timeline and footage live in the plugin's own data\ndirectory, so an update never touches them. Node 18+ and (optionally) ffmpeg\nstill need to be on your machine.\n\n## Driving it with an AI agent\n\nEverything an agent needs is in **[CLAUDE.md](CLAUDE.md)** — the complete\nschema, semantics and recipes. Point any capable model at that file and it can\noperate the editor end to end.\n\n> 📖 **Browsable docs:** the same manual as web pages, one page per topic\n> (MCP tools, the `project.json` schema, clip props, recipes, REST API,\n> export): **[fablecut.space/docs](https://fablecut.space/docs/)**.\n\nThree equivalent control surfaces:\n\n1. **MCP** (best for Claude Code / Claude Desktop) — register the bundled\n   zero-dependency MCP server once:\n\n   ```bash\n   claude mcp add -s user fablecut -- npx -y fablecut mcp\n   ```\n\n   No clone or path needed; your work lives in `~/FableCut`. From a clone,\n   point at the file instead:\n\n   ```bash\n   claude mcp add -s user fablecut -- node \"<path-to>/fablecut/mcp-server.js\"\n   ```\n\n   **OpenCode** can use the same stdio server from its project or global\n   `opencode.json` configuration:\n\n   ```json\n   {\n     \"$schema\": \"https://opencode.ai/config.json\",\n     \"mcp\": {\n       \"fablecut\": {\n         \"type\": \"local\",\n         \"command\": [\"node\", \"/absolute/path/to/FableCut/mcp-server.js\"],\n         \"enabled\": true\n       }\n     }\n   }\n   ```\n\n   For another MCP client, register a local stdio server with this equivalent\n   command. The exact key names vary by client, but the command and arguments\n   do not:\n\n   ```json\n   {\n     \"name\": \"fablecut\",\n     \"transport\": \"stdio\",\n     \"command\": \"npx\",\n     \"args\": [\"-y\", \"fablecut\", \"mcp\"]\n   }\n   ```\n\n   (From a clone: `\"command\": \"node\"`, `\"args\": [\"/absolute/path/to/FableCut/mcp-server.js\"]`.)\n\n   The server is intentionally client-neutral. It speaks MCP over stdio and\n   does not require Claude-specific environment variables. With a clone, keep\n   the path absolute. Node 18 or newer either way.\n\n   Tools: `fablecut_status` (auto-starts the editor), `fablecut_docs`,\n   `fablecut_get_project`, `fablecut_set_project`, `fablecut_patch_project`,\n   `fablecut_import_media`, `fablecut_analyze_reference`, `fablecut_frame`,\n   `fablecut_encode_profiles`, `fablecut_normalize_audio`, `fablecut_auto_duck`,\n   `fablecut_denoise`, `fablecut_export`, `fablecut_scopes`, `fablecut_track`.\n\n   FableCut is also published on the **official MCP registry** as\n   [`io.github.ronak-create/fablecut`](https://registry.modelcontextprotocol.io/v0/servers?search=fablecut)\n   — each release ships an MCPB bundle (`fablecut.mcpb`) that MCPB-capable\n   clients can install directly.\n\n   The surface is **token-efficient by design**: agents patch the timeline with\n   small ops (`fablecut_patch_project`) instead of round-tripping the whole\n   document, read a compact one-line-per-clip summary\n   (`fablecut_get_project {compact:true}`), and fetch only the manual sections\n   they need (`fablecut_docs {section:\"props\"}`).\n2. **The file** — read `project.json`, modify, bump `revision`, write. The UI\n   live-reloads.\n3. **REST** — `GET/PUT /api/project`, `POST /api/upload`, `POST /api/import-url`,\n   `GET /api/library`, `GET /api/export/profiles`, SSE at `/api/events`. See\n   CLAUDE.md for the full list.\n\nExample: ask Claude Code *\"cut these six clips to the beat markers, add a\nteal-orange grade, put a word-pop caption on top and a whoosh on every cut\"* —\nand watch the timeline rebuild itself.\n\nOr hand it a reference: *\"here's a reel I like — analyze it and remake it with\nmy clips, same music\"*. The agent calls `fablecut_analyze_reference`, gets the\nblueprint (cuts, beats, BPM, energy, drop, extracted music), and rebuilds the\nstructure shot-for-shot with your footage.\n\n**The agent can see, not just measure.** `fablecut_analyze_reference` gives it\nthe *ears* — where the cuts land, which shots hit hard. `fablecut_frame` gives it\nthe *eyes*: ask for any moment of any clip (`{path, t:3.2}`) and the call comes\nback with an actual image the model can look at, or ask for a 12-frame contact\nsheet to survey a whole clip in one call (`{path, frames:12}`). Pass a `time`\nwith no `path` and it renders the composed timeline — graded, all tracks, exactly\nas export would. So footage gets chosen by looking at it rather than guessing\nfrom a number, and a grade gets checked against the real picture.\n\n**Conflict-safe concurrent editing**: the UI, the MCP tools, and direct\n`project.json` writes all agree on a `revision` counter. If you edit a clip in\nthe UI while an agent is mid-task, the agent's next write is rejected (409 from\nthe REST API / a conflict error from `fablecut_set_project`) instead of\nsilently overwriting your change. The UI similarly detects when an agent write\nsupersedes a not-yet-saved local tweak and tells you with a toast instead of\ndropping it silently.\n\n## Project layout\n\n```\nserver.js        zero-dependency HTTP server: static hosting, REST API, SSE,\n                 ffmpeg export pipeline\napp.js           the editor: timeline UI, compositor, keyframes, text engine,\n                 SVG rasterizer, chroma key, exporters\nindex.html       single-page UI\nstyle.css        dark editor theme\nmcp-server.js    stdio MCP server exposing the editor to AI agents\nanalyze.js       reference-video analyzer: shots, beats/BPM, energy, drop,\n                 music extraction (module + CLI)\nCLAUDE.md        the agent manual (schema + recipes) — also served by fablecut_docs\nencoding-profiles.json\n                 Fast-export ffmpeg presets (hot-reloaded)\nproject.json     your timeline (created on first run; gitignored)\nmedia/           project footage (gitignored)\nanalysis/        cached edit blueprints from /api/analyze (gitignored)\nlibrary/         default assets: elements/ sfx/ svg/ fonts/\nexports/         finished renders (gitignored)\n```\n\n## Architecture Overview\n\n```mermaid\nflowchart TD\n\nsubgraph group_interaction[\"Editing Experience\"]\n  node_browser_ui[\"Browser Editor<br/>[app.js]\"]\n  node_timeline_model[\"Timeline Model<br/>[app.js]\"]\n  node_ruler_worker[\"Ruler Worker<br/>[ruler-worker.js]\"]\nend\n\nsubgraph group_project_media[\"Project And Media\"]\n  node_project_store[(\"Project Store<br/>[paths.js]\")]\n  node_media_store[(\"Media Store<br/>[paths.js]\")]\n  node_asset_library[(\"Asset Library<br/>[server.js]\")]\n  node_url_importer[\"URL Importer<br/>[import-url.js]\"]\nend\n\nsubgraph group_agent_api[\"Agent Control\"]\n  node_rest_api[\"REST Server<br/>[server.js]\"]\n  node_mcp_server[\"MCP Server<br/>[mcp-server.js]\"]\n  node_sse_hub[\"Change Notifications<br/>[server.js]\"]\nend\n\nsubgraph group_playback_export[\"Playback And Export\"]\n  node_compositor[\"Canvas Compositor<br/>[app.js]\"]\n  node_audio_engine[\"Audio Engine<br/>[app.js]\"]\n  node_audio_meter[\"Audio Meter<br/>[meter-worklet.js]\"]\n  node_export_engine[\"Export Engine<br/>[server.js]\"]\n  node_encoding_profiles[\"Encoding Profiles<br/>[encode-profiles.js]\"]\nend\n\nsubgraph group_analysis[\"Analysis Tools\"]\n  node_reference_analyzer[\"Reference Analyzer<br/>[analyze.js]\"]\nend\n\nnode_human((\"Human Editor\"))\nnode_ai_agent((\"AI Agent\"))\nnode_ffmpeg[\"FFmpeg\"]\n\nnode_human -->|\"edits timeline\"| node_browser_ui\nnode_ai_agent -->|\"sends tools\"| node_mcp_server\nnode_browser_ui -->|\"updates project\"| node_timeline_model\nnode_timeline_model -->|\"persists JSON\"| node_project_store\nnode_browser_ui -->|\"calls REST\"| node_rest_api\nnode_rest_api -->|\"reads writes\"| node_project_store\nnode_rest_api -->|\"serves media\"| node_media_store\nnode_rest_api -->|\"lists assets\"| node_asset_library\nnode_mcp_server -->|\"checks server\"| node_rest_api\nnode_mcp_server -->|\"patches project\"| node_project_store\nnode_mcp_server -->|\"imports media\"| node_url_importer\nnode_url_importer -->|\"stores downloads\"| node_media_store\nnode_rest_api -->|\"downloads URLs\"| node_url_importer\nnode_rest_api -->|\"broadcasts changes\"| node_sse_hub\nnode_sse_hub -->|\"pushes changes\"| node_browser_ui\nnode_timeline_model -->|\"renders timeline\"| node_compositor\nnode_timeline_model -->|\"routes clips\"| node_audio_engine\nnode_audio_engine -->|\"measures audio\"| node_audio_meter\nnode_browser_ui -->|\"uploads frames\"| node_rest_api\nnode_rest_api -->|\"streams export\"| node_export_engine\nnode_export_engine -->|\"loads profile\"| node_encoding_profiles\nnode_export_engine -->|\"encodes video\"| node_ffmpeg\nnode_reference_analyzer -->|\"analyzes media\"| node_ffmpeg\nnode_reference_analyzer -->|\"writes music\"| node_media_store\nnode_ai_agent -.->|\"requests analysis\"| node_reference_analyzer\nnode_browser_ui -.->|\"draws ruler\"| node_ruler_worker\n\nclick node_browser_ui \"https://github.com/ronak-create/fablecut/blob/main/app.js\"\nclick node_timeline_model \"https://github.com/ronak-create/fablecut/blob/main/app.js\"\nclick node_compositor \"https://github.com/ronak-create/fablecut/blob/main/app.js\"\nclick node_audio_engine \"https://github.com/ronak-create/fablecut/blob/main/app.js\"\nclick node_audio_meter \"https://github.com/ronak-create/fablecut/blob/main/meter-worklet.js\"\nclick node_rest_api \"https://github.com/ronak-create/fablecut/blob/main/server.js\"\nclick node_mcp_server \"https://github.com/ronak-create/fablecut/blob/main/mcp-server.js\"\nclick node_sse_hub \"https://github.com/ronak-create/fablecut/blob/main/server.js\"\nclick node_project_store \"https://github.com/ronak-create/fablecut/blob/main/paths.js\"\nclick node_media_store \"https://github.com/ronak-create/fablecut/blob/main/paths.js\"\nclick node_asset_library \"https://github.com/ronak-create/fablecut/blob/main/server.js\"\nclick node_url_importer \"https://github.com/ronak-create/fablecut/blob/main/import-url.js\"\nclick node_export_engine \"https://github.com/ronak-create/fablecut/blob/main/server.js\"\nclick node_encoding_profiles \"https://github.com/ronak-create/fablecut/blob/main/encode-profiles.js\"\nclick node_reference_analyzer \"https://github.com/ronak-create/fablecut/blob/main/analyze.js\"\nclick node_ruler_worker \"https://github.com/ronak-create/fablecut/blob/main/ruler-worker.js\"\n\nclassDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a\nclassDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554\nclassDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f\nclassDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d\nclassDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337\nclassDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81\nclassDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a\nclass node_browser_ui,node_timeline_model,node_ruler_worker toneBlue\nclass node_project_store,node_media_store,node_asset_library,node_url_importer toneAmber\nclass node_rest_api,node_mcp_server,node_sse_hub toneMint\nclass node_compositor,node_audio_engine,node_audio_meter,node_export_engine,node_encoding_profiles toneRose\nclass node_reference_analyzer,node_human,node_ai_agent,node_ffmpeg toneIndigo\n```\n\n## Authoring animated SVG overlays\n\nSVGs animate with plain CSS `@keyframes`. One convention: never hardcode\n`animation-delay` — set `--d: 0.4s` instead, and the compositor drives time by\npausing all animations and rebasing their delays. Full rules + a skeleton in\n[CLAUDE.md](CLAUDE.md#authoring-animated-svgs-the-svg-clip-kind); working\nexamples in [`library/svg/`](library/svg/).\n\n## Notes\n\n- The repo ships with **20 Google Fonts** (`library/fonts/`, OFL — see\n  `LICENSES.md` there) and a set of self-authored SVG overlays and animated\n  elements (`library/elements/`, `library/svg/`, MIT like the rest of the repo).\n- `library/sfx/` is yours to fill (gitignored): sound-effect sites typically\n  don't allow redistributing their files in a public repo, so FableCut doesn't —\n  `library/sfx/README.md` lists good free sources.\n- Export runs in the browser because the compositor *is* the browser; agents\n  ask you to click Export (or render directly with ffmpeg from `media/`).\n\n## Sponsors\n\n<a href=\"https://fluxionai.space/register?source=github&amp;campaign=github-sidrune-fablecut&amp;promo=SDRFABLECUT\" target=\"_blank\" rel=\"noopener noreferrer sponsored\">\n  <img src=\"docs/sponsors/sidrune-ai-banner.png\" alt=\"Sidrune AI — one API for GPT, Claude and other leading AI models\" width=\"640\">\n</a>\n\n**[Sidrune AI](https://fluxionai.space/register?source=github&campaign=github-sidrune-fablecut&promo=SDRFABLECUT)** — One API for GPT, Claude, and other leading AI models. Sign up and get $3 in API credit.\n\n## Community\n\nQuestions, ideas, showing off an edit, or want to help shape what's next? Join\nthe **[FableCut Discord](https://discord.gg/EFMQH7d6Tv)**. Bugs and feature\nrequests are still best filed as [GitHub issues](https://github.com/ronak-create/FableCut/issues).\n\n## License\n\n[MIT](LICENSE)\n"}