~cadence/tube-devel

NewLeaf: Partially fix #18 proxy non-adaptative format videos through new /videoplayback endpoint v1 PROPOSED

As discussed a while ago, this is my current progress for #18, I use
this version of the code since the date of this commit and this is
functional. It's especially useful for the " - Topic" channels auto-
generated music videos.
Though, I didn't manage to have DASH streams to work proxied, so this MR
only proxies the regular non-adaptative streams.

As this is very much WIP, don't merge probably. I'm also not happy with
the verbose `for k, v in r.headers.items():` loop to set headers in
server-side requests.

Lomanic (1):
  Partially fix #18 proxy non-adaptative format videos through new
    /videoplayback endpoint

 configuration.sample.py |  3 +++
 extractors/video.py     |  3 ++-
 index.py                | 18 ++++++++++++++++++
 3 files changed, 23 insertions(+), 1 deletion(-)

-- 
2.34.4
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~cadence/tube-devel/patches/34772/mbox | git am -3
Learn more about email & git

[PATCH NewLeaf 1/1] Partially fix #18 proxy non-adaptative format videos through new /videoplayback endpoint Export this patch

From: Lomanic <lomanic@hotmail.fr>

Configured instance-wide with a boolean in configuration.py
Disabled by default
---
 configuration.sample.py |  3 +++
 extractors/video.py     |  3 ++-
 index.py                | 18 ++++++++++++++++++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/configuration.sample.py b/configuration.sample.py
index 470892f..63156e3 100644
--- a/configuration.sample.py
+++ b/configuration.sample.py
@@ -16,3 +16,6 @@ website_origin = "http://example.com:3000"

# The port to bind to.
#bind_port = 3000

# Tell NewLeaf to proxy video streams
# proxy_videos = False
diff --git a/extractors/video.py b/extractors/video.py
index 68fc86a..4e8ec64 100644
--- a/extractors/video.py
+++ b/extractors/video.py
@@ -14,6 +14,7 @@ from urllib.parse import parse_qs, urlparse, urlencode
from cachetools import TTLCache

video_cache = TTLCache(maxsize=50, ttl=300)
proxy_videos = getattr(configuration, "proxy_videos", False)

ytdl_opts = {
	"quiet": True,
@@ -157,7 +158,7 @@ def extract_video(id):
				})
			else: # format is not adaptive
				result["formatStreams"].append({
					"url": format["url"],
					"url": "{}/videoplayback?{}".format(configuration.website_origin, urlencode({"url": format["url"]})) if proxy_videos else format["url"],
					"itag": format["format_id"],
					"type": result_type,
					"second__mime": mime,
diff --git a/index.py b/index.py
index 482c6d5..a5d7da6 100644
--- a/index.py
+++ b/index.py
@@ -3,6 +3,7 @@ import json
import pathlib
import requests
import yt_dlp
from urllib.parse import urlparse
from extractors.video import extract_video
from extractors.channel import extract_channel, extract_channel_videos, extract_channel_latest
from extractors.manifest import extract_manifest
@@ -141,6 +142,23 @@ class NewLeaf(object):
		cherrypy.response.headers["content-type"] = r.headers["content-type"]
		return next(r.iter_content(chunk_size=None))

	@cherrypy.expose
	def videoplayback(self, url):
		proxy_videos = getattr(configuration, "proxy_videos", False)
		if not proxy_videos:
			raise cherrypy.HTTPError(401, "Unauthorized")
		u = urlparse(url)
		if not (u.hostname.endswith(".googlevideo.com") and u.path == "/videoplayback"):
			raise cherrypy.HTTPError(401, "Unauthorized")
		headers = {k: v for k, v in cherrypy.request.headers.items() if k.lower() not in ["host", "remote-addr"] and not k.lower().startswith("x-")}
		with requests.get(url, headers=headers, stream=True) as r:
			r.raise_for_status()
			for k, v in r.headers.items():
				cherrypy.response.headers[k] = v
			cherrypy.response.status = r.status_code
			# return 5MB at a time, the browser will ask for the next chunk thanks to HTTP 206 Partial Content streaming magic
			return next(r.iter_content(chunk_size=5*1024*1024))

bind_port = getattr(configuration, "bind_port", 3000)
bind_host = getattr(configuration, "bind_host", "0.0.0.0")
server_root = pathlib.Path(__file__).parent.joinpath("root")
-- 
2.34.4