diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index fcc23894..ab67004c 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -262,6 +262,75 @@ class Video self.info["adaptive_fmts"].split(",") do |string| adaptive_fmts << HTTP::Params.parse(string) end + elsif self.info.has_key?("dashmpd") + client = make_client(YT_URL) + response = client.get(self.info["dashmpd"]) + document = XML.parse_html(response.body) + + document.xpath_nodes(%q(//adaptationset)).each do |adaptation_set| + mime_type = adaptation_set["mimetype"] + + document.xpath_nodes(%q(.//representation)).each do |representation| + codecs = representation["codecs"] + itag = representation["id"] + bandwidth = representation["bandwidth"] + url = representation.xpath_node(%q(.//baseurl)).not_nil!.content + + clen = url.match(/clen\/(?\d+)/).try &.["clen"] + clen ||= "0" + lmt = url.match(/lmt\/(?\d+)/).not_nil!["lmt"] + + segment_list = representation.xpath_node(%q(.//segmentlist)).not_nil! + init = segment_list.xpath_node(%q(.//initialization)).not_nil!["sourceurl"] + index = segment_list.xpath_node(%q(.//segmenturl)).not_nil!["media"] + + # TODO: Replace with sane defaults when byteranges are absent + if init.starts_with? "sq" + init = "0-0" + index = "1-1" + else + init = init.lchop("range/") + index = index.lchop("range/") + index = "#{init.split("-")[1].to_i + 1}-#{index.split("-")[0].to_i}" + end + + params = { + "type" => ["#{mime_type}; codecs=\"#{codecs}\""], + "url" => [url], + "projection_type" => ["1"], + "index" => [index], + "init" => [init], + "xtags" => [] of String, + "lmt" => [lmt], + "clen" => [clen], + "bitrate" => [bandwidth], + "itag" => [itag], + } + + if mime_type == "video/mp4" + width = representation["width"]? + height = representation["height"]? + fps = representation["framerate"]? + + metadata = itag_to_metadata?(itag) + if metadata + width ||= metadata["width"]? + height ||= metadata["height"]? + fps ||= metadata["fps"]? + end + + if width && height + params["size"] = ["#{width}x#{height}"] + end + + if width + params["quality_label"] = ["#{height}p"] + end + end + + adaptive_fmts << HTTP::Params.new(params) + end + end end if adaptive_fmts[0]? && adaptive_fmts[0]["s"]?