I Built a Local Video Processing Workstation with AI — Here's the Complete Journey A developer built ClipForge, a cross-platform desktop video processing app using Electron, React, FFmpeg, and Claude Code. The app handles 20+ video/audio operations locally with single, stack, and batch modes. The developer solved challenges like FFmpeg integration, real-time preview via canvas, and Electron packaging across Windows, macOS, and Linux. From idea to release in 3 weeks, using Claude Code to build ClipForge — a cross-platform desktop app powered by Electron and FFmpeg. Most video processing tools force you to: I wanted a fully local, feature-rich, good-looking video processing tool. So I built ClipForge. ClipForge is a desktop app that handles 20+ video/audio operations locally: Three modes: Single operation, Stack chain multiple ops , Batch processing. Built with Electron, React, FFmpeg, and Zustand. Ships for Windows, macOS, and Linux. | Layer | Tech | Why | |---|---|---| | Desktop | Electron 42 | Cross-platform, Node.js for FFmpeg | | UI | React 18 + TypeScript | Component ecosystem | | Build | Vite 5 + Electron Forge | Fast HMR, clean packaging | | State | Zustand | Simple, no boilerplate | | Styling | Tailwind CSS | Rapid UI development | | Video | FFmpeg bundled | Industry-standard processing | | AI | Claude Code | Pair programming assistant | npm create electron-app clipforge Electron Forge generated the boilerplate: main process, preload script, renderer with Vite. Built a 4-panel layout: Dark theme with Tailwind CSS. This is the core challenge — wrapping FFmpeg's CLI into visual operations. Architecture: Renderer React │ invoke 'process:start', request ▼ Preload IPC bridge │ ▼ Main Process Node.js │ composeArgs request → ffmpeg args array ▼ FFmpeg child process.spawn │ progress parsing from stderr ▼ Events back to renderer Example: Watermark Removal Instead of FFmpeg's delogo filter which has boundary restrictions — x≥1, y≥1, no edge support , I used a crop + blur + overlay approach: js case 'delogo': { const x = Math.max 0, Math.round Number p.x || 0 ; const y = Math.max 0, Math.round Number p.y || 0 ; const w = Math.max 10, Math.round Number p.w || 10 ; const h = Math.max 10, Math.round Number p.h || 10 ; args.push '-filter complex', 0:v split a b ; + b crop=${w}:${h}:${x}:${y},gblur=sigma=30,format=rgba,colorchannelmixer=aa=0.7 b2 ; + a b2 overlay=${x}:${y} out ; args.push '-map', ' out ', '-map', '0:a?' ; args.push ...videoCodec outExt ; break; } The filter graph: crop — extract the watermark region gblur — Gaussian blur more natural than boxblur colorchannelmixer=aa=0.7 — semi-transparent blend for smooth integrationUsers need to see changes immediately, not after processing completes. Solution: Canvas-based preview simulation. Instead of running FFmpeg, read frames from the