People convert video far more often than they need to. A great many of those conversions change only the container. The wrapper around the streams, and that can be done in seconds without decoding anything.
What a container is
MP4, MKV, MOV and WebM are containers. They hold streams: a video stream in some codec, one or more audio streams, subtitles, metadata.
The container is not the video. An MKV and an MP4 can hold byte-identical H.264 video, and converting between them is a matter of rewriting the wrapper.
That is remuxing, and in FFmpeg it is one flag:
ffmpeg -i input.mkv -c copy output.mp4
-c copy means copy every stream as it is. No decoding, no encoding, no quality change. A file that would take twenty minutes to re-encode is written in about a second, because the work is reading and writing bytes.
When it works and when it does not
The only question is whether the target container accepts the codecs already inside the file.
Check before you start:
ffprobe -v error -show_entries stream=index,codec_type,codec_name -of csv input.mkv
H.264 video with AAC audio goes into MP4 without complaint. So does H.265, given the right tag. VP9 and Opus belong in WebM or MKV.
Where it fails is a mismatch. A container being asked to hold something it does not support. The usual case is subtitles: MKV holds subtitle formats MP4 does not, and the remux fails on the subtitle stream while the video and audio would have been fine.
The fix is to drop or convert just that stream, not to re-encode the video:
ffmpeg -i input.mkv -map 0:v -map 0:a -c copy output.mp4
Or convert the subtitles alone and copy everything else. Working with subtitles in FFmpeg walks through that case.
Copying one stream and not the other
-c copy is a shorthand. The parts can be set separately, which is how you fix an audio problem without touching the video:
ffmpeg -i input.mkv -c:v copy -c:a aac -b:a 192k output.mp4
The video. The expensive part, is copied untouched. Only the audio is re-encoded, which takes seconds.
This is the answer whenever a file is "nearly right": the video is fine and the audio codec is not accepted by the target, or a device refuses one track but plays the other.
Making an MP4 start playing sooner
MP4 keeps an index of the file, and by default it is written at the end, which means a browser must download the whole file before playback can begin.
ffmpeg -i input.mp4 -c copy -movflags +faststart output.mp4
That moves the index to the front. It is still a remux, still lossless, still seconds, and it is the difference between a video that starts immediately and one that appears to hang.
Every MP4 you serve from a website should have this done to it. Serving video efficiently from your own server walks through the delivery side.
Cutting without re-encoding
Trimming can be a copy too, with one caveat:
ffmpeg -ss 00:01:30 -i input.mp4 -t 60 -c copy output.mp4
Because nothing is decoded, the cut can only land on a keyframe. The result is that the actual start may differ from what you asked by up to a few seconds.
For rough extraction that is fine and enormously faster. For a frame-accurate cut you must re-encode. Trimming, cutting and concatenating explains the trade in detail.
What remuxing cannot do
It cannot change resolution, bitrate, codec or quality, because it never looks inside the streams.
If the file needs to be smaller, or needs a different codec, that is re-encoding and there is no shortcut. Choosing a video codec sets out making that decision well.
The habit worth building: before writing any conversion command, run ffprobe and ask whether a copy would do. It very often would.
Check whether a copy is possible before writing the command
One question decides everything: are the codecs already inside the file ones the target container accepts?
ffprobe -v error -show_entries stream=index,codec_type,codec_name,codec_tag_string \ -of csv=p=0 input.mkv
The tag string matters as much as the codec name. H.265 video tagged hev1 plays in some places and not on Apple devices, which expect hvc1, and that is fixable during a remux without re-encoding:
ffmpeg -i input.mp4 -c copy -tag:v hvc1 output.mp4
A file that plays everywhere except one platform is frequently this, and the fix takes a second rather than an hour.
Timestamps are what break a remux
The commonest remux failure is not a codec mismatch but timing.
A source with gaps, negative starting timestamps or a variable frame rate can produce an output with audio drifting out of sync, while the command reported success.
ffmpeg -fflags +genpts -i input.mkv -c copy output.mp4 ffmpeg -i input.mkv -c copy -avoid_negative_ts make_zero output.mp4
The first regenerates presentation timestamps; the second shifts them so nothing starts before zero, which some players handle badly.
Always check the result rather than assuming: play the end of the file, not the beginning, since drift accumulates. A remux that looks correct in the first ten seconds can be seconds out by the end.
Joining files without re-encoding
Concatenation is a copy operation when the files genuinely match:
printf "file '%s'\n" part1.mp4 part2.mp4 > list.txt ffmpeg -f concat -safe 0 -i list.txt -c copy joined.mp4
The requirement is strict: identical codecs, resolution, frame rate and audio parameters. Files that differ in any of those produce either an error or an output that plays only the first part.
Verify before joining rather than after:
for f in part*.mp4; do ffprobe -v error -show_entries stream=codec_name,width,height,r_frame_rate -of csv=p=0 "$f"; done
Where they differ, re-encoding is unavoidable. Trimming, cutting and concatenating deals with that path.
Confirm nothing was actually re-encoded
A copy that silently became a re-encode is easy to miss, because the output is fine. It simply took an hour and lost quality.
The signal is in the output FFmpeg prints: a stream line showing copy instead of an encoder name. Failing that, compare the results:
ffprobe -v error -show_entries format=duration,size,bit_rate -of default=nk=1 input.mp4 ffprobe -v error -show_entries format=duration,size,bit_rate -of default=nk=1 output.mp4
A remux changes the size slightly, container overhead differs, and leaves the bitrate essentially unchanged. A substantially different bitrate means the video was re-encoded, which was not what you asked for.