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