diff options
Diffstat (limited to 'youtube')
-rw-r--r-- | youtube/templates/watch.html | 41 | ||||
-rw-r--r-- | youtube/watch.py | 3 | ||||
-rw-r--r-- | youtube/yt_data_extract.py | 17 |
3 files changed, 40 insertions, 21 deletions
diff --git a/youtube/templates/watch.html b/youtube/templates/watch.html index e97b638..da3b336 100644 --- a/youtube/templates/watch.html +++ b/youtube/templates/watch.html @@ -14,6 +14,19 @@ text-decoration: underline; } + .playability-error{ + height: 360px; + width: 640px; + grid-column: 2; + background-color: var(--video-background-color); + text-align:center; + } + .playability-error span{ + position: relative; + top: 50%; + transform: translate(-50%, -50%); + } + {% if theater_mode %} video{ grid-column: 1 / span 5; @@ -202,20 +215,24 @@ {% endblock style %} {% block main %} - <video controls autofocus> - {% for video_source in video_sources %} - <source src="{{ video_source['src'] }}" type="{{ video_source['type'] }}"> - {% endfor %} + {% if playability_error %} + <div class="playability-error"><span>{{ 'Error: ' + playability_error }}</span></div> + {% else %} + <video controls autofocus class="video"> + {% for video_source in video_sources %} + <source src="{{ video_source['src'] }}" type="{{ video_source['type'] }}"> + {% endfor %} - {% for source in subtitle_sources %} - {% if source['on'] %} - <track label="{{ source['label'] }}" src="{{ source['url'] }}" kind="subtitles" srclang="{{ source['srclang'] }}" default> - {% else %} - <track label="{{ source['label'] }}" src="{{ source['url'] }}" kind="subtitles" srclang="{{ source['srclang'] }}"> - {% endif %} - {% endfor %} + {% for source in subtitle_sources %} + {% if source['on'] %} + <track label="{{ source['label'] }}" src="{{ source['url'] }}" kind="subtitles" srclang="{{ source['srclang'] }}" default> + {% else %} + <track label="{{ source['label'] }}" src="{{ source['url'] }}" kind="subtitles" srclang="{{ source['srclang'] }}"> + {% endif %} + {% endfor %} - </video> + </video> + {% endif %} <div class="video-info"> <h2 class="title">{{ title }}</h2> diff --git a/youtube/watch.py b/youtube/watch.py index 959dca2..8a396a7 100644 --- a/youtube/watch.py +++ b/youtube/watch.py @@ -123,7 +123,7 @@ decrypt_function_re = re.compile(r'function\(a\)\{(a=a\.split\(""\)[^\}]+)\}') op_with_arg_re = re.compile(r'[^\.]+\.([^\(]+)\(a,(\d+)\)') def decrypt_signatures(info): '''return error string, or False if no errors''' - if not info['formats'] or not info['formats'][0]['s']: + if ('formats' not in info) or (not info['formats']) or (not info['formats'][0]['s']): return False # No decryption needed if not info['base_js']: return 'Failed to find base.js' @@ -356,6 +356,7 @@ def get_watch_page(): uploader = info['author'], description = info['description'], unlisted = info['unlisted'], + playability_error = info['playability_error'], ) diff --git a/youtube/yt_data_extract.py b/youtube/yt_data_extract.py index 6bfec59..1a5f21c 100644 --- a/youtube/yt_data_extract.py +++ b/youtube/yt_data_extract.py @@ -824,7 +824,7 @@ def check_missing_keys(object, *key_sequences): _object = object try: for key in key_sequence: - _object = object[key] + _object = _object[key] except (KeyError, IndexError, TypeError): return 'Could not find ' + key @@ -1028,21 +1028,20 @@ def extract_watch_info(polymer_json): return {'error': 'Invalid top level polymer data'} error = check_missing_keys(top_level, - ['playerResponse'], - ) - if error: - return {'error': error} - - error = check_missing_keys(top_level, ['player', 'args'], ['player', 'assets', 'js'], + ['playerResponse'], ) if error: info['playability_error'] = error - player_args = default_multi_get(top_level, 'player', 'args', default={}) player_response = json.loads(player_args['player_response']) if 'player_response' in player_args else {} + playability_status = default_multi_get(player_response, 'playabilityStatus', 'status', default=None) + playability_reason = default_multi_get(player_response, 'playabilityStatus', 'reason', default='Unknown error') + if playability_status not in (None, 'OK'): + info['playability_error'] = playability_reason + streaming_data = player_response.get('streamingData', {}) yt_formats = streaming_data.get('formats', []) + streaming_data.get('adaptiveFormats', []) @@ -1069,6 +1068,8 @@ def extract_watch_info(polymer_json): fmt.update(_formats.get(str(yt_fmt.get('itag')), {})) info['formats'].append(fmt) + if info['formats']: + info['playability_error'] = None # in case they lie info['base_js'] = default_multi_get(top_level, 'player', 'assets', 'js') if info['base_js']: |