mirror of https://github.com/iv-org/invidious.git
Add storyboards and fix image caching
This commit is contained in:
parent
d522c864d4
commit
62a4c82e95
|
@ -2973,6 +2973,9 @@ get "/api/v1/videos/:id" do |env|
|
||||||
json.field "videoThumbnails" do
|
json.field "videoThumbnails" do
|
||||||
generate_thumbnails(json, video.id, config, Kemal.config)
|
generate_thumbnails(json, video.id, config, Kemal.config)
|
||||||
end
|
end
|
||||||
|
json.field "storyboards" do
|
||||||
|
generate_storyboards(json, video.storyboards, config, Kemal.config)
|
||||||
|
end
|
||||||
|
|
||||||
video.description, description = html_to_content(video.description)
|
video.description, description = html_to_content(video.description)
|
||||||
|
|
||||||
|
@ -4348,7 +4351,7 @@ get "/videoplayback" do |env|
|
||||||
url = "/videoplayback?#{query_params.to_s}"
|
url = "/videoplayback?#{query_params.to_s}"
|
||||||
|
|
||||||
headers = HTTP::Headers.new
|
headers = HTTP::Headers.new
|
||||||
{"Accept", "Accept-Encoding", "Connection", "Range"}.each do |header|
|
{"Accept", "Accept-Encoding", "Cache-Control", "Connection", "If-None-Match", "Range"}.each do |header|
|
||||||
if env.request.headers[header]?
|
if env.request.headers[header]?
|
||||||
headers[header] = env.request.headers[header]
|
headers[header] = env.request.headers[header]
|
||||||
end
|
end
|
||||||
|
@ -4445,7 +4448,63 @@ get "/ggpht/*" do |env|
|
||||||
url = env.request.path.lchop("/ggpht")
|
url = env.request.path.lchop("/ggpht")
|
||||||
|
|
||||||
headers = HTTP::Headers.new
|
headers = HTTP::Headers.new
|
||||||
{"Range", "Accept", "Accept-Encoding"}.each do |header|
|
{"Accept", "Accept-Encoding", "Cache-Control", "Connection", "If-None-Match", "Range"}.each do |header|
|
||||||
|
if env.request.headers[header]?
|
||||||
|
headers[header] = env.request.headers[header]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
client.get(url, headers) do |response|
|
||||||
|
env.response.status_code = response.status_code
|
||||||
|
response.headers.each do |key, value|
|
||||||
|
env.response.headers[key] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
if response.status_code == 304
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
chunk_size = 4096
|
||||||
|
size = 1
|
||||||
|
if response.headers.includes_word?("Content-Encoding", "gzip")
|
||||||
|
Gzip::Writer.open(env.response) do |deflate|
|
||||||
|
until size == 0
|
||||||
|
size = IO.copy(response.body_io, deflate)
|
||||||
|
env.response.flush
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elsif response.headers.includes_word?("Content-Encoding", "deflate")
|
||||||
|
Flate::Writer.open(env.response) do |deflate|
|
||||||
|
until size == 0
|
||||||
|
size = IO.copy(response.body_io, deflate)
|
||||||
|
env.response.flush
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
until size == 0
|
||||||
|
size = IO.copy(response.body_io, env.response, chunk_size)
|
||||||
|
env.response.flush
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/sb/:id/:storyboard/:index" do |env|
|
||||||
|
id = env.params.url["id"]
|
||||||
|
storyboard = env.params.url["storyboard"]
|
||||||
|
index = env.params.url["index"]
|
||||||
|
|
||||||
|
if storyboard.starts_with? "storyboard_live"
|
||||||
|
host = "https://i.ytimg.com"
|
||||||
|
else
|
||||||
|
host = "https://i9.ytimg.com"
|
||||||
|
end
|
||||||
|
client = make_client(URI.parse(host))
|
||||||
|
|
||||||
|
url = "/sb/#{id}/#{storyboard}/#{index}?#{env.params.query}"
|
||||||
|
|
||||||
|
headers = HTTP::Headers.new
|
||||||
|
{"Accept", "Accept-Encoding", "Cache-Control", "Connection", "If-None-Match", "Range"}.each do |header|
|
||||||
if env.request.headers[header]?
|
if env.request.headers[header]?
|
||||||
headers[header] = env.request.headers[header]
|
headers[header] = env.request.headers[header]
|
||||||
end
|
end
|
||||||
|
@ -4504,7 +4563,7 @@ get "/vi/:id/:name" do |env|
|
||||||
url = "/vi/#{id}/#{name}"
|
url = "/vi/#{id}/#{name}"
|
||||||
|
|
||||||
headers = HTTP::Headers.new
|
headers = HTTP::Headers.new
|
||||||
{"Range", "Accept", "Accept-Encoding"}.each do |header|
|
{"Accept", "Accept-Encoding", "Cache-Control", "Connection", "If-None-Match", "Range"}.each do |header|
|
||||||
if env.request.headers[header]?
|
if env.request.headers[header]?
|
||||||
headers[header] = env.request.headers[header]
|
headers[header] = env.request.headers[header]
|
||||||
end
|
end
|
||||||
|
|
|
@ -473,6 +473,75 @@ struct Video
|
||||||
return @player_json.not_nil!
|
return @player_json.not_nil!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def storyboards
|
||||||
|
storyboards = self.player_response["storyboards"]?
|
||||||
|
.try &.as_h
|
||||||
|
.try &.["playerStoryboardSpecRenderer"]?
|
||||||
|
|
||||||
|
if !storyboards
|
||||||
|
storyboards = self.player_response["storyboards"]?
|
||||||
|
.try &.as_h
|
||||||
|
.try &.["playerLiveStoryboardSpecRenderer"]?
|
||||||
|
|
||||||
|
if storyboard = storyboards.try &.["spec"]?
|
||||||
|
.try &.as_s
|
||||||
|
return [{
|
||||||
|
url: storyboard.split("#")[0].sub("M$M", "$N"),
|
||||||
|
width: 106,
|
||||||
|
height: 60,
|
||||||
|
count: -1,
|
||||||
|
interval: 5000,
|
||||||
|
storyboard_width: 3,
|
||||||
|
storyboard_height: 3,
|
||||||
|
storyboard_count: -1,
|
||||||
|
}]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
storyboards = storyboards.try &.["spec"]?
|
||||||
|
.try &.as_s.split("|")
|
||||||
|
|
||||||
|
items = [] of NamedTuple(
|
||||||
|
url: String,
|
||||||
|
width: Int32,
|
||||||
|
height: Int32,
|
||||||
|
count: Int32,
|
||||||
|
interval: Int32,
|
||||||
|
storyboard_width: Int32,
|
||||||
|
storyboard_height: Int32,
|
||||||
|
storyboard_count: Int32)
|
||||||
|
|
||||||
|
if !storyboards
|
||||||
|
return items
|
||||||
|
end
|
||||||
|
|
||||||
|
url = storyboards.shift
|
||||||
|
|
||||||
|
storyboards.each_with_index do |storyboard, i|
|
||||||
|
width, height, count, storyboard_width, storyboard_height, interval, _, sigh = storyboard.split("#")
|
||||||
|
|
||||||
|
width = width.to_i
|
||||||
|
height = height.to_i
|
||||||
|
count = count.to_i
|
||||||
|
interval = interval.to_i
|
||||||
|
storyboard_width = storyboard_width.to_i
|
||||||
|
storyboard_height = storyboard_height.to_i
|
||||||
|
|
||||||
|
items << {
|
||||||
|
url: "#{url}&sigh=#{sigh}".sub("$L", i),
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
count: count,
|
||||||
|
interval: interval,
|
||||||
|
storyboard_width: storyboard_width,
|
||||||
|
storyboard_height: storyboard_height,
|
||||||
|
storyboard_count: (count.to_f / (storyboard_width.to_f * storyboard_height.to_f)).ceil.to_i,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
items
|
||||||
|
end
|
||||||
|
|
||||||
def paid
|
def paid
|
||||||
reason = self.player_response["playabilityStatus"]?.try &.["reason"]?
|
reason = self.player_response["playabilityStatus"]?.try &.["reason"]?
|
||||||
|
|
||||||
|
@ -1062,3 +1131,20 @@ def generate_thumbnails(json, id, config, kemal_config)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def generate_storyboards(json, storyboards, config, kemal_config)
|
||||||
|
json.array do
|
||||||
|
storyboards.each do |storyboard|
|
||||||
|
json.object do
|
||||||
|
json.field "url", storyboard[:url]
|
||||||
|
json.field "width", storyboard[:width]
|
||||||
|
json.field "height", storyboard[:height]
|
||||||
|
json.field "count", storyboard[:count]
|
||||||
|
json.field "interval", storyboard[:interval]
|
||||||
|
json.field "storyboardWidth", storyboard[:storyboard_width]
|
||||||
|
json.field "storyboardHeight", storyboard[:storyboard_height]
|
||||||
|
json.field "storyboardCount", storyboard[:storyboard_count]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue