mirror of
https://github.com/iv-org/invidious.git
synced 2025-07-14 09:28:32 +00:00
Merge ffc44b0cff
into b13f77b5af
This commit is contained in:
commit
9418edbad0
@ -25,7 +25,7 @@ var options = {
|
|||||||
html5: {
|
html5: {
|
||||||
preloadTextTracks: false,
|
preloadTextTracks: false,
|
||||||
vhs: {
|
vhs: {
|
||||||
overrideNative: true
|
overrideNative: !videojs.browser.IS_ANY_SAFARI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -139,7 +139,7 @@ https_only: false
|
|||||||
## Disable proxying server-wide. Can be disable as a whole, or
|
## Disable proxying server-wide. Can be disable as a whole, or
|
||||||
## only for a single function.
|
## only for a single function.
|
||||||
##
|
##
|
||||||
## Accepted values: true, false, dash, livestreams, downloads, local
|
## Accepted values: true, false, dash, livestreams, downloads, local, hls
|
||||||
## Default: false
|
## Default: false
|
||||||
##
|
##
|
||||||
#disable_proxy: false
|
#disable_proxy: false
|
||||||
@ -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
|
||||||
|
@ -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",
|
||||||
@ -498,5 +499,11 @@
|
|||||||
"toggle_theme": "Toggle Theme",
|
"toggle_theme": "Toggle Theme",
|
||||||
"carousel_slide": "Slide {{current}} of {{total}}",
|
"carousel_slide": "Slide {{current}} of {{total}}",
|
||||||
"carousel_skip": "Skip the Carousel",
|
"carousel_skip": "Skip the Carousel",
|
||||||
"carousel_go_to": "Go to slide `x`"
|
"carousel_go_to": "Go to slide `x`",
|
||||||
|
"video_quality_livestream_label": "Livestream",
|
||||||
|
"video_quality_hls_label": "HLS",
|
||||||
|
"video_quality_dash_label": "DASH",
|
||||||
|
"video_quality_hd720_label": "hd720",
|
||||||
|
"video_quality_medium_label": "medium",
|
||||||
|
"video_quality_small_label": "small"
|
||||||
}
|
}
|
||||||
|
@ -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|\.googlevideo\.com)[^\n]*/m) do |match|
|
||||||
path = URI.parse(match).path
|
path = URI.parse(match).path
|
||||||
|
|
||||||
path = path.lchop("/videoplayback/")
|
path = path.lchop("/videoplayback/")
|
||||||
|
@ -91,7 +91,7 @@ module Invidious::Routes::VideoPlayback
|
|||||||
end
|
end
|
||||||
|
|
||||||
if url.includes? "&file=seg.ts"
|
if url.includes? "&file=seg.ts"
|
||||||
if CONFIG.disabled?("livestreams")
|
if CONFIG.disabled?("livestreams") || CONFIG.disabled?("hls")
|
||||||
return error_template(403, "Administrator has disabled this endpoint.")
|
return error_template(403, "Administrator has disabled this endpoint.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ 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)
|
video = get_video(id, region: params.region, get_hls: (params.quality == "hls"))
|
||||||
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)
|
||||||
|
@ -294,7 +294,7 @@ 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, get_hls = false, force_refresh = false)
|
||||||
if (video = Invidious::Database::Videos.select(id)) && !region
|
if (video = Invidious::Database::Videos.select(id)) && !region
|
||||||
# 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)
|
||||||
@ -316,6 +316,19 @@ def get_video(id, refresh = true, region = nil, force_refresh = false)
|
|||||||
Invidious::Database::Videos.insert(video) if !region
|
Invidious::Database::Videos.insert(video) if !region
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The video object we got above could be from a previous request that was not
|
||||||
|
# done through the IOS client. If the users wants HLS we should check if
|
||||||
|
# a manifest exists in the data returned. If not we will rerequest one.
|
||||||
|
if get_hls && !video.hls_manifest_url
|
||||||
|
begin
|
||||||
|
video_with_hls_data = update_video_object_with_hls_data(id, video)
|
||||||
|
return video if !video_with_hls_data
|
||||||
|
Invidious::Database::Videos.update(video_with_hls_data) if !region
|
||||||
|
rescue ex
|
||||||
|
# Use old database video if IOS client request fails
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return video
|
return video
|
||||||
rescue DB::Error
|
rescue DB::Error
|
||||||
# Avoid common `DB::PoolRetryAttemptsExceeded` error and friends
|
# Avoid common `DB::PoolRetryAttemptsExceeded` error and friends
|
||||||
|
@ -111,6 +111,15 @@ def extract_video_info(video_id : String)
|
|||||||
# https://github.com/TeamNewPipe/NewPipeExtractor/issues/562
|
# https://github.com/TeamNewPipe/NewPipeExtractor/issues/562
|
||||||
client_config.client_type = YoutubeAPI::ClientType::AndroidTestSuite
|
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
|
||||||
|
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
|
||||||
|
|
||||||
# Replace player response and reset reason
|
# Replace player response and reset reason
|
||||||
@ -144,6 +153,24 @@ def extract_video_info(video_id : String)
|
|||||||
return params
|
return params
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_video_object_with_hls_data(id : String, video : Video)
|
||||||
|
client_config = YoutubeAPI::ClientConfig.new(client_type: YoutubeAPI::ClientType::IOS)
|
||||||
|
|
||||||
|
new_player_response = try_fetch_streaming_data(id, client_config)
|
||||||
|
current_streaming_data = video.info["streamingData"].try &.as_h
|
||||||
|
|
||||||
|
return nil if !new_player_response
|
||||||
|
|
||||||
|
if current_streaming_data && (manifest = new_player_response.dig?("streamingData", "hlsManifestUrl"))
|
||||||
|
current_streaming_data["hlsManifestUrl"] = JSON::Any.new(manifest.as_s)
|
||||||
|
video.info["streamingData"] = JSON::Any.new(current_streaming_data)
|
||||||
|
|
||||||
|
return video
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
def try_fetch_streaming_data(id : String, client_config : YoutubeAPI::ClientConfig) : Hash(String, JSON::Any)?
|
def try_fetch_streaming_data(id : String, client_config : YoutubeAPI::ClientConfig) : Hash(String, JSON::Any)?
|
||||||
LOGGER.debug("try_fetch_streaming_data: [#{id}] Using #{client_config.client_type} client.")
|
LOGGER.debug("try_fetch_streaming_data: [#{id}] Using #{client_config.client_type} client.")
|
||||||
response = YoutubeAPI.player(video_id: id, params: "2AMB", client_config: client_config)
|
response = YoutubeAPI.player(video_id: id, params: "2AMB", client_config: client_config)
|
||||||
|
@ -105,8 +105,12 @@ def process_video_params(query, preferences)
|
|||||||
vr_mode = vr_mode == 1
|
vr_mode = vr_mode == 1
|
||||||
save_player_pos = save_player_pos == 1
|
save_player_pos = save_player_pos == 1
|
||||||
|
|
||||||
if CONFIG.disabled?("dash") && quality == "dash"
|
# Force set quality to "high" if dash or hls has been disabled by the server
|
||||||
quality = "high"
|
{"dash", "hls"}.each do |disabled_quality|
|
||||||
|
if CONFIG.disabled?(disabled_quality) && quality == disabled_quality
|
||||||
|
quality = "high"
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if CONFIG.disabled?("local") && local
|
if CONFIG.disabled?("local") && local
|
||||||
|
@ -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="<%= HTML.escape(translate(locale,"video_quality_livestream_label")) %>">
|
||||||
|
<% elsif (hlsvp = video.hls_manifest_url) && params.quality == "hls" && !CONFIG.disabled?("hls") %>
|
||||||
|
<source src="<%= URI.parse(hlsvp).request_target %><% if params.local %>?local=true<% end %>" type="application/x-mpegURL" label="<%= HTML.escape(translate(locale,"video_quality_hls_label")) %>">
|
||||||
<% else %>
|
<% else %>
|
||||||
<% if params.listen %>
|
<% if params.listen %>
|
||||||
<% # default to 128k m4a stream
|
<% # default to 128k m4a stream
|
||||||
@ -35,7 +37,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<% if params.quality == "dash" %>
|
<% if params.quality == "dash" %>
|
||||||
<source src="/api/manifest/dash/id/<%= video.id %>?local=true&unique_res=1" type='application/dash+xml' label="dash">
|
<source src="/api/manifest/dash/id/<%= video.id %>?local=true&unique_res=1" type='application/dash+xml' label="<%= HTML.escape(translate(locale,"video_quality_dash_label")) %>">
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
@ -50,7 +52,7 @@
|
|||||||
|
|
||||||
selected = params.quality ? (params.quality == quality) : (i == 0)
|
selected = params.quality ? (params.quality == quality) : (i == 0)
|
||||||
%>
|
%>
|
||||||
<source src="<%= src_url %>" type="<%= mimetype %>" label="<%= quality %>" selected="<%= selected %>">
|
<source src="<%= src_url %>" type="<%= mimetype %>" label="<%= HTML.escape(translate(locale,"video_quality_#{quality}_label")) %>" selected="<%= selected %>">
|
||||||
<% if !params.local && !CONFIG.disabled?("local") %>
|
<% if !params.local && !CONFIG.disabled?("local") %>
|
||||||
<source src="<%= src_url %>&local=true" type="<%= mimetype %>" hidequalityoption="true">
|
<source src="<%= src_url %>&local=true" type="<%= mimetype %>" hidequalityoption="true">
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -54,10 +54,10 @@
|
|||||||
<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")) %>
|
<% next if (option == "dash" && CONFIG.disabled?("dash"))%>
|
||||||
<option value="<%= option %>" <% if preferences.quality == option %> selected <% end %>><%= translate(locale, "preferences_quality_option_" + option) %></option>
|
<% next if (option == "hls" && CONFIG.disabled?("hls"))%>
|
||||||
<% end %>
|
<option value="<%= option %>" <% if preferences.quality == option %> selected <% end %>><%= translate(locale, "preferences_quality_option_" + option) %></option>
|
||||||
<% end %>
|
<% end %>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user