video-adsmetadataffmpeg

FFmpeg keeps your video. It drops the C2PA metadata Meta reads.

··10 min read
FFmpeg keeps your video. It drops the C2PA metadata Meta reads.

Your BFCM render chain probably ends with a crop to 9:16, a caption burn, and a logo stamp. If a clip in that chain came from an AI generator carrying Content Credentials, every one of those steps deletes them, and on October 30 that's a terms problem rather than a cosmetic one. Nothing in your logs will say so.

Quick answer: Resizing video removes C2PA metadata, because FFmpeg writes a brand new MP4 and does not carry the top-level uuid box that holds the Content Credentials manifest. The honest fixes are to leave the credentialed file unaltered, or to re-sign the altered output with the original declared as a parentOf ingredient, since copying the old box forward fails validation as assertion.bmffHash.mismatch. If you need the 9:16 reframe, caption and watermark steps to be an inspectable job instead of a command somebody typed at 1am, run them through FFmpeg Micro as one API call and keep the request body as the record of exactly what was applied.

Stripping that metadata is the specific act Meta now prohibits, so there are no removal recipes here.

What Meta's October 30 clause actually says

Meta published updated Commercial Terms and Self-Serve Ad Terms on October 8, 2026, effective October 30, 2026, with no opt-in step: continuing to advertise past that date is acceptance. Two sentences in the generative AI ad creative terms land on render pipelines. The advertiser is solely responsible for AI-generated creative, including what Meta's own Advantage+ and Ads Creative Studio tools produced, and must not alter or remove any watermark or content-authenticating metadata generated by AI.

That second clause reads like intent, but it's enforced against outputs. Nobody at Meta reads your shell history. They read a file that arrived without the credentials its generator put there.

Where Content Credentials live in an MP4

A C2PA manifest is not in the pixels and not in the normal metadata tags. Per the C2PA 2.4 specification, the manifest store is a JUMBF superbox labeled c2pa, wrapped in a top-level uuid box inside the ISOBMFF container. It sits as a sibling of ftyp, moov and mdat, which is why your usual inspection turns up nothing:

ffprobe -v error -show_entries format_tags -of json credentialed.mp4
{ "format": { "tags": {
  "major_brand": "isom",
  "minor_version": "512",
  "compatible_brands": "isomiso2avc1mp41",
  "encoder": "Lavf61.7.100"
} } }

Four harmless tags, no mention of provenance. ffprobe reports container and stream properties, so a manifest box it doesn't model is invisible. The fastest no-dependency presence test is a byte scan for the JUMBF label:

grep -abo c2pa credentialed.mp4 | head -3

Hits at low byte offsets mean a manifest store is physically present. No hits means nothing to preserve. Presence is not validity, though.

The manifest's hard binding is a c2pa.hash.bmff assertion computed over the asset's bytes with declared box exclusions. AWS documents the full structure in its MediaConvert manifest verification guide, including the exclusion list (/ftyp, /uuid, /free, a subset of /mdat, /moov, /mfra) and the failure code when the hash no longer matches: assertion.bmffHash.mismatch.

Which pipeline steps drop the manifest

Every FFmpeg operation that writes a file goes through a muxer, and the MP4 muxer builds a fresh box tree from the streams it was given. Boxes it doesn't recognize are dropped, so the manifest disappears with no error, no warning, and no visible change to the picture.

StepCommandWhat happens to the manifest
Full re-encode`ffmpeg -i in.mp4 -c:v libx264 -crf 20 out.mp4`Box dropped, and the frame bytes changed, so the BMFF hash couldn't match anyway
Container remux`ffmpeg -i in.mp4 -c copy out.mp4`Box dropped. Stream copy preserves the frames and still loses the credentials
Metadata strip`ffmpeg -i in.mp4 -map_metadata -1 -c copy out.mp4`Box dropped by the remux, not the flag. `-map_metadata -1` clears format and stream tags, never the `uuid` box
Reframe to 9:16`ffmpeg -i in.mp4 -vf "scale=-2:1920,crop=1080:1920" out.mp4`Box dropped, plus the crop alters the pixels any visual watermark lives in
Trim`ffmpeg -ss 2 -t 15 -i in.mp4 -c copy out.mp4`Box dropped, and `mdat` is a different length

The -map_metadata -1 row is the one most teams get backwards. Removal guides credit that flag with killing Content Credentials, which implies that omitting it preserves them. It doesn't. A plain -c copy remux with no metadata flags destroys the manifest just as completely.

No, you cannot copy the box forward

Lifting the uuid box out of the source and grafting it onto your 9:16 render does not produce a compliant file. The hard binding hashes the asset bytes, so a manifest attached to pixels it never signed validates as assertion.bmffHash.mismatch. A verifier reads that as tampering, a worse outcome than a file with no credentials at all. So the premise is wrong: you can't carry a signed manifest across a re-encode, you can only re-sign.

The two patterns that are actually compliant

Keep the credentialed deliverable unaltered, or sign a new manifest for the altered one. There's no third option, and the first is what most ads teams should pick this week.

Leaving the file alone is cheaper than it sounds. If a Sora or Firefly clip arrives signed and you upload that exact file as one of your variants, it stays compliant by definition. The variants that need cropping, rehooking and captioning can derive from an uncredentialed master or b-roll, and there's nothing to remove from a file that never carried a manifest. Treating the master clip as the thing you fan out from helps here, as in reframing a master clip instead of generating every variant.

Re-signing is the pattern Cloudflare Images implements for stills: keep the incoming credentials, append the transformation you applied, sign the result. AWS Elemental MediaConvert does the video equivalent and emits a manifest carrying a c2pa.transcoded action with the original declared as a parentOf ingredient. The cost of entry is a signing identity: MediaConvert signs only MP4 outputs and requires a KMS ECDSA_SHA_256 key plus a PEM certificate chain in Secrets Manager. Most ads teams have no certificate and no way to get one before Friday.

The honest boundary: FFmpeg Micro doesn't sign C2PA manifests, and neither does your FFmpeg binary. What the API changes is whether the altering step is accountable. The reframe is a JSON body you submitted, the job is listable later by status and date range, and the options are the record of what ran:

curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "inputs": [{ "url": "gs://<YOUR_BUCKET>/1730000000-master.mp4" }],
    "outputFormat": "mp4",
    "options": [
      { "option": "-vf", "argument": "scale=-2:1920,crop=1080:1920" },
      { "option": "-c:v", "argument": "libx264" },
      { "option": "-crf", "argument": "20" }
    ]
  }'

Billing is metered per second of input video with no rounding up to the minute, and failed jobs are never billed, so a pre-flight pass over 25 variants costs what the footage actually is.

The check to run before you upload

Inspect input and output with the same tool and compare. The C2PA project's c2patool reads MP4 and MOV, and --info prints the manifest store size and its validation state.

  1. Run c2patool master.mp4 --info on the source. No manifest means the file is out of scope and you can render freely.
  2. If one exists, pick which compliant pattern applies before you queue the render.
  3. Run your render, then c2patool variant_9x16.mp4 --info on the output.
  4. Add --detailed for the JUMBF-level view, including the assertions and the box exclusion list behind the hard binding.
  5. Keep both outputs next to the job ID, and pair them with /v1/ffprobe for the spec audit of codec, dimensions and frame rate. ffprobe answers "is it at spec", c2patool answers "are the credentials intact".

Meta re-encodes your upload anyway, so what are you responsible for?

Meta reads industry provenance signals at upload, C2PA manifests and IPTC DigitalSourceType among them, to decide whether to apply its AI info label, then transcodes the file for delivery, which discards the manifest from what viewers download. The clause binds your conduct, not the manifest surviving Meta's CDN. You're responsible for what you did to the file before it got there, which is why a documented render step beats an undocumented one.

The clause covers watermarks as well as metadata, and those fail differently. Google's Veo marks output with SynthID in the pixels rather than in a container box, and SynthID is built to survive trimming, compression and modest cropping. A 9:16 reframe of a Veo clip won't remove the watermark the way it removes a manifest, so a Veo-sourced variant survives a crop a C2PA-signed one doesn't.

Common pitfalls

Non-compliant renders come out of six habits, and all of them look fine on screen.

  • Treating ffprobe's silence as proof. ffprobe shows no C2PA information even on a fully credentialed file.
  • Blaming -map_metadata -1. Omitting that flag preserves nothing. The remux dropped the box.
  • Grafting the old uuid box onto a new render. That produces assertion.bmffHash.mismatch, which reads as tampering rather than missing data.
  • Checking only the final deliverable. A generate, reframe, caption chain loses the manifest at step two, and an end-to-end check can't tell you which step did it.
  • Assuming the platform re-encode excuses the step. The clause binds your actions, not the bytes Meta serves.
  • Reading pixel watermark survival as metadata survival. Separate mechanisms, separate failure modes, and the clause names both.

FAQ

Does cropping a video to 9:16 remove C2PA content credentials?

Cropping to 9:16 removes C2PA content credentials, because the crop forces a re-encode and the MP4 muxer writes a new container without the uuid box the manifest lived in. The crop also changes the asset bytes the c2pa.hash.bmff binding covers, so reattaching the original manifest fails validation.

Can FFmpeg preserve C2PA metadata through a transcode?

FFmpeg cannot preserve a C2PA manifest through a transcode. FFmpeg has no C2PA muxing support, and a signed manifest is cryptographically bound to the input bytes. The only compliant route for an altered render is a newly signed manifest declaring the original as a parentOf ingredient and the edit as a c2pa.transcoded action.

How do I check whether my output file still has Content Credentials?

Run c2patool output.mp4 --info, which reports the manifest store size and validation state for MP4 and MOV files, and add --detailed for the assertion-level view. For a presence test with no extra tooling, grep -abo c2pa output.mp4 finds the JUMBF label if a manifest store is in the file.

Which AI video generators embed C2PA in video files?

Adobe Firefly and OpenAI's Sora have shipped C2PA Content Credentials in their video output, while Google's Veo marks output with SynthID in the pixels instead. Meta's October 30, 2026 clause covers both watermarks and content-authenticating metadata, so check each source clip rather than assuming by vendor.

Is it safe to add captions or a watermark to an AI-generated ad?

Adding captions or a watermark to an AI-generated ad is safe when the source clip carries no C2PA manifest, which covers most footage in a typical ads library. When the source is credentialed, burn captions and stamp watermarks on an uncredentialed master and upload the credentialed file unaltered as its own variant.

Reframing, captioning and watermarking for Meta placements is the job the video ads use case is built around, and each render lands as a job record you can point at during an audit. A free account gets 200 tokens, roughly 33 minutes of video, enough to run your BFCM set through one pass before the 30th.

About Javid Jamae

Founder & CEO at FFmpeg Micro

Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.

Software EngineeringVideo ProcessingFFmpegCloud ArchitectureAPI DesignAutomation

Ready to process videos at scale?

Start using FFmpeg Micro's simple API today. No infrastructure required.

Get Started Free