options: store audio/sub delay in doubles instead of floats

An `--audio-file` could be sourced from a stream. A stream could be
 using timestamps that match unix time in their segments. In that
 case, setting `audio-delay` will lead to a big unexpected A/V desync
 due to the limited precision of floats.

 This commit changes `--audio-delay` (and --sub-delay while at it) to be
 stored in `double` instead of `float`.

 `audio_delay` was already up-casted to `double` wherever it was
 evaluated. Same for `sub-delay`, except its own value was getting
 adjusted based on `double` values in one place (bad!):

 player/command.c:6297

    mpctx->opts->subs_shared->sub_delay[track_ind] -= a[0] - refpts;

 A showcase:

    mkfifo /tmp/mpv
    date=$(date +'%s')

 Before:

    mpv --input-ipc-server=/tmp/mpv -
    echo 'print-text '"${date}" | socat - /tmp/mpv # 1782890841
    echo 'set audio-delay '"${date}" | socat - /tmp/mpv
    echo 'set sub-delay '"${date}" | socat - /tmp/mpv
    echo 'print-text ${=audio-delay}' | socat - /tmp/mpv # 1782890880.000000
    echo 'print-text ${=sub-delay}' | socat - /tmp/mpv # 1782890880.000000

 After:

    mpv --input-ipc-server=/tmp/mpv -
    echo 'print-text '"${date}" | socat - /tmp/mpv # 1782890841
    echo 'set audio-delay '"${date}" | socat - /tmp/mpv
    echo 'set sub-delay '"${date}" | socat - /tmp/mpv
    echo 'print-text ${=audio-delay}' | socat - /tmp/mpv # 1782890841.000000
    echo 'print-text ${=sub-delay}' | socat - /tmp/mpv # 1782890841.000000

Signed-off-by: Mohammad AlSaleh <CE.Mohammad.AlSaleh@gmail.com>
This commit is contained in:
Mohammad AlSaleh authored and Dudemanguy committed 2026-07-02 17:38:51 +00:00
1 parent c02751a0bf
commit 7aa8580cab
3 files changed
+8 -8

No files matched your search

+3 -3
View File
@@ -381,8 +381,8 @@ const struct m_sub_options mp_subtitle_sub_opts = {
const struct m_sub_options mp_subtitle_shared_sub_opts = {
.opts = (const struct m_option[]){
{"sub-delay", OPT_FLOAT(sub_delay[0])},
{"secondary-sub-delay", OPT_FLOAT(sub_delay[1])},
{"sub-delay", OPT_DOUBLE(sub_delay[0])},
{"secondary-sub-delay", OPT_DOUBLE(sub_delay[1])},
{"sub-pos", OPT_FLOAT(sub_pos[0]), M_RANGE(0.0, 150.0)},
{"secondary-sub-pos", OPT_FLOAT(sub_pos[1]), M_RANGE(0.0, 150.0)},
{"sub-visibility", OPT_BOOL(sub_visibility[0])},
@@ -692,7 +692,7 @@ static const m_option_t mp_opts[] = {
{"audio-pitch-correction", OPT_BOOL(pitch_correction)},
// set a-v distance
{"audio-delay", OPT_FLOAT(audio_delay)},
{"audio-delay", OPT_DOUBLE(audio_delay)},
// ------------------------- codec/vfilter options --------------------
+2 -2
View File
@@ -139,7 +139,7 @@ struct mp_subtitle_opts {
// Options for both primary and secondary subs.
struct mp_subtitle_shared_opts {
float sub_delay[2];
double sub_delay[2];
float sub_pos[2];
bool sub_visibility[2];
int ass_style_override[2];
@@ -263,7 +263,7 @@ typedef struct MPOpts {
int hr_seek;
float hr_seek_demuxer_offset;
bool hr_seek_framedrop;
float audio_delay;
double audio_delay;
float default_max_pts_correction;
int autosync;
int frame_dropping;
+3 -3
View File
@@ -107,7 +107,7 @@ static void update_subtitle_speed(struct dec_sub *sub)
static double pts_to_subtitle(struct dec_sub *sub, double pts)
{
struct mp_subtitle_shared_opts *opts = sub->shared_opts;
float delay = sub->order < 0 ? 0.0f : opts->sub_delay[sub->order];
double delay = sub->order < 0 ? 0.0 : opts->sub_delay[sub->order];
if (pts != MP_NOPTS_VALUE)
pts = (pts * sub->play_dir - delay) / sub->sub_speed;
@@ -118,7 +118,7 @@ static double pts_to_subtitle(struct dec_sub *sub, double pts)
static double pts_from_subtitle(struct dec_sub *sub, double pts)
{
struct mp_subtitle_shared_opts *opts = sub->shared_opts;
float delay = sub->order < 0 ? 0.0f : opts->sub_delay[sub->order];
double delay = sub->order < 0 ? 0.0 : opts->sub_delay[sub->order];
if (pts != MP_NOPTS_VALUE)
pts = (pts * sub->sub_speed + delay) * sub->play_dir;
@@ -365,7 +365,7 @@ void sub_read_packets(struct dec_sub *sub, double video_pts, bool force,
break;
// (Use this mechanism only if sub_delay matters to avoid corner cases.)
float delay = sub->order < 0 ? 0.0f : sub->shared_opts->sub_delay[sub->order];
double delay = sub->order < 0 ? 0.0 : sub->shared_opts->sub_delay[sub->order];
double min_pts = delay < 0 || force ? video_pts : MP_NOPTS_VALUE;
struct demux_packet *pkt;