Strip Video Metadata with FFmpeg: Complete Guide

March 9, 2026 ยท RenderIO

Video files contain more data than you think

You can strip video metadata with FFmpeg in one command. But knowing what to strip, what to keep, and how platforms react to a fully clean file takes more understanding than the command itself.

Every MP4 carries more than just video and audio streams: creation timestamps, GPS coordinates from where it was filmed, the software that encoded it, camera model, color profile, and chapter markers.

This metadata is useful for organization. It's a liability for privacy and content detection. Platforms use it to identify content origin, flag AI generation, and match duplicates across uploads. If you're posting content at scale, metadata is the first thing to deal with. For related techniques around changing video hashes and avoiding duplicate detection, those guides go deeper into fingerprinting.

What metadata exists in video files

Container-level metadata (format tags)

These live in the MP4/MKV container, not in the streams:

encoder: Lavf60.3.100
creation_time: 2026-02-10T14:30:00.000000Z
title: My Video
comment: Edited in Premiere Pro
description: Product demo
copyright: 2026 Company Inc.

The encoder tag is the most common tell. Every FFmpeg output writes Lavf... here by default. Premiere writes its own identifier. DaVinci Resolve writes another. Platforms can infer your entire workflow from this single field.

Stream-level metadata

Each audio and video stream has its own metadata:

# Video stream
handler_name: VideoHandler
encoder: Lavc60.3.100 libx264
creation_time: 2026-02-10T14:30:00.000000Z

# Audio stream
handler_name: SoundHandler
encoder: aac
creation_time: 2026-02-10T14:30:00.000000Z
language: eng

Stream-level encoder tags survive even when you strip container-level metadata. You need to target them separately, covered in the stripping methods below.

Extended metadata (XMP, EXIF)

Some files contain embedded XMP or EXIF data:

  • GPS coordinates: latitude/longitude where the video was recorded

  • Camera info: make, model, lens, exposure settings

  • Software: editing tools used

  • Timestamps: creation, modification, and encoding times

  • Copyright: creator information

  • AI credentials: C2PA Content Credentials (if AI-generated)

C2PA Content Credentials

C2PA is a provenance standard backed by Adobe, Microsoft, and others. It embeds a cryptographically signed record of how content was created, including whether an AI model generated it. Tools like Adobe Firefly, DALL-E, and some video generators attach C2PA manifests automatically.

FFmpeg's -map_metadata -1 removes most metadata, but C2PA manifests are embedded differently (as XMP or as a separate JUMBF box in the container). The nuclear option, re-encoding the entire file, destroys C2PA data because it creates a completely new file with no structural connection to the original.

For a deeper look at removing AI metadata specifically, including C2PA and invisible watermarks, see that guide.

Viewing metadata with ffprobe

See all metadata

ffprobe -v quiet -print_format json -show_format -show_streams input.mp4

This outputs a JSON object with all format and stream metadata. Look at the tags sections. For a full walkthrough of ffprobe's output formats, field extraction, and scripting patterns, see the ffprobe tutorial.

Just format tags

ffprobe -v quiet -show_entries format_tags input.mp4

Just stream tags

ffprobe -v quiet -show_entries stream_tags input.mp4

Everything including chapters

ffprobe -v quiet -show_format -show_streams -show_chapters input.mp4

ExifTool comparison

FFmpeg's ffprobe shows container and stream metadata. ExifTool (exiftool video.mp4) shows more: it reads XMP, EXIF, and embedded thumbnail data that ffprobe misses. If you're doing thorough metadata audits, use both:

# FFmpeg view
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4

# ExifTool view (catches XMP, EXIF, GPS that ffprobe might miss)
exiftool -json input.mp4

ExifTool also strips metadata, but its video support is limited to metadata containers (it can't re-encode). FFmpeg handles both the metadata and the stream content.

Stripping metadata with FFmpeg

Method 1: Strip everything (keep streams intact)

ffmpeg -i input.mp4 -map_metadata -1 -c:v copy -c:a copy output.mp4

Removes all format-level metadata. Fast because it copies streams without re-encoding. But stream-level metadata (like the encoder tag on the video track) survives.

Method 2: Strip everything including stream metadata

ffmpeg -i input.mp4 \
  -map_metadata -1 \
  -map_metadata:s:v -1 \
  -map_metadata:s:a -1 \
  -c:v copy -c:a copy \
  output.mp4

-map_metadata:s:v -1 strips video stream metadata. -map_metadata:s:a -1 strips audio stream metadata. This is more thorough than Method 1.

Method 3: Strip everything and prevent FFmpeg from adding its own

ffmpeg -i input.mp4 \
  -map_metadata -1 \
  -map_metadata:s:v -1 \
  -map_metadata:s:a -1 \
  -fflags +bitexact \
  -flags:v +bitexact \
  -flags:a +bitexact \
  -c:v copy -c:a copy \
  output.mp4

-fflags +bitexact prevents FFmpeg from writing its own encoder tag. Without this flag, FFmpeg adds encoder: Lavf... to the output, which defeats the purpose. This is the recommended method for privacy-focused stripping.

Method 4: Re-encode (destroys everything)

ffmpeg -i input.mp4 \
  -map_metadata -1 \
  -fflags +bitexact \
  -c:v libx264 -crf 22 \
  -c:a aac -b:a 128k \
  output.mp4

Re-encoding creates a completely new file. No metadata from the original can survive: not container tags, not stream tags, not C2PA manifests, not embedded XMP. This is the most thorough approach but takes longer and introduces a generation of quality loss (minimal at CRF 22). For more on video compression settings and what CRF values mean, see that guide.

What platforms do with metadata

TikTok

TikTok reads creation timestamps, encoder tags, and checks for C2PA AI credentials. It also uses metadata as one input to its duplicate content detection system. Stripping metadata alone won't make a video unique because TikTok uses perceptual hashing on the actual frames. But leaving AI generation metadata intact guarantees it gets flagged.

Instagram

Instagram strips most metadata on upload but reads it during processing. GPS data and creation timestamps influence how content is categorized internally. The encoder tag doesn't affect distribution, but AI credentials may trigger reduced reach.

YouTube

YouTube preserves some metadata in its internal systems even after re-encoding your upload. Location data appears in YouTube Studio. Creation dates affect "upload vs. creation" sorting. YouTube also participates in the C2PA ecosystem and may surface AI provenance labels.

Selective metadata removal

Sometimes you want to keep some metadata and remove the rest.

Keep title, remove everything else

ffmpeg -i input.mp4 -map_metadata -1 -metadata title="My Video Title" -c:v copy -c:a copy output.mp4

Replace metadata with specific values (privacy use case)

For privacy-sensitive content, you might want to set a generic creation time and remove everything else:

ffmpeg -i input.mp4 \
  -map_metadata -1 \
  -fflags +bitexact \
  -metadata creation_time="2026-02-10T10:00:00.000000Z" \
  -c:v copy -c:a copy \
  output.mp4

This is useful when you need a valid timestamp (some platforms reject files without one) but don't want the real recording time exposed. Common for journalists protecting sources and businesses sanitizing internal footage before public release.

Remove GPS but keep everything else

FFmpeg doesn't support removing individual tags. The workaround:

# Step 1: Note the metadata you want to keep
ffprobe -v quiet -show_entries format_tags=title,artist input.mp4

# Step 2: Strip everything and re-add what you need
ffmpeg -i input.mp4 \
  -map_metadata -1 \
  -metadata title="My Video" \
  -metadata artist="Creator Name" \
  -c:v copy -c:a copy \
  output.mp4

Verifying metadata removal

After stripping, always verify:

ffprobe -v quiet -print_format json -show_entries format_tags output.mp4

ffprobe -v quiet -print_format json -show_entries stream_tags output.mp4

For a comprehensive check:

ffprobe -v quiet -print_format json -show_format -show_streams output.mp4 | python3 -c "
import json, sys
data = json.load(sys.stdin)
tags = data.get('format', {}).get('tags', {})
if tags:
    print(f'Format tags found: {tags}')
else:
    print('No format tags')
for i, stream in enumerate(data.get('streams', [])):
    stags = stream.get('tags', {})
    if stags:
        print(f'Stream {i} tags: {stags}')
    else:
        print(f'Stream {i}: no tags')
"

Expected output after thorough stripping:

No format tags
Stream 0: no tags
Stream 1: no tags

If you stripped with Method 3 (bitexact flags) and tags still show up, you likely have embedded XMP data that ffprobe doesn't display but ExifTool catches. Run exiftool output.mp4 to check. If XMP survives, re-encode with Method 4.

API calls for metadata stripping

Quick strip (copy streams)

curl -X POST https://renderio.dev/api/v1/run-ffmpeg-command \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: your_api_key" \
  -d '{
    "ffmpeg_command": "-i {{in_video}} -map_metadata -1 -map_metadata:s:v -1 -map_metadata:s:a -1 -fflags +bitexact -c:v copy -c:a copy {{out_video}}",
    "input_files": { "in_video": "https://example.com/video.mp4" },
    "output_files": { "out_video": "clean.mp4" }
  }'

Fast. No re-encoding. Removes all metadata.

Thorough strip (re-encode)

curl -X POST https://renderio.dev/api/v1/run-ffmpeg-command \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: your_api_key" \
  -d '{
    "ffmpeg_command": "-i {{in_video}} -map_metadata -1 -fflags +bitexact -c:v libx264 -crf 22 -c:a aac -b:a 128k {{out_video}}",
    "input_files": { "in_video": "https://example.com/video.mp4" },
    "output_files": { "out_video": "clean.mp4" }
  }'

Takes longer. Destroys all structural metadata including anything embedded in the stream encoding. For making AI video undetectable on TikTok, this is the recommended starting point.

Batch metadata stripping

Process multiple files via the API:

import requests

API_KEY = "ffsk_your_key"
HEADERS = {"Content-Type": "application/json", "X-API-KEY": API_KEY}

videos = [
    "https://storage.example.com/video1.mp4",
    "https://storage.example.com/video2.mp4",
    "https://storage.example.com/video3.mp4",
    "https://storage.example.com/video4.mp4",
    "https://storage.example.com/video5.mp4",
]

from concurrent.futures import ThreadPoolExecutor, as_completed

def submit_job(i, url):
    res = requests.post(
        "https://renderio.dev/api/v1/run-ffmpeg-command",
        headers=HEADERS,
        json={
            "ffmpeg_command": "-i {{in_video}} -map_metadata -1 -map_metadata:s:v -1 -map_metadata:s:a -1 -fflags +bitexact -c:v copy -c:a copy {{out_video}}",
            "input_files": {"in_video": url},
            "output_files": {"out_video": f"clean_{i+1}.mp4"}
        }
    )
    return res.json()["command_id"]

command_ids = []
with ThreadPoolExecutor(max_workers=10) as executor:
    futures = {executor.submit(submit_job, i, url): i for i, url in enumerate(videos)}
    for future in as_completed(futures):
        cmd_id = future.result()
        command_ids.append(cmd_id)
        print(f"Submitted: {cmd_id}")

Submitting jobs in parallel with ThreadPoolExecutor keeps network round-trips from serializing. Since stream copy is used (-c:v copy -c:a copy), each job runs in seconds on the API side regardless of video length. With 10 concurrent submissions, a batch of 100 videos is submitted in a few seconds and all jobs process concurrently.

Privacy considerations

Metadata can contain sensitive information:

  • GPS coordinates reveal filming locations (home, office, client sites)

  • Device serial numbers in some cameras identify specific hardware

  • Timestamps reveal when you were filming and your timezone

  • Software tags reveal your entire editing workflow

  • Creation dates combined with GPS data can place you at a specific location at a specific time

For privacy-sensitive content going to public platforms, always strip metadata. For legal or forensic contexts (evidence, documentation), keep it. Metadata proves provenance and chain of custody.

When NOT to strip metadata

  • Professional delivery: Clients may expect metadata for organization and archival

  • Legal evidence: Metadata proves when/where video was recorded

  • Accessibility: Language tags help platforms serve correct subtitles

  • Archival: Metadata helps catalog and search video libraries

  • GDPR compliance audits: Keeping metadata about what was stripped and when can satisfy audit requirements

Be intentional about what you remove and why. Blanket stripping is right for social media posting. It's wrong for legal, archival, and professional delivery contexts.

FAQ

Does stripping metadata make a video unique for platform detection?

No. Platforms like TikTok use perceptual hashing on the actual video frames, not metadata. Stripping metadata removes one identification vector, but the visual content is still fingerprinted. For true uniqueness, you need to modify the video itself: cropping, color adjustments, overlays. The making videos unique guide covers the techniques.

What's the difference between FFmpeg and ExifTool for metadata stripping?

FFmpeg handles both metadata removal and video re-encoding in one tool. ExifTool is metadata-only. It reads and writes more metadata formats (XMP, EXIF, IPTC) but can't re-encode video. Use FFmpeg for production stripping and ExifTool for auditing what's left afterward.

Does re-encoding always destroy all metadata?

Re-encoding with -map_metadata -1 -fflags +bitexact destroys format tags, stream tags, and structural metadata. However, if the original has XMP embedded as a separate atom in the container, FFmpeg might copy it during muxing. Always verify with ffprobe and ExifTool after stripping.

Can platforms detect that metadata was stripped?

They can infer it. A video file with zero metadata (no encoder tag, no creation time, no handler names) is unusual. Most consumer devices always write metadata. A completely clean file suggests deliberate stripping. Whether platforms penalize this is unclear and likely varies.

How do I strip metadata from hundreds of local files?

Use a shell loop with FFmpeg:

for f in *.mp4; do
  ffmpeg -i "$f" -map_metadata -1 -map_metadata:s:v -1 -map_metadata:s:a -1 \
    -fflags +bitexact -c:v copy -c:a copy "clean_${f}"
done

This processes each file in seconds since it copies streams without re-encoding. For cloud-based batch processing, the Python API example above handles remote files.