feat: storyboard generation (json, webvtt) and proxy
adds support for video storyboard extraction, generation and proxying
This commit is contained in:
93
ythdd_struct_builder.py
Normal file
93
ythdd_struct_builder.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from ythdd_globals import safeTraverse
|
||||
import ythdd_globals
|
||||
|
||||
def genThumbs(videoId: str):
|
||||
|
||||
result = []
|
||||
thumbnails = [
|
||||
{'height': 720, 'width': 1280, 'quality': "maxres", 'url': "maxres"}, # will always attempt to return the best quality available
|
||||
{'height': 720, 'width': 1280, 'quality': "maxresdefault", 'url': "maxresdefault"},
|
||||
{'height': 480, 'width': 640, 'quality': "sddefault", 'url': "sddefault"},
|
||||
{'height': 360, 'width': 480, 'quality': "high", 'url': "hqdefault"},
|
||||
{'height': 180, 'width': 320, 'quality': "medium", 'url': "mqdefault"},
|
||||
{'height': 90, 'width': 120, 'quality': "default", 'url': "default"},
|
||||
{'height': 90, 'width': 120, 'quality': "start", 'url': "1"},
|
||||
{'height': 90, 'width': 120, 'quality': "middle", 'url': "2"},
|
||||
{'height': 90, 'width': 120, 'quality': "end", 'url': "3"},
|
||||
]
|
||||
|
||||
for x in thumbnails:
|
||||
width = x['width']
|
||||
height = x['height']
|
||||
quality = x['quality']
|
||||
url = ythdd_globals.config['general']['public_facing_url'] + 'vi/' + videoId + '/' + x['url'] + '.jpg'
|
||||
result.append({'quality': quality, 'url': url, 'width': width, 'height': height})
|
||||
|
||||
return result
|
||||
|
||||
def genStoryboards(video_id: str) -> list:
|
||||
# generates storyboards inside of /api/v1/videos/:video_id
|
||||
storyboards = []
|
||||
cached_storyboards = safeTraverse(ythdd_globals.general_cache["storyboards"], [video_id], default=[])
|
||||
for sb in cached_storyboards["formats"]:
|
||||
built_storyboard = {
|
||||
"url": f"/api/v1/storyboards/{video_id}?width={sb['width']}&height={sb['height']}",
|
||||
"templateUrl": cached_storyboards['template_url'].replace("$L", str(sb['index'])).replace("$N", sb['name']) + f"&sigh={sb['sigh']}",
|
||||
"width": sb['width'],
|
||||
"height": sb['height'],
|
||||
"count": sb['thumb_count'],
|
||||
"interval": sb['interval'],
|
||||
"storyboardWidth": sb['columns'],
|
||||
"storyboardHeight": sb['rows'],
|
||||
"storyboardCount": sb['images_count']
|
||||
}
|
||||
storyboards.append(built_storyboard)
|
||||
|
||||
return storyboards
|
||||
|
||||
def msToWebvttTimestamp(time: int):
|
||||
|
||||
ms = time % 1000
|
||||
time //= 1000
|
||||
|
||||
hours = time // (60 * 60)
|
||||
time -= hours * 60 * 60
|
||||
minutes = time // 60
|
||||
time -= minutes * 60
|
||||
seconds = time
|
||||
timestamp = f"{str(hours).zfill(2)}:{str(minutes).zfill(2)}:{str(seconds).zfill(2)}.{str(ms).zfill(3)}"
|
||||
|
||||
return timestamp
|
||||
|
||||
def genWebvttStoryboard(video_id: str, width: int = None, height: int = None):
|
||||
# generates WebVTT storyboards for /api/v1/storyboards/:video_id
|
||||
webvtt = "WEBVTT\n\n"
|
||||
cached_storyboards = safeTraverse(ythdd_globals.general_cache["storyboards"], [video_id])
|
||||
if cached_storyboards is None:
|
||||
return ""
|
||||
found_storyboard = {}
|
||||
|
||||
for sb in cached_storyboards["formats"]:
|
||||
if width is not None and width == sb['width']:
|
||||
found_storyboard = sb
|
||||
if height is not None and height == sb['height']:
|
||||
found_storyboard = sb
|
||||
|
||||
# could be changed
|
||||
if not found_storyboard:
|
||||
found_storyboard = cached_storyboards["formats"][0]
|
||||
|
||||
start = 0
|
||||
thumbs_per_sb = sb['columns'] * sb['rows']
|
||||
xx = 0
|
||||
yy = 0
|
||||
for x in range(found_storyboard["thumb_count"]):
|
||||
xx = x % sb['columns']
|
||||
yy = (x // sb['rows']) % sb['rows']
|
||||
xywh = f"#xywh={xx * sb['width']},{yy * sb['height']},{sb['width']},{sb['height']}"
|
||||
webvtt += f"{msToWebvttTimestamp(start)} --> {msToWebvttTimestamp(start + found_storyboard['interval'])}\n"
|
||||
webvtt += cached_storyboards['template_url'].replace("$L", str(sb['index'])).replace("$N", sb['name']).replace("$M", str(x // (thumbs_per_sb))) + f"&sigh={sb['sigh']}{xywh}\n"
|
||||
webvtt += "\n"
|
||||
start += found_storyboard['interval']
|
||||
|
||||
return webvtt
|
||||
Reference in New Issue
Block a user