A free, open-source, Final Cut Pro-style non-linear video editor for Windows.
Magnetic timeline Β· WebCodecs/WebGL2 playback Β· edit-by-transcript Β· auto silence removal Β· keyframe animation Β· smart-render export. Built for long-form creator workflows β multi-hour recordings play with a flat memory footprint and export at disk speed.
Portfolio project. The design is an homage to Apple's Final Cut Pro β the magnetic timeline, three-panel layout, JKL transport, and edit grammar are modeled on it as the design reference. Not affiliated with Apple; no Apple trademarks are used and "Magnetic" is an original product name.
New to Magnetic? Start with the User Guide β a five-minute first edit, the magnetic-timeline workflow, edit-by-transcript, and troubleshooting.
- Library model β Libraries β Events β Projects; import copies media into the
.mglibbundle (hardlinks instead of copies when source and library share a volume) - Filmstrip browser β hover-skim filmstrips, favorite/reject ratings, text search, background thumbnail/waveform generation
- Missing-media relink β assets whose file vanished get an alert badge; relink accepts a replacement whose duration matches Β±1 frame
- Magnetic timeline β spine + connected clips, lanes, gap clips, snapping, zoom, skimming; clips never overlap, edits ripple; minimap strip with drag-to-navigate when the sequence is wider than one screen, and the view pages along with the playhead during playback
- Edit grammar β append
E, insertW, connectQ, overwriteD, ripple delete, lift; selectA/ bladeB/ trimTtools; trim ripples, edit points roll, clip bodies slip; drag-rearrange with magnetic collision; full undo/redo - Viewer β JKL transport (tap again for faster), frame-accurate stepping (
β/β, Β±10 with Shift), in/out marks with play-the-marked-range (/), source/sequence timecode you can click and type to seek, loop playback (Ctrl+L), fullscreen review (Shift+F), live audio meter, transport buttons in both source and sequence modes, and Space plays the browser selection when nothing else is up - Review grid β watch up to 9 selected clips side by side (browser "Watch N" button); click a cell for its audio, double-click to open it in the viewer
- Resizable layout β drag the panel splitters (double-click one to reset it); Reset Layout button restores the defaults
- Clipboard β copy/paste/duplicate clips (
Ctrl+C/V/D), paste-connect (Ctrl+Shift+V), paste attributes incl. keyframes (Ctrl+Alt+V); one undo step per paste - Keyframe animation β animate transform, opacity, and color params from the Inspector (linear/smooth easing); diamonds on timeline clips; WYSIWYG in export
- Transitions β cross dissolve, wipe left/right, fade-to-black
- Titles β free text + 3 presets, rendered as live canvas layers
- Color board β exposure / contrast / saturation / temperature per clip
- Sequence playback β WebCodecs decode β WebGL2 compositor; per-clip transforms (position/scale/rotation/opacity); AudioContext-clocked A/V sync
- Multi-GB clips β streaming demux fetches samples on demand with bounded memory; a 10.85 GB, 4.2-hour clip plays video + audio with a flat ~87 MB renderer heap
- Windowed audio β long clips stream 10-second audio windows double-buffered ahead of the clock instead of decoding whole files
- Audio β mixing, per-clip volume/pan, fade in/out
- Detach audio & split edits β pull audio onto its own lane and trim its edges independently for J-cuts and L-cuts
- Loop to fill β loop a connected music bed to the end of the spine in one action; seam ticks on the timeline, whole-bed fade envelope, one undo step
- Edit-by-transcript β local whisper.cpp transcription, word-click seek, select-text-and-delete-to-cut, filler-word removal, transcript search
- Auto silence removal β background audio analysis, tunable dead-air detection with timeline preview, one-click jump-cuts, one-step undo
- Captions β burned-in captions derived live from the transcript (pop-in / karaoke / block presets); SRT/VTT sidecar export
- Export β H.264/AAC MP4 at 1080p/720p/source via bundled ffmpeg, with progress and cancel; WYSIWYG (exported pixels match the live compositor)
- Smart-render export β when the video track is a single, possibly trimmed, visually untouched asset, export stream-copies the H.264 bitstream and renders only the mixed audio: a 6-hour VOD exports at roughly disk speed, bit-identical video
- Keyboard-shortcut overlay β
Shift+?lists every live binding - NSIS installer β
npm run package, binaries bundled
Explicitly out of scope: multicam, color wheels/curves/scopes, proxy workflow (preview proxies for non-decodable codecs only), compound clips, 360Β°/HDR, plugins, Motion templates, ProRes encode, object tracking, collaboration.
- Windows 10/11 x64
- Node.js 24+, npm 10+
# 1. Install dependencies
npm install
# 2. Fetch native binaries (ffmpeg, ffprobe, whisper.cpp, base.en model)
# into resources/bin/ β pinned URLs, sha256-verified, idempotent
npm run fetch-binaries
# 3. Generate test media into fixtures/ (uses the fetched ffmpeg + Windows SAPI TTS)
npm run fixturesnpm run dev # start electron-vite dev server + app (HMR)npm run typecheck # tsc across main, preload, renderer, shared, e2e
npm run lint # eslint
npm test # vitest unit tests
npm run build # electron-vite production build -> out/
npm run test:e2e # Playwright Electron E2E (requires `npm run build` first)
npm run package # NSIS installer + win-unpacked -> dist/ (bundles resources/bin)The installer bundles ffmpeg/ffprobe/whisper and the base.en model (~250 MB of binaries), so the packaged app has no first-run download. e2e/packaged.spec.ts boots dist/win-unpacked/Magnetic.exe and verifies the bundled binaries resolve; it is skipped until npm run package has produced that output.
| Script | What it does |
|---|---|
dev |
Run the app in development with HMR |
build |
Production build to out/ |
typecheck |
Typecheck node (main/preload/shared/e2e) and web (renderer) projects |
lint |
ESLint over the repo |
test |
Vitest unit tests (src/**/*.test.ts) |
test:e2e |
Playwright _electron E2E suite against the built app |
package |
electron-builder NSIS installer into dist/ |
fetch-binaries |
Download + sha256-verify ffmpeg/ffprobe/whisper/model into resources/bin/ |
fixtures |
Generate deterministic test media into fixtures/ |
format |
Prettier write |
Generated from the live shortcut registry (scripts/dump-shortcuts.mjs); Shift+? in the app shows the same list. Shortcuts are suppressed while typing in text fields. J/K/L and Space are contextual β they drive the source viewer when it has a clip open, otherwise the timeline.
| Shortcut | Action |
|---|---|
Space |
Play / pause (viewer or sequence) |
J |
Viewer: play reverse (again: faster) Β· Timeline: pause |
K |
Pause |
L |
Play forward (again: faster) |
β / β |
Step back / forward one frame |
Shift+β / Shift+β |
Step back / forward 10 frames |
Home / End |
Go to the start / end (viewer or timeline) |
β / β |
Jump to the previous / next edit point |
I / O / X |
Mark in / mark out / clear in-out points |
/ |
Play the marked range (in to out) |
Ctrl+L |
Loop playback on / off |
Shift+F |
Fullscreen viewer |
E |
Append browser selection to the spine |
W |
Insert browser selection at the playhead |
Q |
Connect browser selection at the playhead |
D |
Overwrite at the playhead with browser selection |
Delete |
Ripple delete the selected clips |
Shift+Delete |
Lift the selected clips, leaving a gap |
A |
Select tool |
B |
Blade tool |
T |
Trim tool (edges ripple, edit points roll, body slips) |
Ctrl+B |
Blade at the playhead (selected clips, or the clip under it) |
Ctrl+T |
Add a 1 s cross dissolve at the edit point nearest the playhead |
Ctrl+Z / Ctrl+Shift+Z |
Undo / redo |
N |
Toggle snapping |
S |
Toggle skimming |
= / - |
Zoom the timeline in / out |
Shift+Z |
Zoom the timeline to fit the sequence |
Ctrl+4 |
Show or hide the Inspector |
Ctrl+E |
Export the sequence as a movie |
Ctrl+Shift+T |
Show or hide the timeline transcript |
Ctrl+Shift+D |
Show or hide binary diagnostics |
Shift+? |
Show the keyboard shortcut overlay |
Escape |
Return focus to browser Β· close the clip grid Β· exit fullscreen |
flowchart TB
subgraph rendererBox["Renderer (src/renderer)"]
ui["React UI<br/>browser Β· viewer Β· timeline Β· inspector"]
store["zustand timeline store<br/>undo / redo"]
engine["Playback engine<br/>streaming WebCodecs demux + decode β WebGL2 compositor<br/>AudioContext-clocked sync"]
end
subgraph sharedBox["Shared (src/shared)"]
kernel["Magnetic timeline kernel<br/>pure TS Β· immutable Sequence<br/>every op returns its inverse"]
end
subgraph mainBox["Main process (src/main)"]
ipc["IPC<br/>zod-validated handlers"]
lib["LibraryStore<br/>.mglib JSON + media"]
jobs["JobQueue<br/>filmstrip Β· waveform Β· proxy<br/>transcribe Β· envelope"]
exp["Export sink<br/>rawvideo pipe β ffmpeg<br/>or smart-render stream-copy"]
end
ui --> store
store --> kernel
store --> engine
ui -->|window.api preload bridge| ipc
ipc --> lib
ipc --> jobs
ipc --> exp
src/shared/timeline/β the magnetic-timeline kernel: pure functions over an immutableSequence; clip positions are derived by summation so overlaps are unrepresentable; every op returns its inverse for undosrc/main/β Electron main process: window, menu, library persistence, background jobs, export (including the smart-render planner); every IPC handler zod-validates its payloadsrc/preload/β contextBridge bridge exposing the typedwindow.apisrc/renderer/β React UI (dark FCP-style 3-panel shell), zustand state, and the playback engine (streaming WebCodecs demux + decode, WebGL2 compositing, AudioContext-clocked sync)scripts/β binary fetcher, fixture generator, shortcut-table dumpe2e/β Playwright Electron tests;resources/bin/andfixtures/are gitignored artifacts
The visual language is documented in DESIGN.md (tokens, type scale, spacing, motion β Apple dark-mode chrome where the footage is the hero) and PRODUCT.md (register, users, brand personality).
Renderer security: contextIsolation: true, nodeIntegration: false, sandbox: true, CSP set in index.html, no remote URLs; library files are served over a custom mfile:// protocol scoped to the library, except video/audio playback, which goes through a token-guarded loopback HTTP server (src/main/media-server.ts) because Chromium's media pipeline cannot seek large files through Electron custom-protocol responses. Ctrl+Shift+D toggles a diagnostics overlay that spawn-verifies the bundled binaries.
- The "Explicitly out of scope" list above (multicam, scopes, compound clips, β¦) is deferred by design
- Reverse playback:
Jin the timeline pauses; true reverse playback is viewer-only - 4K media plays at degraded fidelity (frame drops accepted; no proxy editing pipeline)
- Codecs WebCodecs cannot decode natively (e.g. ProRes) play through an auto-generated H.264 preview proxy; export always re-renders from source
- Export encodes H.264/AAC MP4 only; no ProRes/HEVC encode
- Auto-transcribe skips assets over 30 minutes (manual transcribe still works at any length)
- Windows-only: packaging, binary fetching, and E2E are wired for win32
MIT β free for everyone, for any use.
The fetch-binaries script downloads third-party tools that are not part of this repository and carry their own licenses: FFmpeg/FFprobe (GPL builds from gyan.dev), whisper.cpp (MIT), and the Whisper base.en model (MIT).






