Сжать видео
Задайте размер — 10 МБ для Discord, 25 МБ для почты — или просто снизьте качество. Всё считается на вашей машине, поэтому нет ни лимита, ни очереди.
Файл читает и перекодирует ваш собственный браузер. Ни один запрос никуда его не отправляет — у этой страницы просто нет сервера, куда его загружать.
Вопросы
Он правда попадает в точный размер?
Для этого и сделан режим «уложиться в размер». Вес файла — это битрейт, умноженный на длительность, поэтому при известной длительности нужный битрейт вычисляется арифметически. Кодировщики не соблюдают заданный битрейт идеально — управление потоком плывёт в зависимости от материала, — поэтому если первый проход промахнулся больше чем на несколько процентов, промах измеряется и файл перекодируется ещё раз с поправкой. На практике результат оказывается в паре процентов от цели.
Почему именно 10, 16 и 25 МБ?
Это стены, о которые люди реально бьются: 10 МБ — бесплатный лимит Discord, 16 МБ — WhatsApp, 25 МБ — Gmail и большинство почтовых серверов, 50 МБ — Discord Nitro Basic. Инструмент целится чуть ниже лимита, а не ровно в него, потому что файл ровно на 10,0 МБ десятимегабайтный лимит всё равно отклонит.
А если цель недостижима?
Он скажет об этом до начала и назовёт минимальный честный размер для этого видео. Втиснуть час материала в 10 МБ означало бы битрейт, которого не переживает ни одно разрешение: инструмент, который выдал бы нечитаемое видео и назвал это успехом, хуже того, который отказывается.
Насколько уменьшится мой файл?
Прогноз показывается до того, как вы что-то нажали, — из настроек и длительности. Материал прямо с телефона или камеры обычно записан с запасом далеко выше необходимого, и сокращение на 60–90 % там обычное дело. У того, что уже сжимали однажды, запаса почти нет, и инструмент сравнивает ваш файл с тем, что его разрешению разумно требуется, и предупреждает, когда перекодирование только увеличит размер.
Что вообще уменьшает видео?
Меньше пикселей и меньше битов на пиксель. Разрешение — грубый и надёжный рычаг: переход с 4K на 1080p убирает три четверти пикселей ещё до разговора о качестве. Битрейт затем решает, сколько деталей уцелеет. Отключение звука помогает мало: он редко составляет больше нескольких процентов видеофайла.
Файл куда-нибудь загружается?
Нет. Всё идёт через WebCodecs в вашем браузере — именно это делает такой подход осмысленным: загрузить гигабайт, чтобы сервер вернул 200 МБ, дольше, чем посчитать локально, и попутно оставляет ваш материал на чужом диске. Ни лимита размера, ни очереди, ни водяных знаков — потому что нет сервера, который бы их вводил.
Другие инструменты
Build this into your own project
Compressing video to a target file size — 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.
// npm i mediabunny
import { Input, Output, Conversion, BlobSource, BufferTarget, Mp4OutputFormat, ALL_FORMATS } from 'mediabunny';
// Size is bitrate x duration, so a target size fixes the bitrate.
const OVERHEAD = 0.04; // container headers and packaging
const AUDIO_BITRATE = 128_000;
export async function compressToSize(file, targetBytes, { width } = {}) {
const input = new Input({ source: new BlobSource(file), formats: ALL_FORMATS });
const duration = await input.computeDuration();
// Aim under the wall: a file of exactly 10.00 MB is still refused by a 10 MB limit.
const aim = targetBytes * 0.96;
const videoBitrate = Math.max(
90_000,
Math.round((aim * 8 * (1 - OVERHEAD) - AUDIO_BITRATE * duration) / duration),
);
const output = new Output({ format: new Mp4OutputFormat(), target: new BufferTarget() });
const conversion = await Conversion.init({
input,
output,
video: {
...(width ? { width } : {}),
bitrate: videoBitrate,
hardwareAcceleration: 'prefer-hardware', // 180 fps vs 34 on an M5 at 1080p
},
audio: { bitrate: AUDIO_BITRATE },
});
if (!conversion.isValid) throw new Error('Cannot convert this file');
await conversion.execute();
return new Blob([output.target.buffer], { type: 'video/mp4' });
}
// Encoders drift, so measure and correct once if the first pass missed.
const blob = await compressToSize(file, 10 * 1024 * 1024);
console.log(blob.size / 1048576, 'MB'); Build me a video compressor that runs entirely in the browser — no upload, no server.
Requirements:
- Use the "mediabunny" npm package, which wraps WebCodecs. Do not use ffmpeg.wasm: it is ~30 MB and
needs SharedArrayBuffer, which requires COOP/COEP headers that break third-party scripts.
- Let the user target a file size (presets: 10 MB Discord, 16 MB WhatsApp, 25 MB email) as well as
picking a quality.
- To hit a size: size = bitrate x duration, so videoBitrate = (targetBytes * 8 * 0.96 - audioBitrate
* duration) / duration. Aim at 96% of the limit, because a file of exactly 10.00 MB is still
rejected by a 10 MB limit.
- Encoders do not obey a requested bitrate exactly. Measure the result; if it missed by more than 4%
or broke the limit, re-encode once with bitrate * (target / actual), damped to at most a halving
or doubling. Stop at two passes.
- Pass hardwareAcceleration: 'prefer-hardware'. Measured on an M5 at 1080p: 180 fps against 34 fps
for software, and the software encoder also overshot the requested bitrate by 3.5x.
- Show the estimated output size before encoding, and the real before/after afterwards.
- Refuse impossible targets up front: below about 90 kbps video is unwatchable, so if the target
cannot be met at that floor, say so and give the smallest honest size instead of producing junk.
- Warn when the source is already compressed below what its resolution needs — re-encoding it will
make it larger, and only reducing the resolution will help.
Reference implementation: https://life2film.com/tools/video-compressor/
The engine is documented for agents, and every tool page is available as
markdown by adding .md to its address.