From ac1319e7204200577eb8aba74655de8b3e2d4f0a Mon Sep 17 00:00:00 2001 From: James Taylor Date: Mon, 16 Jul 2018 02:05:46 -0700 Subject: Support for downloading video in all available formats --- youtube/shared.css | 38 ++++++++++++++++++++++++++++++++------ youtube/watch.py | 48 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 66 insertions(+), 20 deletions(-) (limited to 'youtube') diff --git a/youtube/shared.css b/youtube/shared.css index 33acb4f..6803e05 100644 --- a/youtube/shared.css +++ b/youtube/shared.css @@ -1,4 +1,4 @@ -h1, h2, h3, h4, h5, h6, div{ +h1, h2, h3, h4, h5, h6, div, button{ margin:0; padding:0; @@ -32,9 +32,6 @@ body{ grid-row: 2; } -button{ - padding:0; /* Fuck browser-specific styling. Fix your shit mozilla */ -} address{ font-style:normal; } @@ -126,7 +123,7 @@ address{ .full-item{ display: grid; - grid-template-rows: 0fr 0fr 0fr 0fr 0fr; + grid-template-rows: 0fr 0fr 0fr 0fr 20px 0fr 0fr; grid-template-columns: 1fr 1fr; align-content: start; } @@ -372,4 +369,33 @@ address{ border-width: 2px; font-weight: bold; text-align: center; - } \ No newline at end of file + } + + +.dropdown{ + z-index:1; + justify-self:start; + min-width:0px; +} + + .dropdown-label{ + background-color: #e9e9e9; + border-style: outset; + border-width: 2px; + font-weight: bold; + } + + .dropdown-content{ + display:none; + background-color: #e9e9e9; + } + .dropdown:hover .dropdown-content { + display: grid; + grid-auto-rows:30px; + } + .dropdown-content a{ + white-space: nowrap; + display:grid; + grid-template-columns: 60px 90px auto; + max-height: 1.2em; + } \ No newline at end of file diff --git a/youtube/watch.py b/youtube/watch.py index 5bf6ebb..94e1e78 100644 --- a/youtube/watch.py +++ b/youtube/watch.py @@ -211,22 +211,28 @@ def watch_page_related_playlist_info(item): def sort_formats(info): - info['formats'].sort(key=lambda x: default_multi_get(_formats, x['format_id'], 'height', default=0)) - for index, format in enumerate(info['formats']): + sorted_formats = info['formats'].copy() + sorted_formats.sort(key=lambda x: default_multi_get(_formats, x['format_id'], 'height', default=0)) + for index, format in enumerate(sorted_formats): if default_multi_get(_formats, format['format_id'], 'height', default=0) >= 360: break - info['formats'] = info['formats'][index:] + info['formats'][0:index] - info['formats'] = [format for format in info['formats'] if format['acodec'] != 'none' and format['vcodec'] != 'none'] - -def formats_html(info): + sorted_formats = sorted_formats[index:] + sorted_formats[0:index] + sorted_formats = [format for format in info['formats'] if format['acodec'] != 'none' and format['vcodec'] != 'none'] + return sorted_formats + +source_tag_template = Template(''' +''') +def formats_html(formats): result = '' - for format in info['formats']: + for format in formats: result += source_tag_template.substitute( src=format['url'], type='audio/' + format['ext'] if format['vcodec'] == "none" else 'video/' + format['ext'], ) return result - + + + def choose_format(info): suitable_formats = [] with open('teste.txt', 'w', encoding='utf-8') as f: @@ -279,14 +285,16 @@ def subtitles_html(info): more_comments_template = Template('''More comments''') -source_tag_template = Template(''' -''') + +download_link_template = Template(''' + $ext $resolution $note''') def get_watch_page(query_string): id = urllib.parse.parse_qs(query_string)['v'][0] + downloader = YoutubeDL(params={'youtube_include_dash_manifest':False}) tasks = ( gevent.spawn(comments.video_comments, id ), - gevent.spawn(YoutubeDL(params={'youtube_include_dash_manifest':False}).extract_info, "https://www.youtube.com/watch?v=" + id, download=False) + gevent.spawn(downloader.extract_info, "https://www.youtube.com/watch?v=" + id, download=False) ) gevent.joinall(tasks) comments_info, info = tasks[0].value, tasks[1].value @@ -300,7 +308,7 @@ def get_watch_page(query_string): #info = YoutubeDL().extract_info(url, download=False) #chosen_format = choose_format(info) - sort_formats(info) + sorted_formats = sort_formats(info) video_info = { "duration": common.seconds_to_timestamp(info["duration"]), @@ -318,7 +326,18 @@ def get_watch_page(query_string): related_videos_html = get_related_items_html(info) else: related_videos_html = '' - + + + + download_options = '' + for format in info['formats']: + download_options += download_link_template.substitute( + url = html.escape(format['url']), + ext = html.escape(format['ext']), + resolution = html.escape(downloader.format_resolution(format)), + note = html.escape(downloader._format_note(format)), + ) + page = yt_watch_template.substitute( video_title = html.escape(info["title"]), page_title = html.escape(info["title"]), @@ -329,9 +348,10 @@ def get_watch_page(query_string): views = (lambda x: '{:,}'.format(x) if x is not None else "")(info.get("view_count", None)), likes = (lambda x: '{:,}'.format(x) if x is not None else "")(info.get("like_count", None)), dislikes = (lambda x: '{:,}'.format(x) if x is not None else "")(info.get("dislike_count", None)), + download_options = download_options, video_info = html.escape(json.dumps(video_info)), description = html.escape(info["description"]), - video_sources = formats_html(info) + subtitles_html(info), + video_sources = formats_html(sorted_formats) + subtitles_html(info), related = related_videos_html, comments = comments_html, more_comments_button = more_comments_button, -- cgit v1.2.3