diff --git a/src/invidious/http_server/utils.cr b/src/invidious/http_server/utils.cr index 623a9177..a1348227 100644 --- a/src/invidious/http_server/utils.cr +++ b/src/invidious/http_server/utils.cr @@ -4,6 +4,17 @@ module Invidious::HttpServer module Utils extend self + @@proxy_alive : Bool = false + + def check_external_proxy + begin + response = HTTP::Client.get("#{CONFIG.external_videoplayback_proxy}") + @@proxy_alive = response.status_code == 200 + rescue + @@proxy_alive = false + end + end + def proxy_video_url(raw_url : String, *, region : String? = nil, absolute : Bool = false) url = URI.parse(raw_url) @@ -14,7 +25,11 @@ module Invidious::HttpServer url.query_params = params if absolute - return "#{HOST_URL}#{url.request_target}" + if @@proxy_alive + return "#{CONFIG.external_videoplayback_proxy}#{url.request_target}" + else + return "#{HOST_URL}#{url.request_target}" + end else return url.request_target end diff --git a/src/invidious/jobs/check_external_proxy.cr b/src/invidious/jobs/check_external_proxy.cr index ce0b296e..7a4a2080 100644 --- a/src/invidious/jobs/check_external_proxy.cr +++ b/src/invidious/jobs/check_external_proxy.cr @@ -4,7 +4,7 @@ class Invidious::Jobs::CheckExternalProxy < Invidious::Jobs::BaseJob def begin loop do - Invidious::Routes::API::Manifest.check_external_proxy + HttpServer::Utils.check_external_proxy LOGGER.info("CheckExternalProxy: Done, sleeping for 1 minute") sleep 1.minutes Fiber.yield diff --git a/src/invidious/routes/api/manifest.cr b/src/invidious/routes/api/manifest.cr index dcfec909..f1fa4124 100644 --- a/src/invidious/routes/api/manifest.cr +++ b/src/invidious/routes/api/manifest.cr @@ -1,15 +1,4 @@ module Invidious::Routes::API::Manifest - @@proxy_alive : Bool = false - - def self.check_external_proxy - begin - response = HTTP::Client.get("#{CONFIG.external_videoplayback_proxy}") - @@proxy_alive = response.status_code == 200 - rescue - @@proxy_alive = false - end - end - # /api/manifest/dash/id/:id def self.get_dash_video_id(env) env.response.headers.add("Access-Control-Allow-Origin", "*") @@ -38,36 +27,21 @@ module Invidious::Routes::API::Manifest haltf env, status_code: response.status_code end - manifest = response.body - - manifest = manifest.gsub(/[^<]+<\/BaseURL>/) do |baseurl| - url = baseurl.lchop("") - url = url.rchop("") - - if local - uri = URI.parse(url) - if @@proxy_alive - url = "#{CONFIG.external_videoplayback_proxy}#{uri.request_target}host/#{uri.host}/" - else - url = "#{HOST_URL}#{uri.request_target}host/#{uri.host}/" - end - end - + # Proxy URLs for video playback on invidious. + # Other API clients can get the original URLs by omiting `local=true`. + manifest = response.body.gsub(/[^<]+<\/BaseURL>/) do |baseurl| + url = baseurl.lchop("").rchop("") + url = HttpServer::Utils.proxy_video_url(url, absolute: true) if local "#{url}" end return manifest end - adaptive_fmts = video.adaptive_fmts - + # Ditto, only proxify URLs if `local=true` is used if local - adaptive_fmts.each do |fmt| - if @@proxy_alive - fmt["url"] = JSON::Any.new("#{CONFIG.external_videoplayback_proxy}#{URI.parse(fmt["url"].as_s).request_target}") - else - fmt["url"] = JSON::Any.new("#{HOST_URL}#{URI.parse(fmt["url"].as_s).request_target}") - end + video.adaptive_fmts.each do |fmt| + fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s, absolute: true)) end end @@ -203,8 +177,9 @@ module Invidious::Routes::API::Manifest manifest = response.body if local - manifest = manifest.gsub(/^https:\/\/\w+---.{11}\.c\.youtube\.com[^\n]*/m) do |match| - path = URI.parse(match).path + manifest = manifest.gsub(/^https:\/\/[^\n"]*/m) do |match| + uri = URI.parse(match) + path = uri.path path = path.lchop("/videoplayback/") path = path.rchop("/") @@ -233,7 +208,7 @@ module Invidious::Routes::API::Manifest raw_params["fvip"] = fvip["fvip"] end - raw_params["local"] = "true" + raw_params["host"] = uri.host.not_nil! "#{HOST_URL}/videoplayback?#{raw_params}" end diff --git a/src/invidious/routes/embed.cr b/src/invidious/routes/embed.cr index 266f7ba4..00f24159 100644 --- a/src/invidious/routes/embed.cr +++ b/src/invidious/routes/embed.cr @@ -157,10 +157,12 @@ module Invidious::Routes::Embed adaptive_fmts = video.adaptive_fmts if params.local - fmt_stream.each { |fmt| fmt["url"] = JSON::Any.new(URI.parse(fmt["url"].as_s).request_target) } - adaptive_fmts.each { |fmt| fmt["url"] = JSON::Any.new(URI.parse(fmt["url"].as_s).request_target) } + fmt_stream.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s)) } end + # Always proxy DASH streams, otherwise youtube CORS headers will prevent playback + adaptive_fmts.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s)) } + video_streams = video.video_streams audio_streams = video.audio_streams diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr index 7e8a630f..73478da1 100644 --- a/src/invidious/routes/watch.cr +++ b/src/invidious/routes/watch.cr @@ -131,10 +131,12 @@ module Invidious::Routes::Watch end if params.local - fmt_stream.each { |fmt| fmt["url"] = JSON::Any.new(URI.parse(fmt["url"].as_s).request_target) } - adaptive_fmts.each { |fmt| fmt["url"] = JSON::Any.new(URI.parse(fmt["url"].as_s).request_target) } + fmt_stream.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s)) } end + # Always proxy DASH streams, otherwise youtube CORS headers will prevent playback + adaptive_fmts.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s)) } + video_streams = video.video_streams audio_streams = video.audio_streams