Video Splitter
Cut a long video into clips that start where the video changes β not every thirty seconds. Everything happens on your machine.
Why cut on the shot, not on the clock
A thirty-second rule knows nothing about the video it is cutting. It will end a clip in the middle of a movement and open the next one on the tail of it, and the join is visible to anyone watching β the first second of a clip is the second that decides whether they stay.
A shot change is a boundary the footage already contains. Starting there means each clip opens on something new, which is what a person would do by hand. That is the only real difference here, and it is the whole point.
What it does not do
It does not read speech, so it cannot find the moment someone says something quotable β tools built around transcription do that, and they do it well. It does not track faces, so the vertical crop takes the centre of the frame and trusts you to look at the previews.
What it does have is the picture: where the shots are, and which of them are sharp, well-exposed and worth a viewer's attention. For footage without much talking β travel, action, b-roll, anything shot on a gimbal β that is the information that matters.
How it works
The scene detector finds the shot boundaries, the same per-frame scorer that Life2Film uses ranks them, and the clips are grouped so no cut ever lands inside a shot. Encoding uses the browser's own video pipeline, so the output is a normal MP4 with no watermark.
Your file is read and re-encoded by your own browser. No request carries it anywhere β this page has no upload endpoint to send it to.
Questions
How is this different from other video splitters?
Most cut every N seconds, so a clip can start halfway through a sentence and end mid-gesture. This one finds the cuts the video already has β the shot changes β and builds clips out of whole shots. You still choose roughly how long a clip should be; the boundaries land on the nearest real change instead of on a stopwatch.
Is my video uploaded?
No. The browser decodes it, WebAssembly analyses the frames, and the clips are re-encoded locally with WebCodecs β the same hardware path your browser uses to play video. Nothing is sent anywhere, which is also why there is no length limit imposed by a plan, no queue and no watermark.
What are the stars next to each clip?
The engine scores every sampled frame for sharpness, exposure, contrast, colourfulness and detail, and each clip gets the duration-weighted average of the shots inside it. The stars are relative to the best clip in this video, not an absolute scale β they are a suggestion of where to look first, not a verdict on what is interesting.
Will the vertical crop cut people out of frame?
It takes the centre of the frame, which is right most of the time and wrong when the subject is off to one side. There is no face tracking here yet, so check the previews before posting. If a clip is framed wide, it is usually better to crop it by hand.
How long does it take?
Analysis takes a few seconds per minute of video. Encoding is the slow part and depends on your machine β expect roughly real time or better for 1080p on a recent laptop, since it uses the GPU where available. Clips are written one at a time so you can start downloading before the rest finish.
Which files work?
MP4 and MOV with H.264, and WebM β whatever your browser can both decode and encode. Camera-native formats like ProRes or raw usually cannot be opened by a browser; transcode a proxy first.
The other tools
Build this into your own project
Splitting video at its shot changes β the same way this page does it, on the user's machine, with no server. Take the code, or hand the prompt to a coding agent.
// Shot detection uses the Life2Film engine:
// https://life2film.com/wasm/va_wasm.js
const engine = await import('https://life2film.com/wasm/va_wasm.js');
await engine.default({ module_or_path: 'https://life2film.com/wasm/va_wasm_bg.wasm' });
// pixels: centre-column mean RGB per sampled frame, timestamps in seconds
const { scenes } = JSON.parse(engine.detect_scenes_slick(JSON.stringify({
pixels, timestamps, duration, algo: 'adjacent_diffs',
}))); Build a video splitter that cuts at the shot changes instead of every N seconds, in the browser.
Requirements:
- Every other splitter cuts on a fixed interval, so clips open mid-gesture. Find the cuts the video
already has and build clips out of whole shots.
- Detect shots with the "life2film-engine" npm package (WebAssembly): sample frames, take the mean RGB
of the centre column, pass pixels + timestamps to detect_scenes_slick.
- Sampling rate decides accuracy, not the algorithm. At 2 samples/second boundaries land 1-3 seconds
out and all sixteen algorithms are wrong the same way; at 10/second they land on the frame. Use a
coarse pass to find candidates, then re-sample tightly around each one at ten times the resolution.
- Group whole shots into clips near the target length; never cut inside a shot. A shot longer than the
target becomes its own clip. Absorb a short tail into the previous clip rather than leaving a
two-second orphan.
- Rank clips by picture quality using score_frame, taking the MEDIAN score per shot (one bad frame
should not sink a good shot) and weighting by duration when combining shots.
- Encode with "mediabunny", trim: {start, end} per clip, and offer a 9:16 crop via
video: { width: 1080, height: 1920, fit: 'cover' }.
- Cap the input length β every sample is a seek costing tens of milliseconds.
Reference implementation: https://life2film.com/tools/video-splitter/
The engine is documented for agents, and every tool page is available as
markdown by adding .md to its address.