Extraction: return and display any errors preventing video playback
This commit is contained in:
parent
70b56d6eef
commit
79d9a18f81
@ -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>
|
||||
|
@ -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'],
|
||||
)
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
@ -1027,22 +1027,21 @@ def extract_watch_info(polymer_json):
|
||||
else:
|
||||
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']:
|
||||
|
Loading…
x
Reference in New Issue
Block a user