Skip to content

vsmuxtools.video.clip_metadata

HDR10Metadata pydantic-model

HDR10Metadata(*, primaries: _Primaries | None = None, white_point: _XY | None = None, min_luminance: float | None = None, max_luminance: float | None = None, max_cll: int | None = None, max_fall: int | None = None)

Bases: BaseModel

Static HDR10 mastering-display and content-light metadata.

Every value is optional, but fields belonging to one metadata group must be supplied together. Coordinates are stored as normalized xy values and luminance values are stored in nits.

Parameters:

Name Type Description Default
primaries _Primaries | None

RGB primaries in (x, y) order, as R, G, B.

None
white_point _XY | None

Display white point as a normalized (x, y) pair.

None
min_luminance float | None

Minimum mastering-display luminance in nits.

None
max_luminance float | None

Maximum mastering-display luminance in nits.

None
max_cll int | None

Maximum content light level in nits.

None
max_fall int | None

Maximum frame-average light level in nits.

None
Show JSON schema:
{
  "additionalProperties": false,
  "description": "Static HDR10 mastering-display and content-light metadata.\n\nEvery value is optional, but fields belonging to one metadata group must\nbe supplied together.  Coordinates are stored as normalized xy values and\nluminance values are stored in nits.\n\n:param primaries: RGB primaries in ``(x, y)`` order, as R, G, B.\n:param white_point: Display white point as a normalized ``(x, y)`` pair.\n:param min_luminance: Minimum mastering-display luminance in nits.\n:param max_luminance: Maximum mastering-display luminance in nits.\n:param max_cll: Maximum content light level in nits.\n:param max_fall: Maximum frame-average light level in nits.",
  "properties": {
    "primaries": {
      "anyOf": [
        {
          "maxItems": 3,
          "minItems": 3,
          "prefixItems": [
            {
              "maxItems": 2,
              "minItems": 2,
              "prefixItems": [
                {
                  "maximum": 1,
                  "minimum": 0,
                  "type": "number"
                },
                {
                  "maximum": 1,
                  "minimum": 0,
                  "type": "number"
                }
              ],
              "type": "array"
            },
            {
              "maxItems": 2,
              "minItems": 2,
              "prefixItems": [
                {
                  "maximum": 1,
                  "minimum": 0,
                  "type": "number"
                },
                {
                  "maximum": 1,
                  "minimum": 0,
                  "type": "number"
                }
              ],
              "type": "array"
            },
            {
              "maxItems": 2,
              "minItems": 2,
              "prefixItems": [
                {
                  "maximum": 1,
                  "minimum": 0,
                  "type": "number"
                },
                {
                  "maximum": 1,
                  "minimum": 0,
                  "type": "number"
                }
              ],
              "type": "array"
            }
          ],
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Primaries"
    },
    "white_point": {
      "anyOf": [
        {
          "maxItems": 2,
          "minItems": 2,
          "prefixItems": [
            {
              "maximum": 1,
              "minimum": 0,
              "type": "number"
            },
            {
              "maximum": 1,
              "minimum": 0,
              "type": "number"
            }
          ],
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "White Point"
    },
    "min_luminance": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Min Luminance"
    },
    "max_luminance": {
      "anyOf": [
        {
          "exclusiveMinimum": 0,
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Max Luminance"
    },
    "max_cll": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Max Cll"
    },
    "max_fall": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Max Fall"
    }
  },
  "title": "HDR10Metadata",
  "type": "object"
}

Config:

  • frozen: True
  • extra: forbid
  • allow_inf_nan: False

Fields:

  • primaries (_Primaries | None)
  • white_point (_XY | None)
  • min_luminance (float | None)
  • max_luminance (float | None)
  • max_cll (int | None)
  • max_fall (int | None)

Validators:

  • _validate_groups

from_clip classmethod

from_clip(clip: VideoNode) -> HDR10Metadata

Read static HDR10 metadata from the first frame of clip.

Incomplete or invalid automatic groups are omitted. Frame properties are read as-is; no mastering values are inferred from colour signals.

Parameters:

Name Type Description Default
clip VideoNode

Video clip whose first frame contains the metadata.

required

Returns:

Type Description
HDR10Metadata

Metadata groups that are complete and valid on frame zero.

Source code in vsmuxtools/video/clip_metadata.py
@classmethod
def from_clip(cls, clip: vs.VideoNode) -> "HDR10Metadata":
    """Read static HDR10 metadata from the first frame of ``clip``.

    Incomplete or invalid automatic groups are omitted.  Frame properties
    are read as-is; no mastering values are inferred from colour signals.

    :param clip: Video clip whose first frame contains the metadata.
    :return: Metadata groups that are complete and valid on frame zero.
    """

    props = clip.get_frame(0).props
    metadata: dict[str, object] = {}
    primary_x: Any = props.get("MasteringDisplayPrimariesX")
    primary_y: Any = props.get("MasteringDisplayPrimariesY")
    try:
        mastering = cls.model_validate(
            {
                "primaries": tuple(zip(primary_x, primary_y, strict=True)),
                "white_point": (props.get("MasteringDisplayWhitePointX"), props.get("MasteringDisplayWhitePointY")),
                "min_luminance": props.get("MasteringDisplayMinLuminance"),
                "max_luminance": props.get("MasteringDisplayMaxLuminance"),
            }
        )
    except (TypeError, ValueError):
        pass
    else:
        metadata.update(mastering.model_dump(exclude_none=True))

    try:
        levels = cls.model_validate(
            {
                "max_cll": props.get("ContentLightLevelMax"),
                "max_fall": props.get("ContentLightLevelAverage"),
            }
        )
    except (TypeError, ValueError):
        pass
    else:
        metadata.update(levels.model_dump(exclude_none=True))

    return cls.model_validate(metadata)

hdr10_args

hdr10_args(clip: VideoNode, *, x265: bool, hdr10: HDR10Metadata | bool = True, existing_args: list[str] | None = None) -> list[str]

Build additional static HDR10 encoder arguments, respecting explicit settings.

Parameters:

Name Type Description Default
clip VideoNode

Output clip being encoded.

required
x265 bool

Select x265 syntax when true, or SVT-AV1 syntax otherwise.

required
hdr10 HDR10Metadata | bool

Automatic metadata, an explicit metadata override, or false to disable it.

True
existing_args list[str] | None

Existing expanded CLI arguments to inspect for explicit settings.

None

Returns:

Type Description
list[str]

Missing HDR10 arguments to append to the encoder command.

Source code in vsmuxtools/video/clip_metadata.py
def hdr10_args(
    clip: vs.VideoNode,
    *,
    x265: bool,
    hdr10: HDR10Metadata | bool = True,
    existing_args: list[str] | None = None,
) -> list[str]:
    """Build additional static HDR10 encoder arguments, respecting explicit settings.

    :param clip: Output clip being encoded.
    :param x265: Select x265 syntax when true, or SVT-AV1 syntax otherwise.
    :param hdr10: Automatic metadata, an explicit metadata override, or false to disable it.
    :param existing_args: Existing expanded CLI arguments to inspect for explicit settings.
    :return: Missing HDR10 arguments to append to the encoder command.
    """

    existing_args = existing_args or []
    args: list[str] = []
    if hdr10 is False:
        return args
    if not isinstance(hdr10, (bool, HDR10Metadata)):
        raise error("hdr10 must be a bool or HDR10Metadata", hdr10_args)

    metadata = hdr10 if isinstance(hdr10, HDR10Metadata) else HDR10Metadata.from_clip(clip)

    display_option = "--master-display" if x265 else "--mastering-display"
    display_value = _master_display_text(metadata, x265)
    if display_value is not None and not _has_arg(existing_args, (display_option,)):
        args.extend([display_option, display_value])

    light_option = "--max-cll" if x265 else "--content-light"
    light_value = _light_level_text(metadata)
    if light_value is not None and not _has_arg(existing_args, (light_option,)):
        args.extend([light_option, light_value])

    return args