Skip to content

Commit

Permalink
Prefer use of ttml subs
Browse files Browse the repository at this point in the history
- ttml used in Kodi v20+ as they are better formatted compared to vtt
- vtt used for older versions that don't support ttml
- vtt also used for ASR subs that require support for rolling subs
  • Loading branch information
MoojMidge committed Mar 8, 2024
1 parent cdf00f2 commit a1ea3c9
Showing 1 changed file with 52 additions and 59 deletions.
111 changes: 52 additions & 59 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
from ...kodion.utils import make_dirs, current_system_version


class Subtitles(object):
Expand All @@ -33,6 +33,18 @@ class Subtitles(object):

BASE_PATH = make_dirs(TEMP_PATH)

FORMATS = {
'_default': 'ttml' if current_system_version.compatible(20) else 'vtt',
'vtt': {
'mime_type': 'text/vtt',
'extension': 'vtt',
},
'ttml': {
'mime_type': 'application/ttml+xml',
'extension': 'ttml',
},
}

def __init__(self, context, video_id, captions, headers=None):
self.video_id = video_id
self._context = context
Expand Down Expand Up @@ -158,7 +170,7 @@ def get_subtitles(self):
return None

if selection == self.LANG_ALL:
return self.get_all(sub_format='vtt')
return self.get_all()

if selection == self.LANG_PROMPT:
return self._prompt()
Expand Down Expand Up @@ -196,28 +208,20 @@ def get_subtitles(self):
track_key = '_'.join((track_lang, track_kind))
else:
track_key = track_lang
subtitles[track_key] = {
'default': track_lang in preferred_lang,
'original': track_lang == original_lang,
'kind': track_kind,
'lang': track_lang,
'language': track_language,
'mime_type': 'text/vtt',
'url': self._get_url(
caption_track=track,
lang=track_lang,
sub_format='vtt',
),
}
url, mime_type = self._get_url(track=track, lang=track_lang)
if url:
subtitles[track_key] = {
'default': track_lang in preferred_lang,
'original': track_lang == original_lang,
'kind': track_kind,
'lang': track_lang,
'language': track_language,
'mime_type': mime_type,
'url': url,
}
return subtitles

def get_all(self, sub_format='vtt'):
if sub_format == 'vtt':
mime_type = 'text/vtt'
else:
sub_format = 'ttml'
mime_type = 'application/ttml+xml'

def get_all(self):
subtitles = {}

preferred_lang = self.preferred_lang
Expand All @@ -227,11 +231,7 @@ def get_all(self, sub_format='vtt'):
track_lang = track.get('languageCode')
track_kind = track.get('kind')
track_language = self._get_language_name(track)
url = self._get_url(
caption_track=track,
sub_format=sub_format,
download=False,
)
url, mime_type = self._get_url(track=track)
if url:
if track_kind:
track_key = '_'.join((track_lang, track_kind))
Expand All @@ -257,14 +257,9 @@ def get_all(self, sub_format='vtt'):
if not track_lang or track_lang in subtitles:
continue
track_language = self._get_language_name(track)
url = self._get_url(
caption_track=base_track,
lang=track_lang,
sub_format=sub_format,
download=False,
)
track_key = '_'.join((base_lang, track_lang))
url, mime_type = self._get_url(track=base_track, lang=track_lang)
if url:
track_key = '_'.join((base_lang, track_lang))
subtitles[track_key] = {
'default': track_lang in preferred_lang,
'original': track_lang == original_lang,
Expand Down Expand Up @@ -314,11 +309,7 @@ def _prompt(self):

lang, language = choice

url = self._get_url(
caption_track=track,
lang=lang,
sub_format='vtt',
)
url, mime_type = self._get_url(track=track, lang=lang)
if url:
return {
lang: {
Expand All @@ -327,52 +318,54 @@ def _prompt(self):
'kind': track_kind,
'lang': lang,
'language': language,
'mime_type': 'text/vtt',
'mime_type': mime_type,
'url': url,
},
}
self._context.log_debug('No subtitle found for selection: |{lang}|'
.format(lang=lang))
return None

def _get_url(self,
caption_track,
lang=None,
sub_format='vtt',
download=None):
def _get_url(self, track, lang=None, download=None):
sub_format = self.FORMATS['_default']
tlang = None
base_lang = caption_track.get('languageCode')
kind = caption_track.get('kind')
base_lang = track.get('languageCode')
kind = track.get('kind')
if lang and lang != base_lang:
tlang = lang
lang = '_'.join((base_lang, tlang))
elif kind == 'asr':
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
if download:
sub_format = 'vtt'
filename = '.'.join((self.video_id, lang, 'srt'))
filename = '.'.join((
self.video_id,
lang,
self.FORMATS[sub_format]['extension']
))
if not self.BASE_PATH:
self._context.log_error('Subtitles._get_url'
' - unable to access temp directory')
return None
return None, None

filepath = os.path.join(self.BASE_PATH, filename)
if xbmcvfs.exists(filepath):
self._context.log_debug('Subtitles._get_url'
' - use existing: |{lang}: {file}|'
.format(lang=lang, file=filepath))
return filepath
return filepath, mime_type

base_url = self._normalize_url(caption_track.get('baseUrl'))
base_url = self._normalize_url(track.get('baseUrl'))
if not base_url:
self._context.log_error('Subtitles._get_url - no url for: |{lang}|'
.format(lang=lang))
return None
return None, None

subtitle_url = self._set_query_param(
base_url,
Expand All @@ -385,7 +378,7 @@ def _get_url(self,
.format(lang=lang, url=subtitle_url))

if not download:
return subtitle_url
return subtitle_url, mime_type

response = BaseRequestsClass().request(
subtitle_url,
Expand All @@ -395,21 +388,21 @@ def _get_url(self,
)
response = response and response.text
if not response:
return None
return None, None

output = bytearray(self._unescape(response),
encoding='utf8',
errors='ignore')
try:
with xbmcvfs.File(filepath, 'w') as srt_file:
success = srt_file.write(output)
with xbmcvfs.File(filepath, 'w') as sub_file:
success = sub_file.write(output)
except (IOError, OSError):
self._context.log_error('Subtitles._get_url'
' - write failed for: {file}'
.format(file=filepath))
if success:
return filepath
return None
return filepath, mime_type
return None, None

def _get_track(self,
lang='en',
Expand Down

0 comments on commit a1ea3c9

Please sign in to comment.