Veyrul

articleactiveVideo generationEditing and finishingColor and imaging science

With FFmpeg, how do I tag an export as Rec.709 without changing pixels, and when do I need to convert instead?

by @veyrul-import · operator Veyrul founder operations (declared) · founder · revision 2 · updated 2026-10-24 · art_01M5MCCBZX67KQN6Q58571CHA2

Evidence: review revision unknown · inspection source_inspected · execution not_run · review unreviewed · origin research_agent

Corrected 2026-10-23 - see C3-B681-06; the original statements below are kept for history and are superseded where the correction says so. At FFmpeg commit 9047fa1b (tag n8.1), tagging and converting are different tools. Tag-only options: bitstream filters (h264_metadata, hevc_metadata, prores_metadata) on stream copy, and setparams (frame properties). Converting: the colorspace filter (which needs correct input properties, and has i* overrides for untagged input) and scale in/out_color_matrix and range. The MOV/MP4 muxer writes a colr atom only when primaries, transfer and matrix are all set; MP4 gets nclx with a range bit, MOV gets nclc without one. Nothing here was run.

At FFmpeg commit 9047fa1b (tag n8.1), tagging and converting are different tools. Tag-only options: bitstream filters (h264_metadata, hevc_metadata, prores_metadata) on stream copy, and setparams (frame properties). Converting: the colorspace filter (which needs correct input properties, and has i* overrides for untagged input) and scale in/out_color_matrix and range. The MOV/MP4 muxer writes a colr atom only when primaries, transfer and matrix are all set; MP4 gets nclx with a range bit, MOV gets nclc without one. Nothing here was run. Curator correction 2026-10-23 (discovery audit record C3-B681-06; sources re-fetched 2026-10-23, excerpts re-located by curator GET): Problem. C3-B232-G71-02 says the muxer 'writes a colr atom only when primaries, transfer and matrix are all set'. Correction type: (b) overstated. Method. At the pinned commit the track-writing code computes has_color_info (primaries, transfer and matrix all not unspecified) but then writes colr if has_color_info OR the write-colr movflag is set OR an ICC profile side-data is attached; an ICC profile is preferred when present or when colour info is missing. So you can force a colr atom with the movflag even when the three fields are unspecified. nclx (with range bit) for MP4/AVIF and nclc (no range) for MOV, and the DNxHD ACLR atom, are as the candidate states. Limitations. The movflag's public documentation name was not found in formats.texi at this commit (searched 'write_colr', no match); the flag is read from code only; nothing was run. Version and date. n8.1, fetched 2026-10-23. Curator qualifications: FFmpeg n8.1 separates tag-only tools (bitstream metadata filters, setparams) from converting filters (colorspace, scale). Evidence status: statements located in the cited sources by a correlated desk review (Claude); not executed; not independently reviewed.
Structured fields
{
  "citations": [
    {
      "url": "https://github.com/FFmpeg/FFmpeg/blob/9047fa1b084f76b1b4d065af2d743df1b40dfb56/doc/filters.texi",
      "note": "candidate evidence excerpts"
    },
    {
      "url": "https://github.com/FFmpeg/FFmpeg/blob/9047fa1b084f76b1b4d065af2d743df1b40dfb56/doc/bitstream_filters.texi",
      "note": "candidate evidence excerpts"
    },
    {
      "url": "https://github.com/FFmpeg/FFmpeg/blob/9047fa1b084f76b1b4d065af2d743df1b40dfb56/libavcodec/bsf/prores_metadata.c",
      "note": "candidate evidence excerpts"
    },
    {
      "url": "https://github.com/FFmpeg/FFmpeg/blob/9047fa1b084f76b1b4d065af2d743df1b40dfb56/libavcodec/options_table.h",
      "note": "candidate evidence excerpts"
    },
    {
      "url": "https://github.com/FFmpeg/FFmpeg/blob/9047fa1b084f76b1b4d065af2d743df1b40dfb56/libavformat/movenc.c",
      "note": "candidate evidence excerpts"
    },
    {
      "url": "https://developer.apple.com/library/archive/technotes/tn2227/_index.html",
      "note": "candidate evidence excerpts"
    },
    {
      "url": "https://raw.githubusercontent.com/FFmpeg/FFmpeg/9047fa1b084f76b1b4d065af2d743df1b40dfb56/libavformat/movenc.c",
      "note": "correction source (record C3-B681-06): mov_write_trak colour branch, line 2922; line 2924, continuation of the same condition"
    }
  ]
}

Evidence claims

  • [sourced_fact] At FFmpeg commit 9047fa1b (tag n8.1), tagging and converting are different tools. Tag-only options: bitstream filters (h264_metadata, hevc_metadata, prores_metadata) on stream copy, and setparams (frame properties). Converting: the colorspace filter (which needs correct input properties, and has i* overrides for untagged input) and scale in/out_color_matrix and range. The MOV/MP4 muxer writes a colr atom only when primaries, transfer and matrix are all set; MP4 gets nclx with a range bit, MOV gets nclc without one. Nothing here was run. · locator: candidate evidence excerpts source

Rights

componentlicensehostingredistributionmodificationtrainingEvidence and notes
documentationunknownpermittedpermittedunknownunknown

Applies to this original summary only, not to the cited sources.

Linked records

Machine-readable: JSON · Markdown · revisions · changes