Skip to content

demux_timeline: update delay_open streams when they are opened - #17936

Open
guidocella wants to merge 1 commit into
mpv-player:masterfrom
guidocella:bilibili
Open

guidocella wants to merge 1 commit into
mpv-player:masterfrom
guidocella:bilibili

Conversation

@guidocella

Copy link
Copy Markdown
Contributor

Changing all_formats' default to true broke reporting the duration of bilibili.tv videos because fragmented MP4 files have the duration in a segment index box and not in the container header.

With all_formats=false the requested formats are opened immediately and libavformat uses HTTP range requests to probe the fragmented MP4 and reads the correct duration.

With all_formats=true every format gets !delay_open and libavformat can't seek for the sidx in that sub-demuxer context.

Fix this by not applying delay_open to the requested formats.

Fixes
#17762 (comment).

Found by Claude.

Comment thread player/lua/ytdl_hook.lua Outdated
hdr[#hdr + 1] = "!delay_open,media_type=" .. sub.media_type ..
",codec=" .. (sub.codec or "null") .. props

if not is_default then

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not delay_open anymore? I think you should be initializing duration as documentation says, instead of removing this flag

Using multiple segments requires you to specify all offsets and durations

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It already sets the duration below but it doesn't work for bilibili.tv.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why setting duration doesn't work?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For bilibili.tv it's not present in the JSON (e.g. yt-dlp -J https://www.bilibili.com/video/BV1tywge6EWy/ > /tmp/bilibili.json). I don't know if other extractors share this problem.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see duration. It also works in mpv. Is your installation broken?

"duration": 14020.729
"duration_string": "3:53:40"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you testing a short video? It only updates duration up until where the cache is filled.

is_default is only true for the tracks in the selected format. Others are still delayed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you testing a short video?

43 minutes, it's not so long, but should be enough, no?

It only updates duration up until where the cache is filled.

I tested with --no-cache

is_default is only true for the tracks in the selected format. Others are still delayed.

And what about other tracks, they still don't have duration set.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With --no-cache duration is only the current time-pos + 1 for me.

The duration is preserved after changing to a delayed track.

@kasper93 kasper93 May 26, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we instead reevaluate the coded parameters of delayed tracks when they are selected/opened for the first time?

This not only involves duration, but also codec and dozen other fields in mp_codec_params which are not populated for delayed open.

You can see that we show null codec for all those tracks, if they are not mapped upfront. You can do this to test:

--- a/player/lua/ytdl_hook.lua
+++ b/player/lua/ytdl_hook.lua
@@ -556,7 +556,7 @@ local function formats_to_edl(json, formats, use_all_formats)
                     props = props .. ",samplerate=" .. as_integer(track.asr)
                 end
                 hdr[#hdr + 1] = "!delay_open,media_type=" .. sub.media_type ..
-                    ",codec=" .. (sub.codec or "null") .. props
+                    ",codec=null" .. props

                 -- Add bitrate information etc. for better user selection.
                 local byterate = 0

@guidocella guidocella Nov 6, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated it as suggested, but there is this limitation:

Limitation: --start=50% still ends up at about 1:26 on the bilibili video. The duration isn't known until the selected segment opens, which happens after the initial seek. The old ytdl_hook approach avoided this because it opened the requested formats immediately; this fix doesn't.

@bitraid

bitraid commented Aug 23, 2026

Copy link
Copy Markdown

Non-fragmented mp4s that lack faststart (have moov after mdat) are also affected. There is no issue when using the direct (no yt-dlp) video URL (provided the HTTP supports byte-range requests).

@kasper93 kasper93 added this to the Release v0.43.0 milestone Aug 23, 2026
delay_open streams are added with the codec parameters specified in the
EDL, so fields like the codec, dimensions and sample rate are missing or
just hints. Moreover, the duration is unknown unless the EDL specifies a
length, e.g. because ytdl's JSON doesn't include it, as with bilibili.tv
videos since all_formats defaults to true.

When a delayed segment is opened, replace the codec parameters of its
streams with the real ones, and set the duration from the opened
demuxer if it was unknown.

The duration is still unknown when the initial seek is performed,
because segments are opened lazily on the first read, so percentage
seeks like --start=50% still don't work in this case.

Fixes
mpv-player#17762 (comment).
@guidocella guidocella changed the title ytdl_hook.lua: get the duration of fragmented mp4 demux_timeline: update delay_open streams when they are opened Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants