We repackaged the same 1080p clip into MKV, MOV and AVI with FFmpeg's -c copy and each one finished in about 0.2 seconds, landing within half a percent of the source's 30.7 MB. Re-encoding that same clip to H.264 at a normal quality setting took 2.3 seconds and came out 76% smaller. Same source file, same target containers even in one case: a completely different operation happened underneath.
Why was your conversion instant, and why didn't the size change?
Because the video and audio inside your file were already a codec the new container can hold, so FileFlip copied the compressed data across instead of rebuilding it. That's a remux, and copying bytes cannot make them fewer.
- You'll get a remux, near-instant and same-size, when you're only swapping the container and the codec inside already fits the target: H.264 or H.265 between MP4, MOV and MKV covers most of the traffic on convert MKV to MP4, MOV to MP4 and AVI to MP4.
- You'll get a transcode, slower and a different size, the moment you change Resolution, Bitrate or Frame rate under Advanced options, or the codec inside doesn't fit the container you picked at all.
- If you actually want the file smaller, a remux won't do it. See making a video file smaller for email for the control that does.
Remuxing vs transcoding at a glance
| Remux | Transcode | |
|---|---|---|
| What happens to the video stream | Copied byte for byte into the new container | Decoded to raw frames, then re-encoded |
| Time, our 10-second 1080p clip | 0.2 seconds | 2.3 to 4.0 seconds |
| File size | Same, within container overhead | Whatever the bitrate or CRF you set produces |
| Quality | Bit-identical on decode | Some loss every pass, even at a matched bitrate |
| Happens when | The codec inside already fits the target container | The codec doesn't fit, or you changed resolution, bitrate or frame rate |
What does a remux actually do?
It copies the already-compressed video stream into a new container's bookkeeping, untouched. Nothing about the picture is decoded, so nothing about it can change.
We took a 10-second, 1920x1080 H.264 clip at 30.7 MB and ran ffmpeg -i source.mp4 -c copy output.mkv, the same for MOV and AVI. Every one finished in under a quarter of a second:
| Target | Time | Size | Change |
|---|---|---|---|
| MKV | 0.19s | 30,703,320 bytes | -0.004% |
| MOV | 0.18s | 30,704,465 bytes | 0.00% |
| AVI | 0.20s | 30,849,980 bytes | +0.47% |
We then decoded every frame of the source and every remux and hashed each one with FFmpeg's -f framemd5. The MKV and MOV hashes matched the source exactly, all 300 frames, in order. That's not "close": it's the identical stream, because -c copy never touched it.
What does a transcode actually do?
It decodes every frame back to raw pixels, then runs the encoder again as if from a fresh source, spending real CPU time on every one.
We re-encoded the same clip to H.264 at CRF 23, a typical "keep it good" setting, and to H.265 at CRF 28, a smaller target that swaps the codec too:
| Target | Time | Size | Change |
|---|---|---|---|
| H.264, CRF 23 | 2.31s | 7,464,001 bytes | -75.7% |
| H.265, CRF 28 | 4.00s | 3,193,370 bytes | -89.6% |
Both took 12 to 21 times longer than any of the remuxes above, on the machine we ran this on. That ratio is what scales: remuxing costs time in proportion to how many bytes are on disk, which a hard drive moves fast, while transcoding costs time in proportion to how many frames there are to decode and re-encode, which is real, per-pixel computation. A ten-minute clip won't take 0.2 seconds to remux, but it stays close to instant; a ten-minute transcode takes proportionally as long as our ten-second one did.
How do you predict which one you'll get?
Check whether the codec already inside your file is one the destination container is built to hold.
| Container | Codecs it can hold | Coming from an H.264 or H.265 MP4 |
|---|---|---|
| MP4 | H.264, H.265, AV1 | Already there |
| MOV | Same box structure as MP4, plus ProRes, DV | Remux |
| MKV | Any codec at all, per the format's own Matroska specification, IETF RFC 9559 | Remux |
| AVI | MPEG-4 Part 2, Motion JPEG, older codecs | Remux, usually, see below |
| WebM | VP8, VP9 or AV1 only | Always a transcode |
MP4, MOV and MKV share enough codec support that moving between them is almost always a remux. WebM sits at the other end: it only allows VP8, VP9 or AV1, so an MP4 holding H.264 has to be re-encoded to get in at all, no matter what settings you pick.
| MP4 | MKV | MOV | AVI | |
|---|---|---|---|---|
| Compression | Varies by file | Varies by file | Varies by file | Varies by file |
| Embedded metadata | Yes | Yes | Yes | Yes |
| Audio | Yes | Yes | Yes | Yes |
| Video | Yes | Yes | Yes | Yes |
| Subtitle tracks | Yes | Yes | Yes | No |
| Chapters | Yes | Yes | Yes | No |
| Streaming | Yes | Yes | Yes | No |
| Released | 2001 | 2002 | 1991 | 1992 |
| Developer | ISO/IEC MPEG (Moving Picture Experts Group) | Matroska (Steve Lhomme and contributors) | Apple | Microsoft |
Why can't a remux make the file smaller?
Because nothing about how the picture is encoded changes. The bits describing each frame are the same bits, just moved into a different box.
- Remux to MKV30.7 MB, unchanged
- Transcode, same bitrate29.9 MB
- Transcode, CRF 237.5 MB
- Transcode, HEVC CRF 283.2 MB
The remux and the bitrate-matched transcode land in almost the same place. Size tracks the settings you choose, not whether the container changed.
The small moves you do see, MKV -0.004%, AVI +0.47%, come from container bookkeeping: index tables, headers, padding, not from the picture. If you want the file smaller, remuxing was never going to do it. Making a video file smaller for email covers the Bitrate control that actually works, and by how much.
What does a transcode cost you in quality?
Some, even when you try to keep everything the same, because every decode-and-re-encode cycle requantizes the picture again.
We measured VMAF, scored against the untouched source, for each transcode above, plus a version re-encoded at the source's own 24.5 Mbps bitrate to isolate the cost of the round trip itself from the cost of a lower bitrate:
| Transcode | VMAF |
|---|---|
| Same bitrate (24.5 Mbps) | 97.3 |
| CRF 23 | 93.3 |
| HEVC CRF 28 | 90.0 |
None of those is the ceiling. Comparing the untouched source against a plain copy of itself, the same VMAF tooling reports 99.9, not a perfect 100, which is measurement noise rather than a real difference. Even the bitrate-matched transcode gives up about 2.6 points against that ceiling for no size benefit at all, purely from being decoded and re-encoded once.


Both frames are the same instant in the clip. The right side was re-encoded at 1 Mbps, a real bitrate setting for shrinking a video, and scores VMAF 62.2 against the source over the whole clip. Magnified 2x from a 320 by 180 pixel crop.
Can a remux still go wrong?
Rarely, but AVI is the one to watch. Every frame we decoded from our AVI remux hashed identical to the source, so the picture itself came through untouched. What moved was the timestamps: FFmpeg renumbered every frame's position by a constant offset, because classic AVI has no separate field for a frame's decode order versus its display order the way MP4, MOV and MKV do, documented in FFmpeg's own bitstream filter reference under the filter written to work around it. On a file with an audio track, that's the kind of gap that shows up as drift between picture and sound, which is one more reason to treat AVI as the format you convert away from rather than into.
Common questions
Does transcoding always make the file smaller?
No. It depends entirely on the bitrate or quality setting you choose, not on the act of re-encoding itself. Our bitrate-matched transcode above landed within 2.8% of the source's size while still taking over three seconds and losing a measurable amount of quality, because re-encoding and shrinking are two separate decisions.
Will FileFlip ever transcode when I only wanted to change the container?
Yes, whenever the codec inside your file isn't one the target container can hold. Converting an H.264 MP4 to WebM is the clearest example: WebM only allows VP8, VP9 or AV1, so the video gets re-encoded no matter what settings you leave alone.
Does re-encoding lose quality even at the exact same bitrate?
Yes, measurably. Our bitrate-matched transcode above scored VMAF 97.3 against a 99.9 ceiling, giving up quality it didn't have to for zero size benefit. It's the same requantization cost covered in lossy vs lossless compression, just from one re-encode instead of twenty.
Can you convert a video with no quality loss at all?
Only through a remux: swap the container, leave Resolution, Bitrate and Frame rate alone, and pick a target the codec already fits. The moment any of those changes, or the codec doesn't fit, it's a transcode and some quality is gone for good.
Convert between them
FileFlip converts MKV, MOV and AVI to MP4 entirely in your browser, on the same FFmpeg build this post's numbers came from. Nothing uploads and there's no account; leave Resolution, Bitrate and Frame rate untouched under Advanced options if a remux is what you're after.
How we measured this
- Source clip: the same 10-second, 1920x1080, 30 fps H.264 segment of Big Buck Bunny (Blender Foundation, CC BY 3.0) at roughly 24.5 Mbps used in making a video file smaller for email, fetched with
pnpm blog:corpora. - Remux:
ffmpeg -i source.mp4 -c copy output.<ext>for MKV, MOV and AVI, timed with/usr/bin/time -p. - Transcode:
ffmpeg -i source.mp4 -c:v libx264 -crf 23 -preset medium output.mp4, the same with-c:v libx265 -crf 28 -tag:v hvc1, and a third run at-b:v 24.5M -maxrate 24.5M -bufsize 49Mto hold bitrate constant while still forcing a full decode and re-encode. - Frame identity:
ffmpeg -i file -f framemd5on the source and each remux, comparing the hash and timestamp of every one of the 300 frames. - Quality: FFmpeg's
libvmaffilter, candidate against the untouched source, both streams already at the same 1920x1080 resolution so no scaling was involved. - Tools: FFmpeg 8.1.2 with libx264, libx265 and libvmaf, on macOS.
- Caveat: one 10-second clip is a single data point, and the exact seconds above are specific to the machine we ran them on; a longer or more detailed source will change the absolute numbers while keeping the same shape, because remux time tracks bytes and transcode time tracks frames.
- Reproducing it:
node scripts/benchmark-video-encoders.mjs <clip>in the repository prints the container and VMAF tables this post draws from; the CRF and matched-bitrate transcode timings were run directly against the same clip.