You don’t need to re-encode an MKV to get an MP4. A remux moves the streams into a new container and leaves them byte-identical. It takes seconds, loses no quality, and the file comes out about the same size.
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 containers: file formats that hold the video, audio and subtitle streams. If the streams inside (H.264, H.265, AAC, AC-3, …) are ones MP4 supports, you only need to rewrap them, not re-encode them.
2. The basic command
ffmpeg -i input.mkv -c copy -movflags +faststart output.mp4
-c copy— copy the streams without re-encoding. Without-map, FFmpeg keeps only one video and one audio stream, and no subtitles (see Mode 1); section 6 shows how to keep every track.-movflags +faststart— move the file’s index (the moov atom) to the start. Recommended for web playback and streaming.
If the codecs are ones MP4 supports (H.264, H.265, AAC, AC-3, MP3, etc.), this is all you need.
3. Three typical failure modes
Mode 1: subtitle format is incompatible
Symptom: The basic command finishes, but the MP4 has no subtitles. Without -map, FFmpeg picks a subtitle stream for MP4 only when you set a subtitle codec such as -c:s mov_text. If you keep every stream with -map 0, the command stops with this error instead:
[mp4 @ 0x...] Could not find tag for codec subrip in stream #2, codec not currently supported in container
Why: MKV files often carry SRT, SSA or ASS text subtitles. MP4 cannot store these as they are, so they have to be converted to mov_text (tx3g), the text subtitle format of MP4.
Fix A — convert the subtitles while remuxing:
ffmpeg -i input.mkv -c:v copy -c:a copy -c:s mov_text -movflags +faststart output.mp4
Fix B — drop the subtitles and keep every video and audio track:
ffmpeg -i input.mkv -map 0:v -map 0:a -c copy -movflags +faststart output.mp4
-map 0:v -map 0:aselects every video and audio stream, so subtitles and attachments are left out. Image-based subtitles (PGS, VobSub) cannot be converted to mov_text, so 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 and Vorbis audio. Recent FFmpeg builds (8.1 included) put FLAC, Opus and most PCM formats, such as pcm_s16le, into MP4 without the error above. 8-bit PCM (pcm_u8) and a few other PCM formats still stop with it. Even when the audio goes in, older players (QuickTime, Windows Media, various mobile apps) cannot play it.
Fix — re-encode only the audio, to AAC:
ffmpeg -i input.mkv -c:v copy -c:a aac -b:a 192k -movflags +faststart output.mp4
The video stays byte-identical and only the audio is re-encoded, so this takes a fraction of the time of a full re-encode.
Mode 3: video codec is MP4-unfriendly (VP9 / AV1)
Symptom: The command succeeds, but the output does not play on many devices.
Why: MP4 can hold VP9 and AV1, but Windows “Films & TV” without the VP9 or AV1 video extension, older iPhones and many hardware players cannot play them from an MP4.
Fix A — re-encode to H.264 so it plays almost everywhere:
ffmpeg -i input.mkv -c:v libx264 -crf 20 -preset slow -pix_fmt yuv420p -c:a aac -b:a 192k -movflags +faststart output.mp4
-pix_fmt yuv420p makes the video 8-bit, which almost every player can decode. It does not convert HDR to SDR, though. For an HDR source, see HDR to SDR.
Fix B — keep VP9/AV1 but use WebM:
ffmpeg -i input.mkv -c copy output.webm
This is lossless and plays in modern browsers, but only if the audio is already Opus or Vorbis. WebM accepts only VP8/VP9/AV1 video, Opus/Vorbis audio and WebVTT subtitles. With AAC, AC-3 or FLAC audio, or with SRT/ASS subtitles, the command fails. In that case convert the audio and subtitles: ffmpeg -i input.mkv -c:v copy -c:a libopus -c:s webvtt output.webm. With 5.1 AC-3 audio, libopus stops with Invalid channel layout 5.1(side). Add -af aformat=channel_layouts=5.1 to keep the 5.1 sound, or -ac 2 to make it stereo.
4. The practical middle-ground: video copy + audio re-encode
Most often you want to keep the video as it is and only fix the audio. Video encoding is the slow part, so this is fast 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
After this command, the video, audio and text subtitles are all in formats MP4 supports.
5. Is -movflags +faststart required?
| Use case | +faststart needed? |
|---|---|
| Local playback only | Optional (harmless) |
| Web / streaming playback | Strongly recommended (otherwise the player has to fetch the moov from the end first; if the server doesn’t support range requests, it must receive the entire file before playback) |
| Social media upload (Discord, Twitter, etc.) | Recommended |
| Phone / older player compatibility | Strongly recommended |
The MP4 moov atom (the index) is written at the end of the file by default. +faststart moves it to the front, so browsers can start playing from the first bytes.
6. Multi-audio / multi-subtitle handling
Copy everything
ffmpeg -i input.mkv -map 0 -map -0:t -c copy -c:s mov_text -movflags +faststart output.mp4
-map 0 selects every stream from input 0. MP4 cannot store SRT/ASS subtitles or attachments such as fonts as they are, so -c:s mov_text converts the subtitles and -map -0:t drops the attachments.
Keep only specific tracks
# Video, second audio track (index 1), and the Japanese subtitle
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
-map 0:s:m:language:jpn selects the subtitle whose language tag is jpn. If the input has no such track, the command fails.
Adding a ? (-map 0:s:m:language:jpn?) does not help. The ? suffix means “no error if this stream is missing”, but it works only on simple selectors such as 0:s?. After the m:key:value form, FFmpeg reads it as part of the language value (jpn?). In FFmpeg 8.1 the command then fails with Stream map matches no streams, even when a Japanese subtitle is present. If you are not sure a subtitle exists, drop the language filter and use -map 0:s?.
Check the streams first with
ffprobe input.mkv, or see the ffprobe metadata guide.
7. Troubleshooting
Could not find tag for codec X in stream Y
Why: MP4 does not support that stream’s codec.
Fix: Re-encode only that stream, or drop it with -sn / -an.
Output plays as black / silent
Why: -c copy put VP9/AV1 into the MP4, and the player cannot decode it.
Fix: Check the codecs with ffprobe. Re-encode to H.264, or keep the file as WebM.
Invalid UTF-8 in decoded subtitles text
Why: The source SRT is Shift-JIS or Windows-1252, not UTF-8. FFmpeg cannot read the text, so the subtitle track in the MP4 comes out empty.
Fix: Convert it to UTF-8 with iconv first:
iconv -f SHIFT-JIS -t UTF-8 subtitle.srt > subtitle_utf8.srt
ffmpeg -i input.mkv -i subtitle_utf8.srt -map 0:v -map 0:a -map 1 -c:v copy -c:a copy -c:s mov_text output.mp4
Without the -map options, FFmpeg picks a subtitle track already inside input.mkv and leaves subtitle_utf8.srt out.
FFmpeg can also do the conversion: put -sub_charenc CP932 (for Shift-JIS) or -sub_charenc CP1252 (for Windows-1252) before -i subtitle.srt.
Remuxed file is larger than the source
Why: MKV and MP4 store timestamps and the index (the container’s bookkeeping) differently. The video and audio data do not change, so the difference is small.
Fix: Accept it. Re-encoding costs quality, and at CRF 20 the file can even come out larger.
FAQ
Q1. Is remuxing really lossless?
A. Yes. -c copy copies the streams bit for bit, so the quality does not change. Only the timestamps and container headers are rewritten.
Q2. Same command in reverse (MP4 → MKV)?
A. Almost the same: ffmpeg -i input.mp4 -c copy output.mkv. MKV accepts nearly every codec, so problems are much rarer in this direction. One exception: FFmpeg cannot copy an MP4 text subtitle (mov_text) into MKV. Add -c:s srt to convert it.
Q3. Batch-convert a folder of MKVs to MP4?
A. Use a shell loop:
for f in *.mkv; do ffmpeg -i "$f" -c copy -movflags +faststart "${f%.mkv}.mp4"; done
See batch conversion with shell scripts for more patterns.
Q4. Why would I prefer MKV over MP4 in the first place?
A. MKV has fewer limits on subtitles and audio tracks. It can hold FLAC (lossless) and Opus audio and PGS image subtitles, so it is the better choice for masters and archives. MP4 is better for sharing and web playback.
Q5. The remuxed MP4 won’t play in macOS QuickTime.
A. Usually the H.265 video is tagged hev1 instead of hvc1. FFmpeg uses hev1 by default when it remuxes HEVC into MP4. Adding -tag:v hvc1 fixes it; see the iPhone MOV to MP4 guide.