Closed gerion0 closed 1 year ago
The YouTube and Tubed add-ons both do this, generate a custom mpd
to use for playback based on quality selection and availability.
https://github.com/anxdpanic/script.module.tubed.api/blob/master/resources/lib/src/tubed_api/usher/lib/mpeg_dash.py
Thanks, I will take a look into it. From a quick look in the code the generated mpd contains a lot of more information. Do you know, if this information (bitrate, framerate, ...) is necessary for a proper working?
I'm not sure if all of it is necessary, but some of it definitely helps avoid unwanted side-effects (ie. framerate avoids a refresh rate switch in Kodi). All the information available was used just to avoid any other potential situations. The majority if not all the required information should be parsable from the url.
@gerion0 how did you go? Can the issue be closed?
No progress on the main issue.
I played around a little bit und tried to reproduce the MPD files from the Tubed addon. The produced files looks like:
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd" minBufferTime="PT1.5S" mediaPresentationDuration="PT556S" type="static" profiles="urn:mpeg:dash:profile:isoff-main:2011">
<Period>
<AdaptationSet id="0" mimeType="video/webm" lang="" subsegmentAlignment="true" subsegmentStartsWithSAP="1" bitstreamSwitching="true" default="true">
<Role schemeIdUri="urn:mpeg:DASH:role:2011" value="main"/>
<Representation id="video" codecs="vp9" startWithSAP="1" bandwidth="2628.373" width="1920" height="1080" frameRate="25">
<BaseURL>https://r5---sn-i5heen7z.googlevideo.com/videoplayback?expire=163292548...</BaseURL>
<SegmentBase indexRange="0-0">
<Initialization range="0-0" />
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" mimeType="audio/webm" lang="" subsegmentAlignment="true" subsegmentStartsWithSAP="1" bitstreamSwitching="true" default="true">
<Role schemeIdUri="urn:mpeg:DASH:role:2011" value="main"/>
<Representation id="audio" codecs="opus" bandwidth="133.128">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>https://r5---sn-i5heen7z.googlevideo.com/videoplayback?expire=1632925488...</BaseURL>
<SegmentBase indexRange="0-0">
<Initialization range="0-0" />
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>
These files do not play at all, the correct encoders are loaded but the stream itself is not downloaded.
My guess it that the <Initialization range="0-0" />
is the problematic part since it says the inputstream.adaptive addon that the relevant media header has no length. However, <Initialization range="0-0" />
is the default/fallback in the Tubed addon and , unfortunately, the correct valeus are not returned by youtube-dl/yt-dlp.
Do you know a minimal MPD that has long media streams and is playable with inputstream.adaptive? Ideally, this would only require the two URLs so inputstream.adaptive downloads the first bytes on it's own and figures out the formats, the length, the seeking capabilities etc.
Is inputstream.adaptive capable of doing so in general? Otherwise, the addon must utilize FFMpeg, download the first bytes, read the stream and feed that into a fake mpd or remux the streams into one.
In it's core my question is:
Given the two URLs:
How must a MPD file which contains these URLS look like so Kodi is playing them simultaineously (without completely downloading them first)?
Ok
Mp4 can be packaged in two ways:
All mp4s have initialization data, usually a small size (~1000 bytes) that tells the video player information like resolution, codecs, profiles etc.
Some segmented mp4 will include the init data with each segment but this is wasteful, so a 'initialization segment' is created separately so the same 1000 bytes aren't having to be downloaded with each segment.
In the one large file scenario it's just at the start of the file.
The range
parameter is to be used with the single file case, so <Initialization range="0-0" />
is telling us that this is the range of the file the init data is in - it doesn't make sense.
Then when you link to the separate init files in your post above, this is telling me you're not using one large file, but trying to play a stream with separate segments (in this case there is no range
attribute).
Assuming that you're getting the single file - you'll need to figure out where the init segment ends. Of course it should start at 0. Maybe there's a python library out there that can help with that, or you can simply search for whatever sequence of characters would signify the end of this sequence. Obviously, only get the first 2 or 3000 bytes of the file to check.
MPD files are normally generated by a packager which can read the source files and so it's assumed the init range information is contained within the MPD.
Thanks for the explanation.
Assuming that you're getting the single file - you'll need to figure out where the init segment ends. Of course it should start at 0. Maybe there's a python library out there that can help with that, or you can simply search for whatever sequence of characters would signify the end of this sequence. Obviously, only get the first 2 or 3000 bytes of the file to check.
What happens, if no such ending exists in the MPD? In the example given in my initial post no init segment is given. In this case, inputstream.adaptive seems to download the whole stream. Is this to search for the init segment?
What happens, if the ending mentioned in the MPD is incorrect/point to data behind the actual ending (e.g. always the first MiB)? Does inputstream.adaptive only download 1 MiB in this case but parses the data for the correct ending anyway?
The answer to the second question could be found by just trying. The example in the OP isn't making sense to me compared to the log, are you sure that exact mpd generated that log?
I've done a little more research for you.
An example of a working mpd is here
The initialization range refers to the location of the init data, and the segmentbase indexrange refers to the location of the SIDX (segment index) data. I'm not sure what happens if you don't provide the indexrange, try and see.
Bug report
Describe the bug
This isn't directly a bug, just a question to understand inputstream.adaptive's behavior without reading the source code.
I'm currently working on the Youtube support for plugin.video.sendtokodi. Currently, this plugin asks Youtube with youtube-dl for a (video and audio combined) stream URL, gets one stream back and plays it. For these cases (video and audio together), Youtube provides only a low resolution stream (720p or lower).
However, youtube-dl can request higher resolutions. In this case, it delivers two URLs (with some metadata), one for video and one for audio. I searched a lot to get Kodi to play these stream together and one common suggestion was inputstream.adaptive (here, partly here).
According to the wiki I need to build a custom mpd file for that. With a lot of try and error, I found out that the minimal mpd file for the example mpd file in the README looks so:
This mpd file is accepted by inputstream.adaptive while missing a lot of fields compared to the original.
My next step was to replace the URLs in the initialization field with the one that youtube provides. inputstream.adaptive resolves this correctly, but downloads the full media files first, and then complains that the stream selection was not successful (see log below).
My questions:
Additional information
youtube-dl -j <youtube-url>
(it provides a bunch of information but the URLs are contained in the block"requested_formats"
).wget
) and remuxing the streams works fine.Debuglog
MPD/M3U8s/ISM
An example or copy of a manifest (or manifests for HLS - master and variants) can be found here (this file, however, will not work. The URLs therein are temporary only):
Your Environment
Used Operating system:
[x] Linux
Operating system version/name: Gentoo Linux
Kodi version: 19.1
inputstream.adaptive version: 2.6.23