mirror of
				https://gitea.invidious.io/iv-org/invidious-copy-2023-06-08.git
				synced 2024-08-15 00:53:38 +00:00 
			
		
		
		
	Fix chunk size for livestreams
This commit is contained in:
		
							parent
							
								
									8033d1ca6d
								
							
						
					
					
						commit
						1277c3d156
					
				
					 1 changed files with 103 additions and 77 deletions
				
			
		
							
								
								
									
										180
									
								
								src/invidious.cr
									
										
									
									
									
								
							
							
						
						
									
										180
									
								
								src/invidious.cr
									
										
									
									
									
								
							| 
						 | 
					@ -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
 | 
					 | 
				
			||||||
  range_start, range_end = parse_range(env.request.headers["Range"]?)
 | 
					 | 
				
			||||||
  chunk_start = range_start
 | 
					 | 
				
			||||||
  chunk_end = range_end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if !chunk_end || chunk_end - chunk_start > HTTP_CHUNK_SIZE
 | 
					 | 
				
			||||||
    chunk_end = chunk_start + HTTP_CHUNK_SIZE - 1
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # TODO: Record bytes written so we can restart after a chunk fails
 | 
					 | 
				
			||||||
  while true
 | 
					 | 
				
			||||||
    if !range_end && content_length
 | 
					 | 
				
			||||||
      range_end = content_length
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if range_end && chunk_start > range_end
 | 
					 | 
				
			||||||
      break
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if range_end && chunk_end > range_end
 | 
					 | 
				
			||||||
      chunk_end = range_end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    headers["Range"] = "bytes=#{chunk_start}-#{chunk_end}"
 | 
					 | 
				
			||||||
    client = make_client(URI.parse(host), region)
 | 
					 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
 | 
					      client = make_client(URI.parse(host), region)
 | 
				
			||||||
      client.get(url, headers) do |response|
 | 
					      client.get(url, headers) do |response|
 | 
				
			||||||
        if first_chunk
 | 
					        response.headers.each do |key, value|
 | 
				
			||||||
          if !env.request.headers["Range"]? && response.status_code == 206
 | 
					          if !RESPONSE_HEADERS_BLACKLIST.includes?(key)
 | 
				
			||||||
            env.response.status_code = 200
 | 
					            env.response.headers[key] = value
 | 
				
			||||||
          else
 | 
					 | 
				
			||||||
            env.response.status_code = response.status_code
 | 
					 | 
				
			||||||
          end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          response.headers.each do |key, value|
 | 
					 | 
				
			||||||
            if !RESPONSE_HEADERS_BLACKLIST.includes?(key) && key != "Content-Range"
 | 
					 | 
				
			||||||
              env.response.headers[key] = value
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
          end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          if location = response.headers["Location"]?
 | 
					 | 
				
			||||||
            location = URI.parse(location)
 | 
					 | 
				
			||||||
            location = "#{location.full_path}&host=#{location.host}"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if region
 | 
					 | 
				
			||||||
              location += "®ion=#{region}"
 | 
					 | 
				
			||||||
            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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        proxy_file(response, env)
 | 
					        env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      # For livestream segments, break after first chunk
 | 
					        if location = response.headers["Location"]?
 | 
				
			||||||
      if url.includes? "&file=seg.ts"
 | 
					          location = URI.parse(location)
 | 
				
			||||||
        break
 | 
					          location = "#{location.full_path}&host=#{location.host}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if region
 | 
				
			||||||
 | 
					            location += "®ion=#{region}"
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          next env.redirect location
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IO.copy(response.body_io, env.response)
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    rescue ex
 | 
					    rescue ex
 | 
				
			||||||
      if ex.message != "Error reading socket: Connection reset by peer"
 | 
					    end
 | 
				
			||||||
        break
 | 
					  else
 | 
				
			||||||
      end
 | 
					    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 !chunk_end || chunk_end - chunk_start > HTTP_CHUNK_SIZE
 | 
				
			||||||
 | 
					      chunk_end = chunk_start + HTTP_CHUNK_SIZE - 1
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chunk_start = chunk_end + 1
 | 
					    # TODO: Record bytes written so we can restart after a chunk fails
 | 
				
			||||||
    chunk_end += HTTP_CHUNK_SIZE
 | 
					    while true
 | 
				
			||||||
    first_chunk = false
 | 
					      if !range_end && content_length
 | 
				
			||||||
 | 
					        range_end = content_length
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if range_end && chunk_start > range_end
 | 
				
			||||||
 | 
					        break
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if range_end && chunk_end > range_end
 | 
				
			||||||
 | 
					        chunk_end = range_end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      headers["Range"] = "bytes=#{chunk_start}-#{chunk_end}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      begin
 | 
				
			||||||
 | 
					        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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            response.headers.each do |key, value|
 | 
				
			||||||
 | 
					              if !RESPONSE_HEADERS_BLACKLIST.includes?(key) && key != "Content-Range"
 | 
				
			||||||
 | 
					                env.response.headers[key] = value
 | 
				
			||||||
 | 
					              end
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if location = response.headers["Location"]?
 | 
				
			||||||
 | 
					              location = URI.parse(location)
 | 
				
			||||||
 | 
					              location = "#{location.full_path}&host=#{location.host}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              if region
 | 
				
			||||||
 | 
					                location += "®ion=#{region}"
 | 
				
			||||||
 | 
					              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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          proxy_file(response, env)
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      rescue ex
 | 
				
			||||||
 | 
					        if ex.message != "Error reading socket: Connection reset by peer"
 | 
				
			||||||
 | 
					          break
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      chunk_start = chunk_end + 1
 | 
				
			||||||
 | 
					      chunk_end += HTTP_CHUNK_SIZE
 | 
				
			||||||
 | 
					      first_chunk = false
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue