mpv-player / mpv-player/mpv

Add --sub-sdr-peak for independent SDR subtitle luminance

Open
#18,487 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

meta:feature-request
Dominant language
C
Stars
37k
Forks
3.5k
Avg merge
1d 10h
Merged PRs (30d)
22

Description

Expected behavior of the wanted feature

Background
--sub-hdr-peak provides a useful way to control subtitle luminance without changing the subtitle's nominal RGB/color values. For example: sub-hdr-peak=100allows white subtitle text to be rendered at a lower diffuse-white luminance while remaining nominally white, rather than requiring sub-color to change the RGB value.

However, with --sub-hdr-peak recent commits changed this to an HDR-output option. With the current vo=gpu-next implementation, it is only applied when the source video has an HDR transfer function.

This leaves no equivalent control for SDR subtitles when rendering SDR video.

Requested feature
add --sub-sdr-peak=<auto|sdr|10-10000> to control the diffuse-white luminance of text subtitles and OSD when their subtitle colorspace is SDR.

The semantics could mirror --sub-hdr-peak:

  • auto (default): preserve the current behavior.
  • sdr: use the standard SDR reference white (203 cd/m²).
  • A numeric value: use that value in cd/m² as the subtitle diffuse-white level.

For example: sub-sdr-peak=100 would cause nominally white subtitle text (RGB 1.0, 1.0, 1.0) to be rendered at 100 nits, rather than changing the subtitle RGB to something like #b0b0b0.

This is useful for users who want to reduce subtitle brightness while preserving subtitle colors and ASS styling.

Why not use sub-color?
sub-color changes the actual RGB value of the subtitle. sub-color=#aaaaaa is not equivalent to assigning a lower luminance to white subtitle RGB. In particular, changing the RGB value can affect colored subtitles, ASS styles, and the intended relationship between subtitle colors.

--sub-sdr-peak would instead control the color-space/luminance interpretation of the subtitle, analogous to the existing HDR option.

Proposed implementation
The existing libass_overlay_color() already constructs a pl_color_space for the subtitle and uses color.hdr.max_luma to specify the diffuse-white level. Therefore this should not require any changes to subtitle rendering itself.

The existing:

if (src && pl_color_transfer_is_hdr(src->params.color.transfer) &&
    p->next_opts->sub_hdr_peak)
{
    color.hdr = (struct pl_hdr_metadata) {
        .max_luma = p->next_opts->sub_hdr_peak,
    };
} else if (ref_luma && !pl_color_transfer_is_hdr(color.transfer)) {
    color.hdr.max_luma = ref_luma;
}
`
could become `if (src && pl_color_transfer_is_hdr(src->params.color.transfer) &&
    p->next_opts->sub_hdr_peak)
{
    color.hdr = (struct pl_hdr_metadata) {
        .max_luma = p->next_opts->sub_hdr_peak,
    };
} else if (!pl_color_transfer_is_hdr(color.transfer) &&
           p->next_opts->sub_sdr_peak)
{
    color.hdr.max_luma = p->next_opts->sub_sdr_peak;
} else if (ref_luma && !pl_color_transfer_is_hdr(color.transfer)) {
    color.hdr.max_luma = ref_luma;
}

could become:

if (src && pl_color_transfer_is_hdr(src->params.color.transfer) &&
    p->next_opts->sub_hdr_peak)
{
    color.hdr = (struct pl_hdr_metadata) {
        .max_luma = p->next_opts->sub_hdr_peak,
    };
} else if (!pl_color_transfer_is_hdr(color.transfer) &&
           p->next_opts->sub_sdr_peak)
{
    color.hdr.max_luma = p->next_opts->sub_sdr_peak;
} else if (ref_luma && !pl_color_transfer_is_hdr(color.transfer)) {
    color.hdr.max_luma = ref_luma;
}

and gl_next_opts would gain:

int sub_sdr_peak;

with an option definition mirroring sub-hdr-peak:

{"sub-sdr-peak", OPT_CHOICE(sub_sdr_peak,
    {"auto", 0},
    {"sdr", PL_COLOR_SDR_WHITE}),
    M_RANGE(10, 10000)},

No explicit default would be necessary beyond zero/auto, preserving existing behavior.

The resulting option definitions would therefore be symmetrical:

--sub-sdr-peak   diffuse white for SDR subtitle rendering
--sub-hdr-peak   diffuse white for HDR subtitle rendering

Interaction with sub-hdr-peak
The two options should be mutually exclusive based on the subtitle colorspace:

HDR subtitle colorspace → sub-hdr-peak

SDR subtitle colorspace → sub-sdr-peak

Thus an HDR video with normal SDR subtitles would continue to use the existing HDR subtitle handling, while an SDR subtitle rendered in an SDR colorspace could use sub-sdr-peak.

The default auto behavior would remain unchanged, so existing configurations would not be affected.

Alternative behavior of the wanted feature

No response

Log File

No response

Sample Files

No response

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with libass_overlay_color() and the gl_next_opts structure, then compare the existing sub-hdr-peak option definition and its handling. Add the symmetrical SDR option and ensure SDR subtitle colorspaces use it while preserving the default behavior and HDR handling.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
cli
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.