Fix chunk size for livestreams

pull/633/head
Omar Roth 6 years ago
parent 8033d1ca6d
commit 1277c3d156
No known key found for this signature in database
GPG Key ID: B8254FB7EC3D37F2

@ -4429,6 +4429,7 @@ get "/api/manifest/hls_variant/*" do |env|
manifest manifest
end end
# TODO: Fix redirect for local streams
get "/api/manifest/hls_playlist/*" do |env| get "/api/manifest/hls_playlist/*" do |env|
client = make_client(YT_URL) client = make_client(YT_URL)
manifest = client.get(env.request.path) manifest = client.get(env.request.path)
@ -4641,93 +4642,118 @@ get "/videoplayback" do |env|
next next
end end
content_length = nil if url.includes? "&file=seg.ts"
first_chunk = true begin
range_start, range_end = parse_range(env.request.headers["Range"]?) client = make_client(URI.parse(host), region)
chunk_start = range_start client.get(url, headers) do |response|
chunk_end = range_end response.headers.each do |key, value|
if !RESPONSE_HEADERS_BLACKLIST.includes?(key)
env.response.headers[key] = value
end
end
if !chunk_end || chunk_end - chunk_start > HTTP_CHUNK_SIZE env.response.headers["Access-Control-Allow-Origin"] = "*"
chunk_end = chunk_start + HTTP_CHUNK_SIZE - 1
end
# TODO: Record bytes written so we can restart after a chunk fails if location = response.headers["Location"]?
while true location = URI.parse(location)
if !range_end && content_length location = "#{location.full_path}&host=#{location.host}"
range_end = content_length
end
if range_end && chunk_start > range_end if region
break location += "&region=#{region}"
end
next env.redirect location
end
IO.copy(response.body_io, env.response)
end
rescue ex
end end
else
content_length = nil
first_chunk = true
range_start, range_end = parse_range(env.request.headers["Range"]?)
chunk_start = range_start
chunk_end = range_end
if range_end && chunk_end > range_end if !chunk_end || chunk_end - chunk_start > HTTP_CHUNK_SIZE
chunk_end = range_end chunk_end = chunk_start + HTTP_CHUNK_SIZE - 1
end end
headers["Range"] = "bytes=#{chunk_start}-#{chunk_end}" # TODO: Record bytes written so we can restart after a chunk fails
client = make_client(URI.parse(host), region) while true
begin if !range_end && content_length
client.get(url, headers) do |response| range_end = content_length
if first_chunk end
if !env.request.headers["Range"]? && response.status_code == 206
env.response.status_code = 200
else
env.response.status_code = response.status_code
end
response.headers.each do |key, value| if range_end && chunk_start > range_end
if !RESPONSE_HEADERS_BLACKLIST.includes?(key) && key != "Content-Range" break
env.response.headers[key] = value end
end
end
env.response.headers["Access-Control-Allow-Origin"] = "*" if range_end && chunk_end > range_end
chunk_end = range_end
end
if location = response.headers["Location"]? headers["Range"] = "bytes=#{chunk_start}-#{chunk_end}"
location = URI.parse(location)
location = "#{location.full_path}&host=#{location.host}"
if region begin
location += "&region=#{region}" client = make_client(URI.parse(host), region)
client.get(url, headers) do |response|
if first_chunk
if !env.request.headers["Range"]? && response.status_code == 206
env.response.status_code = 200
else
env.response.status_code = response.status_code
end end
env.redirect location response.headers.each do |key, value|
break if !RESPONSE_HEADERS_BLACKLIST.includes?(key) && key != "Content-Range"
end env.response.headers[key] = value
end
end
if title = query_params["title"]? env.response.headers["Access-Control-Allow-Origin"] = "*"
# https://blog.fastmail.com/2011/06/24/download-non-english-filenames/
env.response.headers["Content-Disposition"] = "attachment; filename=\"#{URI.escape(title)}\"; filename*=UTF-8''#{URI.escape(title)}"
end
if !response.headers.includes_word?("Transfer-Encoding", "chunked") if location = response.headers["Location"]?
content_length = response.headers["Content-Range"].split("/")[-1].to_i64 location = URI.parse(location)
if env.request.headers["Range"]? location = "#{location.full_path}&host=#{location.host}"
env.response.headers["Content-Range"] = "bytes #{range_start}-#{range_end || (content_length - 1)}/#{content_length}"
env.response.content_length = ((range_end.try &.+ 1) || content_length) - range_start if region
else location += "&region=#{region}"
env.response.content_length = content_length end
env.redirect location
break
end
if title = query_params["title"]?
# https://blog.fastmail.com/2011/06/24/download-non-english-filenames/
env.response.headers["Content-Disposition"] = "attachment; filename=\"#{URI.escape(title)}\"; filename*=UTF-8''#{URI.escape(title)}"
end
if !response.headers.includes_word?("Transfer-Encoding", "chunked")
content_length = response.headers["Content-Range"].split("/")[-1].to_i64
if env.request.headers["Range"]?
env.response.headers["Content-Range"] = "bytes #{range_start}-#{range_end || (content_length - 1)}/#{content_length}"
env.response.content_length = ((range_end.try &.+ 1) || content_length) - range_start
else
env.response.content_length = content_length
end
end end
end end
end
proxy_file(response, env) proxy_file(response, env)
end
rescue ex
if ex.message != "Error reading socket: Connection reset by peer"
break
end
end end
# For livestream segments, break after first chunk chunk_start = chunk_end + 1
if url.includes? "&file=seg.ts" chunk_end += HTTP_CHUNK_SIZE
break first_chunk = false
end
rescue ex
if ex.message != "Error reading socket: Connection reset by peer"
break
end
end end
chunk_start = chunk_end + 1
chunk_end += HTTP_CHUNK_SIZE
first_chunk = false
end end
end end

Loading…
Cancel
Save