ytdl_hook.lua: get the duration of fragmented mp4#17936
Conversation
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 mpv-player#17762 (comment).
| hdr[#hdr + 1] = "!delay_open,media_type=" .. sub.media_type .. | ||
| ",codec=" .. (sub.codec or "null") .. props | ||
|
|
||
| if not is_default then |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
It already sets the duration below but it doesn't work for bilibili.tv.
There was a problem hiding this comment.
Why setting duration doesn't work?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I see duration. It also works in mpv. Is your installation broken?
"duration": 14020.729
"duration_string": "3:53:40"
There was a problem hiding this comment.
I see. What's the issue though? It fetches whole timeline pretty quickly.
You could always skip delay-open when there is no duration, but this will fetch all formats, which is slower.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Are you testing a short video?
43 minutes, it's not so long, but should be enough, no?
It only updates
durationup until where the cache is filled.
I tested with --no-cache
is_defaultis 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.
There was a problem hiding this comment.
With --no-cache duration is only the current time-pos + 1 for me.
The duration is preserved after changing to a delayed track.
There was a problem hiding this comment.
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
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.