summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOmar Roth <omarroth@hotmail.com>2018-03-12 20:36:49 -0500
committerOmar Roth <omarroth@hotmail.com>2018-03-12 20:36:49 -0500
commit8fb97a451153cc5cf1a20e6b76e25d6ee2a01c28 (patch)
treef9c82070f8ed8d45951c336b5f43b204a1b7ff85
parentc53ab9451919c0e2af39372e5a8b00f664cfb8a8 (diff)
downloadinvidious-8fb97a451153cc5cf1a20e6b76e25d6ee2a01c28.tar.gz
invidious-8fb97a451153cc5cf1a20e6b76e25d6ee2a01c28.tar.bz2
invidious-8fb97a451153cc5cf1a20e6b76e25d6ee2a01c28.zip
Add suppor for dash manifest
-rw-r--r--src/invidious.cr79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/invidious.cr b/src/invidious.cr
index 4b820a79..ded6a875 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -327,6 +327,85 @@ get "/redirect" do |env|
end
end
+# Return dash manifest for the given video ID
+get "/api/manifest/dash/id/:id" do |env|
+ env.response.headers.add("Access-Control-Allow-Origin", "*")
+ env.response.content_type = "application/dash+xml"
+
+ id = env.params.url["id"]
+
+ yt_client = get_client(youtube_pool)
+ begin
+ video = get_video(id, yt_client, PG_DB)
+ rescue ex
+ halt env, status_code: 403
+ ensure
+ youtube_pool << yt_client
+ end
+
+ adaptive_fmts = [] of HTTP::Params
+ if video.info.has_key?("adaptive_fmts")
+ video.info["adaptive_fmts"].split(",") do |string|
+ adaptive_fmts << HTTP::Params.parse(string)
+ end
+ else
+ halt env, status_code: 403
+ end
+
+ manifest = XML.build(indent: " ") do |xml|
+ xml.element("MPD", xmlns: "urn:mpeg:dash:schema:mpd:2011", profiles: "urn:mpeg:dash:profile:full:2011",
+ mediaPresentationDuration: "PT#{video.info["length_seconds"]}S", minBufferTime: "PT2S", type: "static") do
+ host = URI.parse(adaptive_fmts[0]["url"]).host.to_s
+
+ xml.element("BaseURL") { xml.text "https://#{host}" }
+ xml.element("Period", id: "0") do
+ adaptive_fmts.each do |fmt|
+ mimetype, codecs = fmt["type"].split(";")
+ codecs = codecs[9..-2]
+ fmt_type = mimetype.split("/")[0]
+ fmt_id = fmt["itag"]
+ bandwidth = fmt["bitrate"]
+
+ url = fmt["url"]
+ if fmt["s"]?
+ url += "&signature="
+ url += decrypt_signature(fmt["s"])
+ end
+
+ url = URI.parse(url)
+ url = url.path.not_nil! + "?" + url.query.not_nil!
+
+ if fmt_type == "video"
+ width, height = fmt["size"].split("x")
+ framerate = fmt["fps"]
+
+ xml.element("AdaptationSet", contentType: "video", width: width,
+ height: height, frameRate: framerate, subsegmentAlignment: true, id: fmt_id) do
+ xml.element("Representation", id: fmt_id, bandwidth: bandwidth, codecs: codecs, mimeType: mimetype) do
+ xml.element("BaseURL") { xml.text url }
+ xml.element("SegmentBase", indexRange: fmt["init"]) do
+ xml.element("Initialization", range: fmt["index"])
+ end
+ end
+ end
+ else
+ xml.element("AdaptationSet", contentType: "audio", subsegmentAlignment: true, id: fmt_id) do
+ xml.element("Representation", id: fmt_id, bandwidth: bandwidth, codecs: codecs, mimeType: mimetype) do
+ xml.element("BaseURL") { xml.text url }
+ xml.element("SegmentBase", indexRange: fmt["init"]) do
+ xml.element("Initialization", range: fmt["index"])
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ manifest
+end
+
error 404 do |env|
error_message = "404 Page not found"
templated "error"