Add option for HLS quality in user preferences

This commit is contained in:
syeopite 2023-09-22 10:34:26 -04:00
parent 9892604758
commit 2d1617a46a
No known key found for this signature in database
GPG Key ID: A73C186DA3955A1A
8 changed files with 41 additions and 21 deletions

View File

@ -796,7 +796,7 @@ default_user_preferences:
## ##
## Default video quality. ## Default video quality.
## ##
## Accepted values: dash, hd720, medium, small ## Accepted values: hls, dash, hd720, medium, small
## Default: hd720 ## Default: hd720
## ##
#quality: hd720 #quality: hd720

View File

@ -81,6 +81,7 @@
"preferences_speed_label": "Default speed: ", "preferences_speed_label": "Default speed: ",
"preferences_quality_label": "Preferred video quality: ", "preferences_quality_label": "Preferred video quality: ",
"preferences_quality_option_dash": "DASH (adaptive quality)", "preferences_quality_option_dash": "DASH (adaptive quality)",
"preferences_quality_option_hls": "HLS",
"preferences_quality_option_hd720": "HD720", "preferences_quality_option_hd720": "HD720",
"preferences_quality_option_medium": "Medium", "preferences_quality_option_medium": "Medium",
"preferences_quality_option_small": "Small", "preferences_quality_option_small": "Small",

View File

@ -177,7 +177,7 @@ module Invidious::Routes::API::Manifest
manifest = response.body manifest = response.body
if local if local
manifest = manifest.gsub(/^https:\/\/\w+---.{11}\.c\.youtube\.com[^\n]*/m) do |match| manifest = manifest.gsub(/^(https:\/\/\w+---.{11}\.c\.youtube\.com[^\n]*)|(https:\/\/\w+---.{11}\.googlevideo\.com[^\n]*)/m) do |match|
path = URI.parse(match).path path = URI.parse(match).path
path = path.lchop("/videoplayback/") path = path.lchop("/videoplayback/")

View File

@ -52,7 +52,11 @@ module Invidious::Routes::Watch
env.params.query.delete_all("listen") env.params.query.delete_all("listen")
begin begin
video = get_video(id, region: params.region) if params.quality == "hls"
video = get_video(id, region: params.region, force_hls: true)
else
video = get_video(id, region: params.region)
end
rescue ex : NotFoundException rescue ex : NotFoundException
LOGGER.error("get_video not found: #{id} : #{ex.message}") LOGGER.error("get_video not found: #{id} : #{ex.message}")
return error_template(404, ex) return error_template(404, ex)

View File

@ -294,8 +294,8 @@ struct Video
predicate_bool upcoming, isUpcoming predicate_bool upcoming, isUpcoming
end end
def get_video(id, refresh = true, region = nil, force_refresh = false) def get_video(id, refresh = true, region = nil, force_hls = false, force_refresh = false)
if (video = Invidious::Database::Videos.select(id)) && !region if (video = Invidious::Database::Videos.select(id)) && !region && !force_hls
# If record was last updated over 10 minutes ago, or video has since premiered, # If record was last updated over 10 minutes ago, or video has since premiered,
# refresh (expire param in response lasts for 6 hours) # refresh (expire param in response lasts for 6 hours)
if (refresh && if (refresh &&
@ -312,8 +312,8 @@ def get_video(id, refresh = true, region = nil, force_refresh = false)
end end
end end
else else
video = fetch_video(id, region) video = fetch_video(id, region, force_hls)
Invidious::Database::Videos.insert(video) if !region Invidious::Database::Videos.insert(video) if !region && !force_hls
end end
return video return video
@ -323,8 +323,8 @@ rescue DB::Error
return fetch_video(id, region) return fetch_video(id, region)
end end
def fetch_video(id, region) def fetch_video(id, region, force_hls = false)
info = extract_video_info(video_id: id) info = extract_video_info(video_id: id, force_hls: force_hls)
if reason = info["reason"]? if reason = info["reason"]?
if reason == "Video unavailable" if reason == "Video unavailable"

View File

@ -50,7 +50,7 @@ def parse_related_video(related : JSON::Any) : Hash(String, JSON::Any)?
} }
end end
def extract_video_info(video_id : String) def extract_video_info(video_id : String, force_hls : Bool = false)
# Init client config for the API # Init client config for the API
client_config = YoutubeAPI::ClientConfig.new client_config = YoutubeAPI::ClientConfig.new
@ -101,16 +101,29 @@ def extract_video_info(video_id : String)
params["reason"] = JSON::Any.new(reason) if reason params["reason"] = JSON::Any.new(reason) if reason
new_player_response = nil new_player_response = nil
if force_hls
# Don't use Android test suite client if po_token is passed because po_token doesn't client_config.client_type = YoutubeAPI::ClientType::IOS
# work for Android test suite client.
if reason.nil? && CONFIG.po_token.nil?
# Fetch the video streams using an Android client in order to get the
# decrypted URLs and maybe fix throttling issues (#2194). See the
# following issue for an explanation about decrypted URLs:
# https://github.com/TeamNewPipe/NewPipeExtractor/issues/562
client_config.client_type = YoutubeAPI::ClientType::AndroidTestSuite
new_player_response = try_fetch_streaming_data(video_id, client_config) new_player_response = try_fetch_streaming_data(video_id, client_config)
else
# Don't use Android test suite client if po_token is passed because po_token doesn't
# work for Android test suite client.
if reason.nil? && CONFIG.po_token.nil?
# Fetch the video streams using an Android client in order to get the
# decrypted URLs and maybe fix throttling issues (#2194). See the
# following issue for an explanation about decrypted URLs:
# https://github.com/TeamNewPipe/NewPipeExtractor/issues/562
client_config.client_type = YoutubeAPI::ClientType::AndroidTestSuite
new_player_response = try_fetch_streaming_data(video_id, client_config)
else
if reason.nil?
# Fetch the video streams using an Android client in order to get the
# decrypted URLs and maybe fix throttling issues (#2194). See the
# following issue for an explanation about decrypted URLs:
# https://github.com/TeamNewPipe/NewPipeExtractor/issues/562
client_config.client_type = YoutubeAPI::ClientType::AndroidTestSuite
new_player_response = try_fetch_streaming_data(video_id, client_config)
end
end
end end
# Replace player response and reset reason # Replace player response and reset reason

View File

@ -4,8 +4,10 @@
<% if params.autoplay %>autoplay<% end %> <% if params.autoplay %>autoplay<% end %>
<% if params.video_loop %>loop<% end %> <% if params.video_loop %>loop<% end %>
<% if params.controls %>controls<% end %>> <% if params.controls %>controls<% end %>>
<% if (hlsvp = video.hls_manifest_url) && !CONFIG.disabled?("livestreams") %> <% if (hlsvp = video.hls_manifest_url) && video.live_now && !CONFIG.disabled?("livestreams") %>
<source src="<%= URI.parse(hlsvp).request_target %><% if params.local %>?local=true<% end %>" type="application/x-mpegURL" label="livestream"> <source src="<%= URI.parse(hlsvp).request_target %><% if params.local %>?local=true<% end %>" type="application/x-mpegURL" label="livestream">
<% elsif (hlsvp = video.hls_manifest_url) && params.quality == "hls" %>
<source src="<%= URI.parse(hlsvp).request_target %><% if params.local %>?local=true<% end %>" type="application/x-mpegURL" label="HLS">
<% else %> <% else %>
<% if params.listen %> <% if params.listen %>
<% # default to 128k m4a stream <% # default to 128k m4a stream

View File

@ -54,7 +54,7 @@
<div class="pure-control-group"> <div class="pure-control-group">
<label for="quality"><%= translate(locale, "preferences_quality_label") %></label> <label for="quality"><%= translate(locale, "preferences_quality_label") %></label>
<select name="quality" id="quality"> <select name="quality" id="quality">
<% {"dash", "hd720", "medium", "small"}.each do |option| %> <% {"hls", "dash", "hd720", "medium", "small"}.each do |option| %>
<% if !(option == "dash" && CONFIG.disabled?("dash")) %> <% if !(option == "dash" && CONFIG.disabled?("dash")) %>
<option value="<%= option %>" <% if preferences.quality == option %> selected <% end %>><%= translate(locale, "preferences_quality_option_" + option) %></option> <option value="<%= option %>" <% if preferences.quality == option %> selected <% end %>><%= translate(locale, "preferences_quality_option_" + option) %></option>
<% end %> <% end %>