How to play an MKV on a Mac without re-encoding it
An MKV often holds video the Mac can already decode. Moving it into an MP4 took 0.5 to 1.4 seconds in our test. The commands, the HEVC tag trap, and how Kinora handles it.
3 Nov 2026 · T. Krause · 10 min read
To play an MKV on a Mac without re-encoding it, copy its streams into an MP4 with ffmpeg:
ffmpeg -i film.mkv -c copy film.mp4
On macOS 27.2 this works when the video inside is H.264 and the sound is AAC, AC-3, E-AC-3, ALAC, FLAC or Opus. I haven't tested whether older versions play FLAC and Opus in an MP4. HEVC needs -tag:v hvc1. MP3, MP2, DTS, Vorbis and TrueHD need -c:a aac, and surround needs one more option. All of that is explained below. The step is called remuxing, and it leaves the picture and sound data untouched. On a five-minute 1080p test file of 587 MB it took 0.5 to 1.4 seconds. Re-encoding the same file took 28 to 42 seconds.
The problem is usually the container, the file format that wraps the streams. AVFoundation, Apple's media framework, rejected every MKV I gave it, including one holding H.264 and AAC, which it plays without trouble in an MP4.
What AVFoundation accepted
I made short test files with ffmpeg 8.1.2 and asked AVFoundation about each one on macOS 27.2, using the same check as our video player Kinora. All the MP4s below were copied without re-encoding. ffmpeg exited with status 0 for each of them except TrueHD, which stops with status 88 unless you add -strict -2.
| File | Video / audio | Plays? |
|---|---|---|
.mkv | H.264 / AAC | No |
.mkv | H.264 / Opus | No |
.mkv | HEVC / AAC | No |
.webm | VP9 / Opus | No |
.avi | MPEG-4 / MP3 | No |
.mp4 | H.264 / AAC | Yes |
.mp4 | H.264 / Opus | Yes |
.mp4 | H.264 / MP3 | Picture only, no audio track |
.mp4 | H.264 / MP2 | Picture only, no audio track |
.mp4 | H.264 / DTS | Picture only, no audio track |
.mp4 | H.264 / Vorbis | Picture only, no audio track |
.mp4 | H.264 / TrueHD, with -strict -2 | Audio track listed as not playable |
.mp4 | HEVC / AAC, tag hev1 | No, only the audio track passes |
.mp4 | HEVC / AAC, tag hvc1 | Yes |
.mp4 | VP9 / Opus | No, only the audio track passes |
Three results matter most. A clean exit from ffmpeg doesn't mean the result plays, as the VP9 file shows. The two HEVC rows hold the same video data and differ only in a tag. And the MP3, MP2, DTS and Vorbis files count as playable even though AVFoundation has dropped their sound.
The HEVC tag
Without further instructions, ffmpeg wrote the HEVC stream with the tag hev1, and AVFoundation refused its video track. With -tag:v hvc1 the same stream played. The two tags mark where the stream's parameter sets are stored. Apple's HLS authoring specification is written for streaming, but it states the same preference, recommending hvc1 over hev1.
ffmpeg -i film.mkv -c copy -tag:v hvc1 film.mp4
Use the tag only for HEVC. To see what a file holds, ask ffprobe:
ffprobe -v error -show_entries stream=codec_type,codec_name -of csv=p=0 film.mkv
When the sound goes missing
MP3, MP2, DTS and Vorbis fail without any warning. ffmpeg exits with 0 and ffprobe still shows the audio stream in the MP4, but AVFoundation lists only the video track and calls the file playable. AVPlayer ran such a file with a video track and nothing else. I didn't listen to it, so "silent" is my conclusion from there being no audio track to play. Sample rates of 44.1 and 48 kHz behaved the same. AAC, AC-3, E-AC-3, ALAC, FLAC and Opus all kept their tracks, and AVFoundation decoded each of them.
For those four and TrueHD, copy the video and convert only the sound:
ffmpeg -i film.mkv -c:v copy -c:a aac film.mp4
That gave a playable AAC track in the test. With HEVC, add -tag:v hvc1 to the same command. If you want to keep the MP3 as it is, an H.264 file written to film.mov with -c copy kept its MP3 track, which AVFoundation listed and decoded.
Surround has a trap of its own. On a 5.1 DTS, TrueHD or FLAC file, that command exits with 0 and the sound is gone again, because all three decode to a layout called 5.1(side). ffmpeg's AAC encoder writes that layout with a program config element, and AVFoundation listed no track for the result. Ask for a layout the encoder writes plainly:
ffmpeg -i film.mkv -c:v copy -c:a aac -af "aformat=channel_layouts=7.1|5.1|5.0|4.0|3.0|stereo|mono" film.mp4
The same three files then had a playable 5.1 AAC track.
Subtitles need a word of warning. By default ffmpeg took one video and one audio stream and left out an SRT track without a message. Adding -map 0 to keep everything made it stop with "Could not find tag for codec subrip".
How Kinora decides
Kinora is a Mac video player built around variable speed and a spectrogram centred on the playhead. It analyses the sound ahead of playback, so the spectrogram also shows what comes next. It doesn't bundle ffmpeg, but it uses one you've installed to open these files. The logic is in MediaPreparer.swift, about 400 lines, and it makes the same decisions as the commands above.
It first asks AVFoundation about the file and then about each track AVFoundation lists. Asking about the file alone isn't enough, because a file can list a sound track that won't play, and Kinora treats that as not playable. When AVFoundation lists no sound at all, Kinora asks ffprobe to read up to 256 packets of each audio stream and count how many decode. If a stream has sound, the file goes to conversion. A file that passes opens directly and ffmpeg never runs.
Otherwise ffprobe reads the codecs, and Kinora decides the picture and the sound separately.
For the picture, H.264 and HEVC get copied, HEVC with the hvc1 tag. So does any other video AVFoundation already plays in the source, such as MPEG-4 in an MP4. Everything else goes through h264_videotoolbox, the hardware encoder, or libx264 in software if the hardware encoder fails or its result doesn't play.
For the sound, Kinora takes the first audio stream with sound in it. It skips a stream with no packets, and one where fewer than one packet in three decodes. AAC, ALAC, AC-3 and E-AC-3 get copied. Anything else becomes AAC at 192 kbit/s, with the layout list above for surround.
After each attempt, Kinora asks AVFoundation about the output. If the sound is missing, only the sound changes: a copy becomes AAC, surround AAC becomes stereo, then comes the next stream, and last the picture alone. If the picture fails, only the video step changes. A retry for the sound leaves copied video copied, so only the sound is encoded again. Video that needs encoding goes through the encoder again on every attempt, because Kinora doesn't keep the first pass. MPEG-4, VP9 or AV1 in an MKV with AAC that a copy loses takes two encodes. A video with no sound at all passes. Given the table above, I'd copy this check into any script of your own.
If every stream fails, the picture plays with a line over it: "No sound: Kinora can't decode this file's audio." A stream with no packets isn't audio, so that file plays with no line, and the spectrogram panel says "No audio track". If there's nothing to play at all, Kinora says the file couldn't be converted.
I ran an H.264 MKV, an HEVC MKV and an MPEG-4 AVI with MP3 speech through the app, with a meter on the player's audio output. All three reached the output with peaks of -2.3 dBFS. DTS and TrueHD 5.1 MKVs with a test tone reached it at -18 dBFS. The meter replaces the samples with silence, so I still haven't listened to any of them. A video with no sound played on, with "No audio track" where the spectrogram would be.
Opus and FLAC show where this list is more careful than macOS 27.2 needs, since both played fine in an MP4. Kinora runs from macOS 14 and I tested only one version, so I can't say whether older systems accept them. The cost is one extra generation of audio encoding, and FLAC stops being lossless.
What each step costs
I timed Kinora's encoder settings on a generated 1080p test pattern with a stereo test tone, five minutes at 30 frames per second, on an M3 Pro that was also running other work. Each ran at least three times, and the two encoder rows also turn the sound into AAC at 192 kbit/s. The test file's sound is already AAC, which Kinora itself would copy, and copying it made both files only 0.26 MB smaller.
| Step | Time | Output size |
|---|---|---|
| Copy streams | 0.5 to 1.4 s | 587 MB |
| Copy video, MP3 sound to AAC (a second test file of the same length) | 3.5 to 3.7 s | 589 MB |
| Hardware encoder | about 42 s | 311 MB |
| Software encoder | 28 to 40 s | 278 MB |
The hardware encoder was slower here and its file was larger, which I didn't expect. A test pattern isn't a film and the machine was busy, so I wouldn't conclude much from it without timing real footage. The gap between copying and encoding is the result that matters.
Kinora also passes -movflags +faststart. That moves the file's index, the table covered in what happens to a recording when the Mac crashes, to the front. In the test output the index started at byte 32 with the flag and at byte 586,347,784 without it.
What you give up
Sound in MP3, DTS and the other formats off the copy list gets encoded again as AAC, which costs one generation of quality. That includes an MP4 with MP3 sound, which goes through conversion before it plays. The rate stays at 192 kbit/s for surround, so 5.1 gets far less per channel than stereo.
Damaged audio can be loud. An MP3 with 5% of its bytes overwritten decoded to +89.7 dBFS after a plain AAC encode. Kinora puts a limiter at full scale on every AAC encode, and that brought the same file down to +1.6 dBFS. The damage is still there as noise. Below full scale the limiter changed nothing in the test, and copied audio doesn't pass through it.
Kinora keeps the first video stream and one audio stream, using -map 0:v:0? -map 0:<stream> -sn -dn. A film with several languages plays in whichever comes first and has sound, and subtitles inside the file are dropped. A .srt file with the same name next to the video still loads.
Conversion isn't streaming either. Kinora shows a percentage and starts playback when ffmpeg has finished, so a long film that needs encoding means a wait. The temporary MP4 can be about as large as the original. Kinora deletes it when the window closes, or at the next launch if the app didn't get that far. If you close the window during a conversion, the partial file goes too.
Without ffmpeg, these files don't open at all, and Kinora tells you to run brew install ffmpeg. It looks in four fixed folders: /opt/homebrew/bin, /usr/local/bin, /opt/local/bin and /usr/bin. An MP4 with sound AVFoundation doesn't list gets the same message, as long as ffprobe is there to notice the sound. Homebrew's ffmpeg package installs both. With ffprobe missing as well, Kinora can't tell the sound is there: the picture plays with no sound, and the spectrogram panel says "No audio track".
When AVFoundation lists a sound track as playable, Kinora takes its word. In the test, it listed AAC damaged throughout in an MP4 and decoded no samples from it, so that file opens directly with no "No sound" line.
To try it, install ffmpeg and open an MKV you have lying around in the Kinora demo, which has every feature and closes after five minutes. Then change the speed and watch the spectrogram, since those are what the app is for. Kinora needs macOS 14 or later on Apple silicon, and the download is on the Kinora page.