Clip sections from HLS (.m3u8) streams and export them as MP4 — entirely in your browser. No uploads, no server, no installs.
Try it → chrissabato.github.io/livecut
- Paste an
.m3u8stream URL and click Load (or click the sample URL to prefill it) - The video starts playing automatically, muted
- Use Mark In / Mark Out while the video plays (or press I / O) — the video pauses at the marked point
- Fine-tune the marks with the nudge buttons (
−1s−0.1s+0.1s+1s) — the video seeks and pauses at each adjusted position - Click Preview to play through the selected range and confirm it looks right
- Give the clip a name and click Add
- Repeat for as many clips as you need
- Hit Export on any saved clip to download it as MP4
Exports are downloaded directly to your machine. Nothing leaves your browser.
- Quick clip buttons —
-3s,-5s,-10sset the in/out points instantly based on the current playhead - Live button — jumps to the live edge of the stream (5 s behind) for easy live clipping
- Clip preview — preview pending marks or any saved clip before exporting
- Multi-clip workflow — mark and queue multiple named clips before exporting
- Inline rename — click any clip name in the list to edit it
- Per-clip export — each clip has its own export button and progress bar
- Frame-accurate nudging — adjust in/out points in 0.1 s or 1 s steps with instant seek
- 4-minute clip limit — warns before you queue a clip that could exhaust browser memory
- Keyboard shortcuts —
Ito mark in,Oto mark out while playing - No re-encoding — uses stream copy (
-c copy) so exports are fast and lossless - Automatic CORS proxy fallback — tries the stream directly first; only routes through a proxy if needed
- Early error detection — CORS/403 errors are shown immediately on load, not at export time
The stream URL must be publicly accessible with Access-Control-Allow-Origin: * headers. Streams behind authentication or without CORS support will not work directly, but the built-in proxy fallback handles most cases automatically.
LiveCut tries every stream URL directly first. If that fails (CORS or 403), it automatically retries through a proxy. Only the playlist fetch goes through the proxy — video segments are fetched directly from the CDN, so proxy bandwidth usage is minimal.
Local CORS proxy — strips origin/referer headers that some CDNs block:
npx local-cors-proxy --proxyUrl https://your-stream-host.com --port 8010Then paste http://localhost:8010/your-stream.m3u8 into LiveCut.
Browser extension — extensions like "CORS Unblock" inject permissive response headers. Works for origin-based blocks; does not help with authentication-based 403s.
Some streams can't be fixed from a browser at all — the CDN blocks the request based on Origin/Referer and returns 403, or sends no CORS headers on the video segments. The LiveCut desktop app is a thin Electron shell that loads this same site and strips/rewrites those headers at the network layer, so those streams just work.
Download (v1.0.3):
| Platform | |
|---|---|
| macOS — Apple Silicon | LiveCut-1.0.3-arm64.dmg |
| macOS — Intel | LiveCut-1.0.3-x64.dmg |
| Windows — x64 | LiveCut-1.0.3-x64.exe |
| Windows — ARM64 | LiveCut-1.0.3-arm64.exe |
All builds, notes, and older versions: releases page (desktop-v* tags).
- Auto-updating content: the desktop app loads the live site, so UI, export logic, and parser fixes reach it through the normal deploy — no re-download. You only re-download when the shell itself changes.
- Windows SmartScreen: the Windows build is currently unsigned. Windows shows "Windows protected your PC" — click More info → Run anyway. The macOS build is signed and notarized and opens normally.
- Not supported: DRM/Widevine streams, streams that need a login/auth cookie, and fully-offline export (FFmpeg core still downloads on first export).
The shell lives in electron/ and has its own README with dev/build/release details.
- Segment URLs and timing are read directly from HLS.js's already-parsed playlist — no re-fetch of the
.m3u8URL, so time-limited signed URLs don't expire between load and export - Only the segments that overlap the selected clip range are downloaded
- FFmpeg.wasm concatenates the segments and trims to the exact in/out points
- The result is downloaded as an
.mp4file
FFmpeg.wasm requires SharedArrayBuffer, which requires cross-origin isolation (crossOriginIsolated = true). A service worker (coi-serviceworker.js) injects the necessary Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers. On first load the page reloads once to activate — this is expected.
- Clips are processed in memory; the 4-minute limit helps avoid hitting browser memory limits at typical bitrates
- Only one clip exports at a time
- Segment URLs must still be valid at export time (the
.m3u8URL expiry is no longer an issue, but individual segment URLs can also be time-limited on some streams)
npm install
npm run devRequires Node 18+. The dev server sets the required COOP/COEP headers automatically.
For local development with a proxy, create a .env.local file (not committed):
VITE_PROXY_URL=https://your-proxy-url.example.com
No need to build anything — grab the prebuilt static files from the Releases page, unzip, and copy the contents onto any static web host (Apache, Nginx, S3, etc.). A fresh zip is published automatically on every deploy.
This build has no analytics or CORS proxy baked in. If you need a proxy for streams that block CORS, set VITE_PROXY_URL and rebuild from source instead (see above).
Push to main — GitHub Actions builds and deploys to GitHub Pages automatically, and bumps the patch version on each deploy. It also publishes a clean static build (no analytics/proxy) as a zip attached to a new GitHub Release, for anyone who wants to self-host.
Settings → Pages → Source must be set to GitHub Actions (one-time setup).
The following repository variables must be set under Settings → Secrets and variables → Actions → Variables:
| Variable | Description |
|---|---|
PROXY_URL |
CORS proxy URL (e.g. https://proxy.example.com) |
GA_MEASUREMENT_ID |
Google Analytics 4 measurement ID (e.g. G-XXXXXXXXXX) |
These are injected at build time and do not appear in the source code.
Usage is tracked via Google Analytics 4. The following custom events are recorded:
| Event | Parameters |
|---|---|
stream_loaded |
stream_url, via_proxy |
clip_added |
duration_seconds |
clip_exported |
stream_url, duration_seconds, via_proxy |
| Playback | HLS.js |
| Video processing | FFmpeg.wasm 0.12 |
| UI | React 18 + Vite |
| Hosting | GitHub Pages |