Skip to content

Sportinger/MasterSelects

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2,413 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MasterSelects

Local-first Media Editor for Video, Audio, Vector Animation & 3D


⚡ ~2 MB compressed

compressed editor shell

GPU-first media editing with 33 effects, 37 blend modes, 23 audio FX, stem separation, native WebGPU 3D, and 19 direct runtime dependencies.
Built from scratch in 4.1k+ lines of WGSL and 330k+ lines of TypeScript/TSX app code.
Import .lottie, .riv, Lottie JSON, OBJ, glTF, GLB, PLY, SPLAT, KSPLAT, SPZ, SOG, LCC assets and play PLY / GLB sequences directly on the timeline. Built with one coding-agent subscription from January to now.

Version License FOSSA Status

WebGPU React 19 TypeScript Vite Rust

Discord Reddit


masterselects_github.mp4


Supported Formats

Decoding depends on what the browser supports — the container is just the wrapper, the codec inside is what matters.

Import (Decode)
Video filesMP4, WebM, MOV, AVI, MKV, WMV, M4V, FLV
Video codecsH.264 (AVC), H.265 (HEVC)¹, VP8, VP9, AV1
Audio filesWAV, MP3, OGG, FLAC, AAC, M4A, WMA, AIFF, OPUS
Audio stemsOn-device Demucs/HTDemucs separation creates Vocals, Drums, Bass, and Other stems as project-local WAV media when the project write path is available
ImagePNG, JPG/JPEG, WebP, GIF, BMP, SVG
Vector animation.lottie packages, .riv files, and Lottie JSON files (content-sniffed)
3D ModelsOBJ, glTF, GLB - rendered through the native WebGPU shared-scene path
3D sequencesPLY and GLB frame sequences played as timeline media
Gaussian SplatsPLY, compressed PLY, SPLAT, KSPLAT, SPZ, SOG, LCC, SOG-style ZIP payloads
DownloadYouTube, TikTok, Instagram, Twitter/X, Vimeo + all yt-dlp sites via Native Helper
Export (Encode)
Video containersMP4, WebM via WebCodecs / HTMLVideo; MOV, MKV, AVI, MXF via FFmpeg WASM
FFmpeg codecsProRes, DNxHR, FFV1, UTVideo, MJPEG
Video codecsH.264, H.265¹, VP9, AV1 — GPU-accelerated via WebCodecs
Image exportPNG, JPG/JPEG, WebP, BMP (current playhead frame)
Audio-only exportWAV, plus AAC or OGG/Opus depending on browser codec support
InterchangeFCPXML (Final Cut Pro / DaVinci Resolve)

¹ H.265 decode/encode depends on OS & hardware — full support on Windows, partial on macOS/Linux.

MOV files work because they share the same ISO BMFF container as MP4 — any MOV with H.264/H.265 inside plays fine. MKV works if it contains browser-decodable codecs (H.264, VP9, etc.). Native Helper decode is an opt-in companion path for browser gaps when the helper is connected and the source path is resolvable; unsupported codecs do not automatically switch to it.


What Makes This Different

Most browser-based video editors share a pattern: Canvas 2D compositing, heavyweight dependency trees, and CPU-bound rendering that falls apart at scale. This project takes a fundamentally different approach.

GPU-first architecture. Preview, scrubbing, and export all run through the same WebGPU ping-pong compositor. Video textures are imported as texture_external (zero-copy, no CPU roundtrip). 37 blend modes, 3D rotation, and inline color effects all execute in a single WGSL composite shader per layer. The 3D layer system now renders through the native WebGPU shared-scene path for 3D planes, primitive meshes, 3D text, OBJ/glTF/GLB models, camera clips, and gaussian splats - no GSAP, no Canvas 2D fallback in the hot path.

Current startup footprint. A fresh production build currently loads an editor shell of about 2 MB compressed on the main editor start path. The largest contributors are the native 3D / gaussian-splat render path, browser-side media parsing/runtime code, and AI/media helper modules. Reducing the initial bundle again is an active optimization target.

Zero-copy export pipeline. Frames are captured as new VideoFrame(offscreenCanvas) directly from the GPU canvas. No readPixels(), no getImageData(), no staging buffers in the default path. The GPU renders, WebCodecs encodes. That's it.

3-tier scrubbing cache. 300 GPU textures in VRAM for instant scrub (Tier 1), per-video last-frame cache for seek transitions (Tier 2), and a 900-frame RAM Preview with CPU/GPU promotion (Tier 3). When the cache is warm, scrubbing doesn't decode at all.

Audio workstation in the timeline. Audio Focus turns the timeline into a detailed waveform and spectrogram editor with non-destructive region edits, gain fades, silence removal, repair operations, spectral selections, image-in-spectrum layers, recording, and bake/unbake. The docked Audio Mixer adds track/master strips, Peak/RMS meters, stereo phase correlation, track sends rendered into the master return mix, FX stacks, limiter controls, and export preflight. Stem separation runs a browser ONNX Demucs/HTDemucs path and publishes Vocals, Drums, Bass, and Other stems as normal WAV media when the project media write succeeds, with artifact-backed fallback state when it cannot.

19 direct runtime dependencies. React/React DOM, Zustand, MediaBunny, mp4box, PlayCanvas / splat-transform helpers, dotLottie, Rive WASM, HuggingFace Transformers, ONNX Runtime, SoundTouch, FFmpeg WASM packages, fflate, gifenc, Tabler icons, and WebGPU types. Everything else is custom-built from scratch: the WebGPU compositor, all 33 GPU effects, the 23-effect audio registry, the keyframe animation system, the export engine, the audio mixer, the text renderer, the mask engine, the video scope renderers, the dock/panel system, the timeline UI, and the native shared 3D scene path. Zero runtime abstraction layers between your timeline and the GPU.

Nested composition rendering. Compositions within compositions, each with their own resolution. The normal 2D/nested compositor path renders them to pooled GPU textures with frame-level caching and composites them in the parent's ping-pong pass. Native 3D and gaussian-splat auxiliary paths can submit their own GPU work when those layer types are active.

On-device AI and analysis. SAM2 (Segment Anything Model 2) runs entirely in-browser via ONNX Runtime. Click to select objects in the preview, propagate masks across frames. Stem separation writes project-local WAV media, while local transcription, waveform pyramids, spectrogram tiles, loudness envelopes, beat/onset maps, and frequency/phase summaries are generated as project artifacts instead of being baked into timeline clips. Large neural models are loaded on demand.


Why I Built This

No Adobe subscription, no patience for cracks, and every free online editor felt like garbage. I wanted something that actually works: fast in the browser, GPU-first, built for real editing instead of templates, and open enough that AI can steer the timeline instead of just suggesting ideas.

The vision: an editor where AI can directly operate the tool. The built-in chat connects to OpenAI/Cloud or a local Lemonade Server and exposes 86 exported model tools across timeline, media, editing, playback, stats, and node-workspace actions. External agents can steer the running editor over the local/native HTTP bridge, and in development the Vite bridge still exists too. Live outputs still matter too - I've been doing video art for 16 years, so multi-output routing was never optional.

Built with Claude as my pair-programmer. Every feature gets debugged, refactored, and beaten into shape until it does what I need. ~330k lines of TypeScript/TSX app code, ~4.1k lines of WGSL shader files, and a Rust native helper for the stuff browsers still can't do cleanly.


AI Control

MasterSelects is being built around the idea that AI should be able to do the edit, not just talk about it.

  • Built-in editor chat: OpenAI/Cloud or local Lemonade chat, compact provider/model menus, project-saved system prompts, and direct access to 86 exported timeline/media/editing and diagnostics tools
  • Local Lemonade provider: OpenAI-compatible Lemonade Server support for local chat models such as gemma4-it-e2b-FLM; model discovery comes from /models, and the endpoint is restricted to loopback hosts
  • External agent bridge: Claude Code or any other local agent can drive the running editor via the Native Helper HTTP bridge, and in development the same tool surface is also available through the Vite bridge and window.aiTools
  • AI video, image, and audio generation: FlashBoard routes through Kie.ai, hosted cloud, ElevenLabs, Suno, EvoLink, and legacy PiAPI-compatible catalogs depending on account and key setup
  • Experimental multicam AI: Claude/Anthropic generates edit decision lists for the multicam workflow
  • On-device AI: SAM2 segmentation in-browser via ONNX Runtime, MatAnyone2 via Native Helper, plus local Whisper transcription via Transformers.js

Example Native Helper bridge call:

curl -X POST http://127.0.0.1:9877/api/ai-tools \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <startup-token>" \
  -d '{"tool":"_list","args":{}}'

This requires the Native Helper to be running, a MasterSelects editor tab to be connected, and the helper startup token. The Vite /api/ai-tools bridge still exists in development, but it is now gated by a per-session token as well.


What It Does

Feature Description
Multi-track Timeline Cut, copy, paste, multi-select, JKL shuttle, nested compositions
33 GPU Effects Color correction, blur, distort, stylize, keying - all real-time
Video Scopes GPU-accelerated Histogram, Vectorscope, Waveform monitor
Keyframe Animation Bezier curves, copy/paste, tick marks, 5 easing modes
Vector Masks Pen tool, edge dragging, feathering, multiple masks per clip
SAM2 Segmentation AI object selection in preview - click to mask, propagate across frames
Transitions Crossfade transitions with GPU-accelerated rendering (experimental)
AI Integration Built-in OpenAI/Cloud or local Lemonade chat, 86 exported tool-callable edit/debug actions, and local/native bridges for external agents
FlashBoard Media Panel generation tray for text-to-video, image-to-video, images, speech, and music
Multicam AI Sync cameras, transcribe footage, and generate Claude-powered multicam EDLs (experimental)
Export Pipeline WebCodecs Fast/Precise, FFmpeg intermediates, image/audio-only export, FCPXML, and project-persistent presets
Audio Workstation Audio Focus, detailed waveforms and spectrograms, 23 Audio FX, track sends into the master return mix, stem separation, recording, and export preflight
Download Panel YouTube, TikTok, Instagram, Twitter/X, Vimeo, and other yt-dlp-supported sites via Native Helper
Vector Animation .lottie, .riv, and Lottie JSON clips with bounce playback, render resolution overrides, state-machine keyframes, Rive data binding, and preview/export
Text & Solids 50 Google Fonts, stroke, shadow, and solid color clips
Proxy System GPU-accelerated proxies with resume and cache indicator
Output Manager Multi-window outputs, source routing, corner pin warping, slice masks
Signal IR Universal import layer for files that become binary, table, model, splat, or text-summary signals
Slot Grid Resolume-style 12x4 grid with multi-layer live playback and slot-clip trims
Preview & Playback RAM Preview, transform handles, multiple render targets
Project Storage Local folders, raw media auto-copy, continuous save by default, interval mode, backups
Interactive Tutorial Guided onboarding with animated Clippy mascot
See Keyframe Editor
Bezier Curve Editor

Quick Start

npm install
npm run dev     # http://localhost:5173

Requirements: Chrome 113+ with WebGPU support is the main target. Dedicated GPU recommended.

Firefox: project storage requires the Native Helper backend because Firefox does not support the File System Access API flow used by Chrome.

Linux: Enable Vulkan for smooth 60fps: chrome://flags/#enable-vulkan


Native Helper

Cross-platform Rust companion app for the parts browsers still can't do well. Required for Firefox project storage and for yt-dlp-based downloads.

cd tools/native-helper
cargo run --release    # WebSocket :9876, HTTP :9877
Capability Details
Storage Native project persistence backend for Firefox
AI Control Local HTTP bridge for external agents to steer the running editor
Download yt-dlp integration for YouTube, TikTok, Instagram, Twitter/X, Vimeo, and other supported sites

Platforms: Windows, Linux, macOS. Building the Native Helper requires Rust. The Windows MSI bundles yt-dlp.exe; source builds and non-Windows archive installs use yt-dlp from the helper folder or PATH. See Native Helper docs for platform-specific setup.


Security

MasterSelects is a local-first editor. Editing, rendering, caching, and most analysis stay in the browser unless you explicitly invoke an external provider or the Native Helper.

  • API keys: stored in IndexedDB with per-browser Web Crypto encryption
  • Native Helper: binds to 127.0.0.1 only, requires a random startup Bearer token for HTTP and WebSocket
  • Dev bridge: Vite /api/ai-tools and local file routes require a per-session token and reject non-loopback origins
  • Lemonade local chat: endpoint is restricted to localhost, 127.0.0.1, or ::1; Lemonade can suggest tool calls but execution still goes through the normal chat approval and dispatcher path
  • Local file access: restricted to explicit allowed roots (project root, temp, Desktop, Documents, Downloads, Videos)
  • AI tool policy: external bridge calls run through caller restrictions and approval gates
  • Secret handling: logs redact common secret/token patterns; .keys.enc export disabled
  • CI checks: secret scanning, JS and Rust security audits, dedicated tests for bridge auth and file access policy

Known boundary: this is not perfect sandboxing. Same-user local processes, malicious browser extensions, and compromised same-origin code can still be dangerous. The goal is clear, test-covered local trust boundaries.

See Security.md for the full trust model and limitations.


Known Issues

This is alpha software. Features get added fast, things break.

  • FFmpeg WASM export is still work in progress
  • Multicam AI is experimental
  • Transitions are experimental
  • Stem separation downloads a large ONNX model on first use and depends on WebGPU/WASM runtime performance
  • Firefox project storage requires the Native Helper backend
  • Video downloads require Native Helper; the Windows MSI bundles yt-dlp, while source/non-Windows installs need yt-dlp beside the helper or on PATH
  • Audio waveforms may not display for some video formats
  • Very long videos (>2 hours) may cause performance issues

If something breaks, refresh. If it's still broken, open an issue.


Tech Stack

  • Frontend: React 19, TypeScript, Zustand, Vite 7.3
  • Rendering: WebGPU + 4.1k+ lines of WGSL shader files
  • Video: WebCodecs, MediaBunny, mp4box, HTMLVideo fallback, and experimental FFmpeg WASM export path
  • Audio: Web Audio API, AudioWorklet recording, 23 registry-backed Audio FX, flexible EQ, track sends rendered into the master mix, stem separation through ONNX Runtime, artifact-backed waveform/spectrogram/loudness/beat/frequency analysis, and export preflight
  • AI: Built-in OpenAI/Cloud or local Lemonade editor chat with 86 exported model tools, Native Helper HTTP bridge for Claude Code / external agents, Claude/Anthropic for experimental multicam EDLs, SAM2 via ONNX Runtime, MatAnyone2 via Native Helper, local Whisper via Hugging Face Transformers, and Kie.ai / hosted cloud / ElevenLabs / Suno / EvoLink / PiAPI-compatible generation flows
  • Native: Rust helper for Firefox storage backend, native decode/encode, and bundled/system yt-dlp downloads
  • Storage: File System Access API on Chrome, Native Helper backend on Firefox, IndexedDB, local project folders with raw media

Shortcuts

Key Action
Space Play/Pause
J / K / L Reverse / Pause / Forward (shuttle)
C Cut at playhead
I / O Set in/out points
Ctrl+C/V Copy/Paste clips or keyframes
Shift+Click Multi-select clips
Tab Toggle edit mode
Ctrl+Z/Y Undo/Redo
Ctrl+S Save project

All 89 shortcuts


Documentation

Detailed docs for each feature: docs/Features/


Development

npm run dev              # Dev server with HMR
npm run dev:changelog    # Dev server with changelog dialog
npm run build            # Production build (tsc + vite)
npm run build:deploy     # Production build (vite only, skip tsc)
npm run lint             # ESLint
npm run preview          # Preview production build
npm run test             # Run tests (vitest)
npm run test:security    # Security-focused test suite
npm run test:watch       # Run tests in watch mode
npm run test:ui          # Run tests with UI
npm run test:coverage    # Run tests with coverage
npm run test:unit        # Run unit tests only
Project Structure
src/
├── components/          # React UI
│   ├── timeline/        # Timeline editor (hooks/, components/, utils/)
│   ├── panels/          # Properties, Media, AI, Download, Export, Scopes, Transitions
│   ├── preview/         # Canvas + overlays + transform handles + SAM2 overlay
│   ├── outputManager/   # Multi-window output with slices
│   ├── export/          # Export dialog, codec selector, FFmpeg section
│   ├── dock/            # Panel/tab system
│   ├── common/          # Dialogs, tutorial, settings, shared components
│   └── mobile/          # Mobile-responsive layout
├── stores/              # Zustand state management
│   ├── timeline/        # Slices: track, clip, keyframe, mask, playback, selection, transitions, ...
│   └── mediaStore/      # Slices: import, folder, proxy, composition, slot, selection
├── engine/              # WebGPU rendering pipeline
│   ├── core/            # WebGPUContext, RenderTargetManager
│   ├── render/          # Compositor, RenderLoop, LayerCollector, NestedCompRenderer
│   ├── export/          # FrameExporter, VideoEncoder, ClipPreparation
│   ├── audio/           # AudioMixer, AudioEncoder, TimeStretch
│   ├── ffmpeg/          # FFmpegBridge, codecs
│   ├── pipeline/        # CompositorPipeline, EffectsPipeline, OutputPipeline, SlicePipeline
│   ├── scene/           # Shared-scene 3D runtime
│   ├── native3d/        # Native WebGPU 3D renderer helpers
│   ├── gaussian/        # Gaussian splat loading/render support
│   ├── texture/         # TextureManager, ScrubbingCache, MaskTextureManager
│   ├── managers/        # CacheManager, ExportCanvasManager, OutputWindowManager
│   ├── analysis/        # Histogram, Vectorscope, Waveform scopes
│   ├── video/           # VideoFrameManager
│   ├── stats/           # PerformanceStats
│   └── structuralSharing/ # SnapshotManager for undo/redo
├── effects/             # 33 GPU effects (color/, blur/, distort/, stylize/, keying/)
├── transitions/         # Transition definitions (crossfade)
├── artifacts/           # Content-addressed artifact storage
├── importers/           # Universal media importers
├── signals/             # Signal IR contracts and adapters
├── runtime/             # Runtime renderer adapters
├── extensions/          # Extension/provider integration points
├── marketing/           # Public/landing surfaces
├── routing/             # Route-level app shells
├── styles/              # Shared styles
├── shims/               # Browser/runtime shims
├── services/            # Audio, AI, Project, NativeHelper, Logger, LayerBuilder, MediaRuntime
│   ├── aiTools/         # 86 exported AI tool definitions + handlers
│   ├── sam2/            # SAM2 model manager + service
│   ├── project/         # Project persistence, save/load
│   ├── nativeHelper/    # Native decoder + WebSocket client
│   ├── layerBuilder/    # Layer building + video sync
│   ├── mediaRuntime/    # Media runtime bindings + playback
│   ├── vectorAnimation/ # Lottie/Rive metadata + runtime canvas playback
│   └── export/          # FCPXML export
├── shaders/             # WGSL (composite, effects, output, optical flow, slice)
├── hooks/               # React hooks (useEngine, useGlobalHistory, useMIDI, useTheme)
├── utils/               # Keyframe interpolation, mask renderer, file loader
├── types/               # TypeScript type definitions
├── workers/             # Transcription worker
└── test/                # In-browser test components
tools/
├── native-helper/       # Rust binary (FFmpeg + yt-dlp bridge)
│   └── src/             # WebSocket server, decode/encode sessions
├── ffmpeg-build/        # FFmpeg build scripts
├── ffmpeg-wasm-build/   # FFmpeg WASM build configuration
├── qwen3vl-server/      # Qwen3 VL server for scene description
└── visitor-tray/        # Windows tray notifier for hosted visit events

License Scan (FOSSA)

FOSSA Status

The linked FOSSA report tracks direct and transitive dependencies across npm, Cargo, and pip. The current npm runtime surface in package.json has 19 direct runtime dependencies.

Category Count Status
License Issues 35 flagged All reviewed — no violations
Vulnerabilities 6 All in dev-dependencies, fixable via npm audit fix
Outdated Deps 4 Non-critical

Flagged licenses (all compliant):

Package License Why it's OK
soundtouch-ts LGPL-2.1 Used as unmodified npm dependency
sharp / libvips (15 platform binaries) LGPL-3.0 Used as unmodified prebuilt binary
mediabunny MPL-2.0 Used as unmodified npm dependency
torch, pillow BSD/PIL Python tooling only (tools/qwen3vl-server), not shipped
Cargo crates (r-efi, ring, rustix, wit-bindgen, ...) Apache-2.0 / MIT Standard Rust ecosystem, no copyleft issues

No source code of any dependency has been modified. No GPL/AGPL dependencies. All copyleft packages (LGPL, MPL) are used strictly as libraries via their published APIs.

View full FOSSA report · Attribution report (HTML)


MIT License · Built by a video artist who got tired of waiting for Adobe to load