Skip to content

Commit

Permalink
Videos: Fix missing host parameter on playback URLs when local=true (
Browse files Browse the repository at this point in the history
  • Loading branch information
syeopite committed Jan 22, 2025
2 parents dca130c + 3ac8978 commit 52daafe
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 25 deletions.
30 changes: 12 additions & 18 deletions src/invidious/routes/api/manifest.cr
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,21 @@ module Invidious::Routes::API::Manifest
haltf env, status_code: response.status_code
end

manifest = response.body

manifest = manifest.gsub(/<BaseURL>[^<]+<\/BaseURL>/) do |baseurl|
url = baseurl.lchop("<BaseURL>")
url = url.rchop("</BaseURL>")

if local
uri = URI.parse(url)
url = "#{HOST_URL}#{uri.request_target}host/#{uri.host}/"
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>[^<]+<\/BaseURL>/) do |baseurl|
url = baseurl.lchop("<BaseURL>").rchop("</BaseURL>")
url = HttpServer::Utils.proxy_video_url(url, absolute: true) if local
"<BaseURL>#{url}</BaseURL>"
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|
fmt["url"] = JSON::Any.new("#{HOST_URL}#{URI.parse(fmt["url"].as_s).request_target}")
video.adaptive_fmts.each do |fmt|
fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s, absolute: true))
end
end

Expand Down Expand Up @@ -183,8 +176,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("/")
Expand Down Expand Up @@ -213,7 +207,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
Expand Down
6 changes: 4 additions & 2 deletions src/invidious/routes/embed.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
9 changes: 6 additions & 3 deletions src/invidious/routes/video_playback.cr
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,13 @@ module Invidious::Routes::VideoPlayback
env.response.headers["Access-Control-Allow-Origin"] = "*"

if location = resp.headers["Location"]?
location = URI.parse(location)
location = "#{location.request_target}&host=#{location.host}#{region ? "&region=#{region}" : ""}"
url = Invidious::HttpServer::Utils.proxy_video_url(location, region: region)

env.redirect location
if title = query_params["title"]?
url = "#{url}&title=#{URI.encode_www_form(title)}"
end

env.redirect url
break
end

Expand Down
6 changes: 4 additions & 2 deletions src/invidious/routes/watch.cr
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,12 @@ module Invidious::Routes::Watch
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

Expand Down

0 comments on commit 52daafe

Please sign in to comment.