A video's metadata is not one thing, and no single command removes all of it. An MP4 keeps the picture in one box and the records about the file in several others, so "remove the metadata" is really a question about which boxes you are willing to rewrite. Measured on a 102,295-byte test file: a plain ffmpeg -c copy drops the C2PA provenance box and leaves all ten tags; adding -map_metadata -1 removes four of those ten; rewriting the container in place removes all ten and the provenance box as well. In every one of those methods the compressed video is byte-for-byte identical afterwards — 100,307 bytes with the same MD5 — because removing metadata is not a re-encode, whatever a tool may imply.
The tool below does the third of those. Everything quoted on this page is a real run on this machine, reproducible with the scripts named at the end.
This is the box list read straight out of the test file, not the list the format permits. An ISO base media file is a flat sequence of boxes at the top level, each with a size and a four-character type, and some of those boxes contain more boxes.
| Path | Size | What it holds |
|---|---|---|
ftyp | 32 B | The brand: which specification the file follows, and which readers it expects |
free | 8 B | Padding. Carries nothing, exists to keep other boxes aligned |
mdat | 100,315 B | Every frame of video and every sample of audio, compressed |
uuid | 153 B | The C2PA content credential — a signed record of origin |
moov | 1,787 B | The index: timing, track layout, and the offsets a player needs |
moov/mvhd | 108 B | Timescale and duration for the whole movie |
moov/trak | 1,475 B | One track: its handler, its sample table, its sample entry |
moov/udta | 196 B | User data — this is where descriptive metadata lives |
moov/udta/meta/ilst | 143 B | Four tags: (c)nam, (c)ART, (c)too, (c)cmt |
Note where the interesting things are not. There is no EXIF block, no XMP packet and no IPTC record — those are still-image structures. A video carries the equivalent information under different names in different places, which is why a tool built for photos finds nothing to remove here.
People search for this because they know what metadata did to their photos, and the honest answer is that a video does not store it the same way. The mapping is roughly this:
| What you want gone | Where a photo keeps it | Where a video keeps it |
|---|---|---|
| Location | A GPS IFD inside the EXIF block | A (c)xyz atom under moov/udta, holding coordinates as text |
| Creation time | DateTimeOriginal in the EXIF block | A timestamp in mvhd, plus a date tag in ilst |
| Device identity | Make, model and body serial number | The handler_name and vendor id on each track |
| The software used | A Software tag | A (c)too tag, plus a compressor name inside the sample entry |
| Provenance | A C2PA segment in APP11 | A C2PA uuid box at the top level |
The provenance row is the one that matches exactly: both formats put a C2PA record in a structure of its own, which is why it is the one that comes off cleanly in both. The still-image side, segment by segment →
Here is the same test file put through each method. The tag count is what ffprobe reports; the mdat line is the compressed video, taken from the bytes rather than from the tool that wrote them.
| Method | Size | C2PA box | Tags removed | mdat |
|---|---|---|---|---|
| Untouched | 102,295 B | present, 153 B | — | 100,307 B, 3b11cb33… |
ffmpeg -c copy | 102,142 B | gone | 0 of 10 | identical |
-c copy -map_metadata -1 | 102,043 B | gone | 4 of 10 | identical |
| In-place rewrite (this tool) | 102,295 B | gone | 10 of 10 | identical |
Three things in that table are worth pausing on, because each one contradicts something a metadata cleaner usually tells you.
The provenance box comes off whether you ask or not. A plain -c copy does not preserve the uuid box, because ffmpeg keeps the streams it understands and discards top-level boxes it does not. That is worth knowing in both directions: it is the fastest way to shed a credential, and it is how one disappears from a file somebody meant to keep it on.
Stripping the tags does not strip the software string. After -map_metadata -1 the file still reports encoder=Lavc63.1.101 libx264. The reason is that this string is not a tag at all — it lives at offset 100,984 inside the sample entry moov/trak/mdia/minf/stbl/stsd/avc1, as a fixed 32-byte compressor name field sitting next to the frame width and height. It is a field of a structure rather than a box, so no metadata flag can reach it. Clearing it means editing the sample entry, whose fixed header length depends on the track type, which is why this tool leaves it alone and names it here instead.
Nothing here is a re-encode. The mdat MD5 is the same string in all four rows. If a tool changes the picture while claiming to remove metadata, it is doing something else to your file.
Every method above changes the container. Two of them make the file shorter, which is the obvious thing to do and also the thing that can destroy it.
A player does not scan a video looking for frames. It reads stco inside moov, which is a list of absolute byte positions — "sample one starts at offset 40". Those are positions in the file itself. Delete a box that sits before mdat and every sample slides, while the table keeps the old numbers. The decoder then reads frames from the wrong bytes.
The C2PA box belongs right after ftyp and before moov, so it sits before the media. Inserting it there shifts the media by 158 bytes. On a test file where the offset table was left alone:
box inserted, offset table not corrected 0 of 72 frames decode same insertion, offset table corrected 72 of 72 frames decode
Zero frames is not a subtle artefact; it is a file that no longer plays. That is why this tool rewrites boxes in place instead of deleting them: the record is destroyed, the box no longer claims to be a credential, and no byte in the file changes position. The price is that the file does not shrink. The tool, and how to check its output →
Every number above comes from commands you can run on your own file. The tags:
ffprobe -v error -show_format -show_streams yourfile.mp4
The compressed video, so you can prove nothing was re-encoded:
ffmpeg -i original.mp4 -f framemd5 - > before.txt ffmpeg -i cleaned.mp4 -f framemd5 - > after.txt diff before.txt after.txt
And the box list, which is what tells you whether a credential was ever there:
python dev/video_meta_report.py yourfile.mp4
The scripts behind this page are dev/video_meta_report.py, dev/video_metadata_methods.py and dev/make_video_fixtures.py, and the tool itself is tested by _selftest/video.js across seven fixtures. Where a video watermark can hide, and which layer comes off →
Not in the same form, and this trips people up when they go looking. EXIF is a JPEG and TIFF structure. A video stores its records in ISO base media boxes instead, so the same information turns up in different places with different names: a location is a (c)xyz atom under moov/udta rather than a GPS IFD, a title is a (c)nam or an ilst entry, and the software that wrote the file is a (c)too tag plus a compressor name field. When ffprobe prints TAG: lines for a video, those are the box values being surfaced under familiar names, not EXIF.
Measured on a 102,295-byte test file: a plain ffmpeg -c copy drops the C2PA provenance box but leaves all ten tags. Adding -map_metadata -1 removes four of those ten. An in-place rewrite of the container removes all ten tag values and the provenance box. Nothing removes the ftyp brand fields, and nothing removes the compressor name inside the sample entry unless a tool edits that structure field by field.
It should not, and on this machine it does not. The compressed video sits in the mdat box, and every method tested here leaves mdat byte-for-byte identical: 100,307 bytes with the same MD5 before and after. That is the line between removing metadata and removing a watermark. If a tool re-encodes, the file gets smaller or softer and the picture changes; if it only edits the container, mdat does not move at all.
Because the chunk offset table stores absolute byte positions. The stco box inside moov lists where each sample starts in the file, as a raw offset. Delete a box that sits before mdat and every sample slides backwards while the table keeps the old numbers, so the decoder reads frames from the wrong bytes. Measured here: inserting the C2PA box where the format puts it, without correcting that table, left zero of 72 frames decodable. Correcting the table restored all 72.
The output was read back with ffprobe, which reports the same codec, resolution, stream count and duration, and every frame decoded to an identical MD5. Because nothing in the file changes position, there is no offset for a player to get wrong. That is the reason this tool rewrites boxes in place rather than deleting them: it costs the file-size reduction and buys back the guarantee that the index is still correct.
Yes, and it is worth insisting on. This is a byte-level edit of the container, so it needs no decoder, no encoder and no server — it runs in the page you are already on, and the file never leaves the machine. A site that asks you to upload a video before cleaning its metadata is sending your file somewhere to do arithmetic it could have done locally.