You don’t need to re-encode MKV to get MP4. A remux — swapping the container while keeping the streams byte-identical — takes seconds, is completely lossless, and produces a file the same size. This guide covers the one-line command, the three cases where a plain remux fails, and the minimal re-encode recipes that fix them. ~8 min read.
Tested on: FFmpeg 6.1 / Windows 11 / Ubuntu 24.04
What you’ll learn
- Remux vs. re-encode — what actually changes
- The one-line command
- Three typical failure modes and how to fix each
- The practical middle-ground: keep video, re-encode audio only
- Why
-movflags +faststartmatters - Handling multi-audio / multi-subtitle tracks
- FAQ
1. Remux vs. re-encode
| Operation | What happens to streams | Time | Quality | Size |
|---|---|---|---|---|
Remux (-c copy) | Bit-for-bit copy | Seconds | Identical | Essentially same |
| Re-encode | Decode → re-compress | Minutes to hours | Slight loss | Depends on settings |
MKV and MP4 are both just containers. If the streams inside (H.264, H.265, AAC, AC-3, …) are compatible with MP4, you only need to rewrap — you do not need to re-encode.
2. The basic command
ffmpeg -i input.mkv -c copy -movflags +faststart output.mp4
-c copy— copy all streams without re-encoding-movflags +faststart— move the moov atom to the start (required for web playback and streaming)
If the codecs are MP4-compatible (H.264, H.265, AAC, AC-3, MP3, etc.), that’s it.
3. Three typical failure modes
Mode 1: subtitle format is incompatible
Error:
[mp4 @ 0x...] Could not find tag for codec subrip in stream #2, codec not currently supported in container
Why: MKV commonly carries SRT / SSA / ASS text subtitles. MP4 only accepts mov_text (tx3g).
Fix A — convert subtitles on the fly:
ffmpeg -i input.mkv -c:v copy -c:a copy -c:s mov_text -movflags +faststart output.mp4
Fix B — drop subtitles:
ffmpeg -i input.mkv -c copy -sn -movflags +faststart output.mp4
-sndisables subtitle streams in the output. Image subtitles (PGS, VobSub) cannot be converted to mov_text — dropping them is the safe option.
Mode 2: non-standard audio codec (PCM / FLAC / Opus)
Error:
[mp4 @ 0x...] Could not find tag for codec pcm_s16le in stream #1
Why: MKV can hold PCM, FLAC, Opus, Vorbis. Recent FFmpeg builds can mux Opus/FLAC into MP4, but older players (QuickTime, Windows Media, various mobile apps) can’t play them.
Fix — re-encode audio only to AAC:
ffmpeg -i input.mkv -c:v copy -c:a aac -b:a 192k -movflags +faststart output.mp4
Video stays byte-identical; only audio re-encodes. It’s a fraction of the time a full re-encode would take.
Mode 3: video codec is MP4-unfriendly (VP9 / AV1)
Symptom: Command succeeds but the output won’t play on many devices.
Why: VP9 and AV1 can technically live inside MP4 (fMP4), but Windows “Films & TV”, older iPhones, and many hardware players refuse to decode them from an MP4.
Fix A — re-encode to H.264 for max compatibility:
ffmpeg -i input.mkv -c:v libx264 -crf 20 -preset slow -c:a aac -b:a 192k -movflags +faststart output.mp4
Fix B — keep VP9/AV1 but use WebM:
ffmpeg -i input.mkv -c copy output.webm
This keeps the file lossless and plays in modern browsers.
4. The practical middle-ground: video copy + audio re-encode
In real life, the most common need is “keep the video as-is, normalize the audio.” Since video encoding is the expensive part, this recipe is cheap and almost always works:
ffmpeg -i input.mkv \
-c:v copy \
-c:a aac -b:a 192k \
-c:s mov_text \
-movflags +faststart \
output.mp4
Video, audio, and text subtitles are all MP4-compatible after this one command.
5. Is -movflags +faststart required?
| Use case | +faststart needed? |
|---|---|
| Local playback only | Optional (harmless) |
| Web / streaming playback | Required (otherwise the browser must download the entire file before playback) |
| Social media upload (Discord, Twitter, etc.) | Required |
| Phone / older player compatibility | Strongly recommended |
MP4’s moov atom (index data) is written at the end by default. +faststart relocates it to the front so browsers can stream from the first byte.
6. Multi-audio / multi-subtitle handling
Copy everything
ffmpeg -i input.mkv -map 0 -c copy -movflags +faststart output.mp4
-map 0 maps every stream from input 0 to the output.
Keep only specific tracks
# Video, second audio track (index 1), and Japanese subtitle (if present)
ffmpeg -i input.mkv \
-map 0:v:0 -map 0:a:1 -map 0:s:m:language:jpn? \
-c copy -c:s mov_text \
-movflags +faststart output.mp4
The ? suffix on -map means “don’t error if this track doesn’t exist” — safer when you’re not 100 % sure the stream is there.
Inspect streams first with
ffprobe input.mkv, or see our ffprobe metadata guide.
7. Troubleshooting
Could not find tag for codec X in stream Y
Why: That stream’s codec isn’t MP4-supported.
Fix: Re-encode just that stream, or drop it with -sn / -an.
Output plays as black / silent
Why: -c copy wrapped VP9/AV1 in MP4 but the player can’t decode.
Fix: Check with ffprobe. Re-encode to H.264 or keep as WebM.
File truncates at 1 hour
Why: 32-bit FFmpeg build × MKV’s timestamp quirks (PCR wrap).
Fix: Use a 64-bit official build. On Windows grab ffmpeg-full from gyan.dev.
Subtitles come out as garbled characters
Why: Source SRT was Shift-JIS / Windows-1252 and wasn’t converted to UTF-8 before being packed into mov_text.
Fix: Convert with iconv first:
iconv -f SHIFT-JIS -t UTF-8 subtitle.srt > subtitle_utf8.srt
ffmpeg -i input.mkv -i subtitle_utf8.srt -c:v copy -c:a copy -c:s mov_text output.mp4
Remuxed file is larger than the source
Why: Packed B-frames and similar MKV-only tricks get unpacked into MP4’s format. Usually within ±5 %.
Fix: Live with it, or re-encode video lightly (-c:v libx264 -crf 20 -preset medium).
FAQ
Q1. Is remuxing really lossless?
A. Yes. -c copy does a bit-for-bit copy of the bitstream — zero quality change. Only timestamps and container headers get rewritten.
Q2. Same command in reverse (MP4 → MKV)?
A. Almost identical: ffmpeg -i input.mp4 -c copy output.mkv. MKV accepts pretty much anything, so compatibility issues are much rarer going this direction.
Q3. Batch-convert a folder of MKVs to MP4?
A. A shell loop is plenty fast:
for f in *.mkv; do ffmpeg -i "$f" -c copy -movflags +faststart "${f%.mkv}.mp4"; done
See our batch-convert article for more patterns.
Q4. Why would I prefer MKV over MP4 in the first place?
A. MKV has looser limits on subtitles and audio tracks, and can hold Opus / FLAC (lossless / modern audio) and PGS image subtitles. It’s the better choice for masters and archives. MP4 wins for distribution and web playback.
Q5. The remuxed MP4 won’t play in macOS QuickTime.
A. Usually either H.265 without the hvc1 tag, or non-MP3 audio incompatibility. -tag:v hvc1 fixes the HEVC case — see our iPhone MOV to MP4 guide.
Related resources
FFmpeg Cheat Sheet (PDF): remux, container conversion, and stream mapping commands on a single A4.
Related posts
- FFmpeg Video Compression — CRF & Bitrate Guide
- iPhone MOV to MP4 — The hvc1 Tag Fix
- Inspect Video Metadata with FFprobe
- Batch Convert with Shell Scripts
Tested on ffmpeg 6.1.1 / Windows 11 + Ubuntu 24.04
Primary sources: ffmpeg.org/ffmpeg.html / ffmpeg.org/ffmpeg-formats.html / trac.ffmpeg.org/wiki/Map