If you have a video file and you want the same video without sound, the correct operation is not a re-encode. It is a container-level track drop. The video stream stays byte-for-byte identical, the audio stream is discarded, and the operation runs at disk speed.
Most "mute video" tools re-encode the video anyway. That is slower and lossy, and it is unnecessary for any MP4, MOV, MKV, or similar container. Here is what the operation actually looks like.
The core idea
A modern video container holds streams. An MP4 might carry a video stream, a stereo audio stream, and a metadata track. Each stream is independent inside the container; the container's moov atom (or Matroska equivalent) references each one separately.
Removing audio means:
- Read the container's stream table.
- Skip the audio streams when writing the output.
- Copy the video stream's samples through unchanged.
- Write a new container with only the video stream registered.
Nothing decodes. Nothing re-encodes. The output video is bit-identical to the input at the sample level.
The ffmpeg one-liner
On the command line:
ffmpeg -i input.mp4 -c copy -an output.mp4
-c copy copies every stream through without re-encoding, and -an drops the audio. Runs at whatever your disk can read and write; for a two-hour movie on an SSD, about ten seconds.
The common mistake is dropping the -c copy flag. Without it, ffmpeg defaults to re-encoding, which takes minutes and loses quality:
# Wrong: takes 30 minutes for a movie and produces a worse file
ffmpeg -i input.mp4 -an output.mp4
The browser equivalent
ffmpeg-wasm ships the same behavior for browser use:
import { FFmpeg } from '@ffmpeg/ffmpeg';
import { fetchFile } from '@ffmpeg/util';
const ffmpeg = new FFmpeg();
await ffmpeg.load();
await ffmpeg.writeFile('input.mp4', await fetchFile(inputFile));
await ffmpeg.exec(['-i', 'input.mp4', '-c', 'copy', '-an', 'output.mp4']);
const data = await ffmpeg.readFile('output.mp4');
Same flags, same behavior. Runs entirely in the tab through WebAssembly, so the video never leaves the machine. On a modern laptop the operation is bounded by disk IO, not CPU, so it finishes in seconds.
What does not work
Some tools try to mute by setting the audio track's volume to zero, or by writing silence over the audio samples. Both are wasteful: the audio track is still in the file, it still takes up space, and any player will still allocate a decode buffer for it. Muting is not the same as removing.
Some tools decode the audio to silence and re-encode it. Same problem: the file still has an audio track that is doing nothing.
The right operation is a proper track drop at the container level.
When you cannot use -c copy
If your source is a live stream (HLS, RTMP) or a partial file, -c copy may need the container's index to be fully written before it can copy through. In that case, either wait for the recording to finish, or accept a real re-encode for the muted output.
If you need to remove audio from only part of the video (mute the first ten seconds, keep audio for the rest), that is a re-encode of the whole file. There is no way to selectively drop samples without re-encoding.
The one-click version
If you do not want to install ffmpeg locally, Wave's remove-audio-from-video tool does the same operation in the browser. Drop the video, download an MP4 without the audio track. The file stays on your machine, and the operation is a real track drop, not a re-encode.
Summary
Removing audio from a video is a container operation, not a codec operation. Use -c copy -an on the command line or the browser tool that runs the same flags. Any tool that takes minutes to do this is doing the wrong operation, and the output will be worse than the input for no reason.
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.