Skip to content

Commit

Permalink
Workaround InputStream.Adaptive using incorrect path for downloaded subs
Browse files Browse the repository at this point in the history
- InputStream.Adaptive assumes absolute local paths are relative to manifest base url
- Disable adding subs to manifest if downloaded and fallback to using Kodi to load subs
- Disable downloading ttml subs as Kodi does not support this
- Use ttml subs based on ISA capability not Kodi version
- Also do not try to fetch subs for live streams as they are already included in the manifest
  • Loading branch information
MoojMidge committed Mar 8, 2024
1 parent a1ea3c9 commit 529e5ca
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ def video_playback_item(context, video_item, show_fanart=None):
'thumb': image,
})

if video_item.subtitles and manifest_type != 'mpd':
if video_item.subtitles:
list_item.setSubtitles(video_item.subtitles)

item_info = create_info_labels(video_item)
Expand Down
30 changes: 17 additions & 13 deletions resources/lib/youtube_plugin/youtube/helper/subtitles.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
)
from ...kodion.constants import TEMP_PATH
from ...kodion.network import BaseRequestsClass
from ...kodion.utils import make_dirs, current_system_version
from ...kodion.utils import make_dirs


class Subtitles(object):
Expand All @@ -34,7 +34,7 @@ class Subtitles(object):
BASE_PATH = make_dirs(TEMP_PATH)

FORMATS = {
'_default': 'ttml' if current_system_version.compatible(20) else 'vtt',
'_default': None,
'vtt': {
'mime_type': 'text/vtt',
'extension': 'vtt',
Expand All @@ -53,6 +53,13 @@ def __init__(self, context, video_id, captions, headers=None):
self.pre_download = settings.subtitle_download()
self.sub_selection = settings.get_subtitle_selection()

if (not self.pre_download
and settings.use_mpd_videos()
and context.inputstream_adaptive_capabilities('ttml')):
self.FORMATS['_default'] = 'ttml'
else:
self.FORMATS['_default'] = 'vtt'

sub_lang = context.get_subtitle_language()
ui_lang = settings.get_language()
if not sub_lang and ui_lang:
Expand All @@ -66,8 +73,7 @@ def __init__(self, context, video_id, captions, headers=None):
else:
self.preferred_lang = ('en',)

if not headers and 'headers' in captions:
headers = captions['headers']
if headers:
headers.pop('Authorization', None)
headers.pop('Content-Length', None)
headers.pop('Content-Type', None)
Expand Down Expand Up @@ -326,23 +332,21 @@ def _prompt(self):
.format(lang=lang))
return None

def _get_url(self, track, lang=None, download=None):
def _get_url(self, track, lang=None):
sub_format = self.FORMATS['_default']
tlang = None
base_lang = track.get('languageCode')
kind = track.get('kind')
if lang and lang != base_lang:
tlang = lang
lang = '_'.join((base_lang, tlang))
lang = '-'.join((base_lang, tlang))
elif kind == 'asr':
lang = '_'.join((base_lang, kind))
lang = '-'.join((base_lang, kind))
sub_format = 'vtt'
else:
lang = base_lang
mime_type = self.FORMATS[sub_format]['mime_type']

if download is None:
download = self.pre_download
download = self.pre_download
if download:
filename = '.'.join((
self.video_id,
Expand All @@ -359,7 +363,7 @@ def _get_url(self, track, lang=None, download=None):
self._context.log_debug('Subtitles._get_url'
' - use existing: |{lang}: {file}|'
.format(lang=lang, file=filepath))
return filepath, mime_type
return filepath, self.FORMATS[sub_format]['mime_type']

base_url = self._normalize_url(track.get('baseUrl'))
if not base_url:
Expand All @@ -378,7 +382,7 @@ def _get_url(self, track, lang=None, download=None):
.format(lang=lang, url=subtitle_url))

if not download:
return subtitle_url, mime_type
return subtitle_url, self.FORMATS[sub_format]['mime_type']

response = BaseRequestsClass().request(
subtitle_url,
Expand All @@ -401,7 +405,7 @@ def _get_url(self, track, lang=None, download=None):
' - write failed for: {file}'
.format(file=filepath))
if success:
return filepath, mime_type
return filepath, self.FORMATS[sub_format]['mime_type']
return None, None

def _get_track(self,
Expand Down
77 changes: 43 additions & 34 deletions resources/lib/youtube_plugin/youtube/helper/video_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -1126,37 +1126,6 @@ def _get_video_info(self):
is_live = video_details.get('isLiveContent', False)
thumb_suffix = '_live' if is_live else ''

if client.get('_query_subtitles'):
for client_name in ('smarttv_embedded', 'web', 'android'):
result = self.request(
video_info_url, 'POST',
error_msg=('Caption request failed to get player response for'
'video_id: {0}'.format(self.video_id)),
**self.build_client(client_name, client_data)
)
response = result and result.json() or {}
captions = response.get('captions')
if captions:
captions['headers'] = result.request.headers
break
else:
captions = response.get('captions')
if captions:
captions['headers'] = client['headers']
if captions:
captions = Subtitles(
self._context, self.video_id, captions
)
default_lang = captions.get_lang_details()
subs_data = captions.get_subtitles()
else:
default_lang = {
'default': 'und',
'original': 'und',
'is_asr': False,
}
subs_data = None

meta_info = {
'video': {
'id': video_details.get('videoId', self.video_id),
Expand Down Expand Up @@ -1187,9 +1156,7 @@ def _get_video_info(self):
'default': ('https://i.ytimg.com/vi/{0}/default{1}.jpg'
.format(self.video_id, thumb_suffix)),
},
'subtitles': [
subtitle['url'] for subtitle in subs_data.values()
] if subs_data else None,
'subtitles': None,
}

if _settings.use_remote_history():
Expand All @@ -1214,6 +1181,7 @@ def _get_video_info(self):

httpd_is_live = (_settings.use_isa() and
is_httpd_live(port=_settings.httpd_port()))
use_mpd_vod = _settings.use_mpd_videos()

pa_li_info = streaming_data.get('licenseInfos', [])
if any(pa_li_info) and not httpd_is_live:
Expand Down Expand Up @@ -1263,6 +1231,47 @@ def _get_video_info(self):
streaming_data['hlsManifestUrl'],
live_type, meta_info, client['headers'], playback_stats
))
else:
live_type = None

if not live_type and client.get('_query_subtitles'):
for client_name in ('smarttv_embedded', 'web', 'android'):
caption_client = self.build_client(client_name, client_data)
result = self.request(
video_info_url, 'POST',
error_msg=(
'Caption request failed to get player response for'
'video_id: {0}'.format(self.video_id)),
**caption_client
)
response = result and result.json() or {}
captions = response.get('captions')
if captions:
break
else:
captions = result.get('captions')
caption_client = client
if captions:
captions = Subtitles(
self._context,
self.video_id,
captions,
caption_client['headers']
)
default_lang = captions.get_lang_details()
subs_data = captions.get_subtitles()
if subs_data and (not use_mpd_vod or captions.pre_download):
meta_info['subtitles'] = [
subtitle['url'] for subtitle in subs_data.values()
]
subs_data = None
else:
default_lang = {
'default': 'und',
'original': 'und',
'is_asr': False,
}
subs_data = None

# extract adaptive streams and create MPEG-DASH manifest
if not manifest_url and httpd_is_live and adaptive_fmts:
Expand Down

0 comments on commit 529e5ca

Please sign in to comment.