diff options
Diffstat (limited to 'youtube/watch.py')
-rw-r--r-- | youtube/watch.py | 127 |
1 files changed, 24 insertions, 103 deletions
diff --git a/youtube/watch.py b/youtube/watch.py index 3ca39ad..47a93bf 100644 --- a/youtube/watch.py +++ b/youtube/watch.py @@ -24,97 +24,25 @@ except FileNotFoundError: def get_video_sources(info): - '''return dict with organized sources: { - 'uni_sources': [{}, ...], # video and audio in one file - 'uni_idx': int, # default unified source index - 'pair_sources': [({video}, {audio}), ...], - 'pair_idx': int, # default pair source index - } - ''' - audio_sources = [] - video_only_sources = [] - uni_sources = [] - pair_sources = [] - target_resolution = settings.default_resolution + video_sources = [] + max_resolution = settings.default_resolution for fmt in info['formats']: - if not all(fmt[attr] for attr in ('ext', 'url')): - continue - if fmt['ext'] != 'mp4': # temporary until webm support + if not all(fmt[attr] for attr in ('quality', 'width', 'ext', 'url')): continue - - # unified source - if fmt['acodec'] and fmt['vcodec']: - source = { + if (fmt['acodec'] and fmt['vcodec'] + and fmt['quality'] <= max_resolution): + video_sources.append({ + 'src': fmt['url'], 'type': 'video/' + fmt['ext'], - } - source.update(fmt) - uni_sources.append(source) - continue - - if not (fmt['init_range'] and fmt['index_range']): - continue + 'quality': fmt['quality'], + 'height': fmt['height'], + 'width': fmt['width'], + }) - # audio source - if fmt['acodec'] and not fmt['vcodec'] and fmt['audio_bitrate']: - source = { - 'type': 'audio/' + fmt['ext'], - 'bitrate': fmt['audio_bitrate'], - } - source.update(fmt) - source['mime_codec'] = (source['type'] + '; codecs="' - + source['acodec'] + '"') - audio_sources.append(source) - # video-only source, include audio source - elif all(fmt[attr] for attr in ('vcodec', 'quality', 'width')): - source = { - 'type': 'video/' + fmt['ext'], - } - source.update(fmt) - source['mime_codec'] = (source['type'] + '; codecs="' - + source['vcodec'] + '"') - video_only_sources.append(source) - - audio_sources.sort(key=lambda source: source['audio_bitrate']) - video_only_sources.sort(key=lambda src: src['quality']) - uni_sources.sort(key=lambda src: src['quality']) - - for source in video_only_sources: - # choose an audio source to go with it - # 0.15 is semiarbitrary empirical constant to spread audio sources - # between 144p and 1080p. Use something better eventually. - target_audio_bitrate = source['quality']*source.get('fps', 30)/30*0.15 - compat_audios = [a for a in audio_sources if a['ext'] == source['ext']] - if compat_audios: - closest_audio_source = compat_audios[0] - best_err = target_audio_bitrate - compat_audios[0]['audio_bitrate'] - best_err = abs(best_err) - for audio_source in compat_audios[1:]: - err = abs(audio_source['audio_bitrate'] - target_audio_bitrate) - # once err gets worse we have passed the closest one - if err > best_err: - break - best_err = err - closest_audio_source = audio_source - pair_sources.append((source, closest_audio_source)) - - uni_idx = 0 if uni_sources else None - for i, source in enumerate(uni_sources): - if source['quality'] > target_resolution: - break - uni_idx = i - - pair_idx = 0 if pair_sources else None - for i, source_pair in enumerate(pair_sources): - if source_pair[0]['quality'] > target_resolution: - break - pair_idx = i + # order the videos sources so the preferred resolution is first # + video_sources.sort(key=lambda source: source['quality'], reverse=True) - return { - 'uni_sources': uni_sources, - 'uni_idx': uni_idx, - 'pair_sources': pair_sources, - 'pair_idx': pair_idx, - } + return video_sources def make_caption_src(info, lang, auto=False, trans_lang=None): @@ -510,11 +438,10 @@ def get_watch_page(video_id=None): item['url'] += '&index=' + str(item['index']) info['playlist']['author_url'] = util.prefix_url( info['playlist']['author_url']) - if settings.img_prefix: - # Don't prefix hls_formats for now because the urls inside the manifest - # would need to be prefixed as well. - for fmt in info['formats']: - fmt['url'] = util.prefix_url(fmt['url']) + # Don't prefix hls_formats for now because the urls inside the manifest + # would need to be prefixed as well. + for fmt in info['formats']: + fmt['url'] = util.prefix_url(fmt['url']) # Add video title to end of url path so it has a filename other than just # "videoplayback" when downloaded @@ -550,14 +477,9 @@ def get_watch_page(video_id=None): 'codecs': codecs_string, }) - source_info = get_video_sources(info) - uni_idx = source_info['uni_idx'] - video_height = yt_data_extract.deep_get(source_info, 'uni_sources', - uni_idx, 'height', - default=360) - video_width = yt_data_extract.deep_get(source_info, 'uni_sources', - uni_idx, 'width', - default=640) + video_sources = get_video_sources(info) + video_height = yt_data_extract.deep_get(video_sources, 0, 'height', default=360) + video_width = yt_data_extract.deep_get(video_sources, 0, 'width', default=640) # 1 second per pixel, or the actual video width theater_video_target_width = max(640, info['duration'] or 0, video_width) @@ -602,6 +524,7 @@ def get_watch_page(video_id=None): download_formats = download_formats, other_downloads = other_downloads, video_info = json.dumps(video_info), + video_sources = video_sources, hls_formats = info['hls_formats'], subtitle_sources = subtitle_sources, related = info['related_videos'], @@ -634,14 +557,12 @@ def get_watch_page(video_id=None): time_start = time_start, js_data = { - 'video_id': info['id'], - 'video_duration': info['duration'], + 'video_id': video_info['id'], 'settings': settings.current_settings_dict, 'has_manual_captions': any(s.get('on') for s in subtitle_sources), - **source_info, }, + # for embed page font_family=youtube.font_choices[settings.font], - **source_info, ) |