Merge pull request #1011 from croneter/fix-subtitle-naming

Improve subtitle naming
This commit is contained in:
croneter 2019-10-05 16:58:41 +02:00 committed by GitHub
commit af23a4aabd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 54 deletions

View file

@ -19,6 +19,8 @@ import shutil
import os import os
from os import path # allows to use path_ops.path.join, for example from os import path # allows to use path_ops.path.join, for example
from distutils import dir_util from distutils import dir_util
import re
import xbmc import xbmc
import xbmcvfs import xbmcvfs
@ -26,6 +28,7 @@ from .tools import unicode_paths
# Kodi seems to encode in utf-8 in ALL cases (unlike e.g. the OS filesystem) # Kodi seems to encode in utf-8 in ALL cases (unlike e.g. the OS filesystem)
KODI_ENCODING = 'utf-8' KODI_ENCODING = 'utf-8'
REGEX_FILE_NUMBERING = re.compile(r'''_(\d\d)\.\w+$''')
def encode_path(path): def encode_path(path):
@ -216,3 +219,25 @@ def basename(path):
return path.rsplit('\\', 1)[1] return path.rsplit('\\', 1)[1]
except IndexError: except IndexError:
return '' return ''
def create_unique_path(directory, filename, extension):
"""
Checks whether 'directory/filename.extension' exists. If so, will start
numbering the filename until the file does not exist yet (up to 99)
"""
res = path.join(directory, '.'.join((filename, extension)))
while exists(res):
occurance = REGEX_FILE_NUMBERING.search(res)
if not occurance:
filename = '{}_00'.format(filename[:min(len(filename),
251 - len(extension))])
res = path.join(directory, '.'.join((filename, extension)))
else:
number = int(occurance.group(1)) + 1
if number > 99:
raise RuntimeError('Could not create unique file: {} {} {}'.format(
directory, filename, extension))
basename = re.sub(REGEX_FILE_NUMBERING, '', res)
res = '{}_{:02d}.{}'.format(basename, number, extension)
return res

View file

@ -351,12 +351,12 @@ def audio_subtitle_prefs(api, listitem):
for stream in mediastreams: for stream in mediastreams:
# Since Plex returns all possible tracks together, have to sort # Since Plex returns all possible tracks together, have to sort
# them. # them.
index = stream.attrib.get('id') index = stream.get('id')
typus = stream.attrib.get('streamType') typus = stream.get('streamType')
# Audio # Audio
if typus == "2": if typus == "2":
codec = stream.attrib.get('codec') codec = stream.get('codec')
channellayout = stream.attrib.get('audioChannelLayout', "") channellayout = stream.get('audioChannelLayout', "")
try: try:
track = "%s %s - %s %s" % (audio_numb + 1, track = "%s %s - %s %s" % (audio_numb + 1,
stream.attrib['language'], stream.attrib['language'],
@ -368,48 +368,42 @@ def audio_subtitle_prefs(api, listitem):
codec, codec,
channellayout) channellayout)
audio_streams_list.append(index) audio_streams_list.append(index)
audio_streams.append(utils.try_encode(track)) audio_streams.append(track.encode('utf-8'))
audio_numb += 1 audio_numb += 1
# Subtitles # Subtitles
elif typus == "3": elif typus == "3":
try: try:
track = "%s %s" % (sub_num + 1, stream.attrib['language']) track = '{} {}'.format(sub_num, stream.attrib['displayTitle'])
except KeyError: except KeyError:
track = "%s %s (%s)" % (sub_num + 1, track = '{} {} ({})'.format(sub_num + 1,
utils.lang(39707), # unknown utils.lang(39707), # unknown
stream.attrib.get('codec')) stream.get('codec'))
default = stream.attrib.get('default') default = stream.get('default')
forced = stream.attrib.get('forced') forced = stream.get('forced')
downloadable = stream.attrib.get('key') downloadable = stream.get('key')
if default: if default:
track = "%s - %s" % (track, utils.lang(39708)) # Default track = "%s - %s" % (track, utils.lang(39708)) # Default
if forced: if forced:
track = "%s - %s" % (track, utils.lang(39709)) # Forced track = "%s - %s" % (track, utils.lang(39709)) # Forced
if downloadable: if downloadable:
# We do know the language - temporarily download
if 'language' in stream.attrib:
path = api.download_external_subtitles( path = api.download_external_subtitles(
'{server}%s' % stream.attrib['key'], '{{server}}{}'.format(stream.get('key')),
"subtitle.%s.%s" % (stream.attrib['languageCode'], stream.get('displayTitle'),
stream.attrib['codec'])) stream.get('codec'))
# We don't know the language - no need to download if path:
else:
path = api.attach_plex_token_to_url(
"%s%s" % (app.CONN.server,
stream.attrib['key']))
downloadable_streams.append(index) downloadable_streams.append(index)
download_subs.append(utils.try_encode(path)) download_subs.append(path.encode('utf-8'))
else: else:
track = "%s (%s)" % (track, utils.lang(39710)) # burn-in track = "%s (%s)" % (track, utils.lang(39710)) # burn-in
if stream.attrib.get('selected') == '1' and downloadable: if stream.get('selected') == '1' and downloadable:
# Only show subs without asking user if they can be # Only show subs without asking user if they can be
# turned off # turned off
default_sub = index default_sub = index
subtitle_streams_list.append(index) subtitle_streams_list.append(index)
subtitle_streams.append(utils.try_encode(track)) subtitle_streams.append(track.encode('utf-8'))
sub_num += 1 sub_num += 1
if audio_numb > 1: if audio_numb > 1:

View file

@ -254,46 +254,33 @@ class Media(object):
try: try:
mediastreams = self.xml[0][self.part] mediastreams = self.xml[0][self.part]
except (TypeError, KeyError, IndexError): except (TypeError, KeyError, IndexError):
return return externalsubs
kodiindex = 0
fileindex = 0
for stream in mediastreams: for stream in mediastreams:
# Since plex returns all possible tracks together, have to pull # Since plex returns all possible tracks together, have to pull
# only external subtitles - only for these a 'key' exists # only external subtitles - only for these a 'key' exists
if cast(int, stream.get('streamType')) != 3: if int(stream.get('streamType')) != 3 or 'key' not in stream.attrib:
# Not a subtitle # Not a subtitle or not not an external subtitle
continue continue
# Only set for additional external subtitles NOT lying beside video
key = stream.get('key')
# Only set for dedicated subtitle files lying beside video
# ext = stream.attrib.get('format')
if key:
# We do know the language - temporarily download
if stream.get('languageCode') is not None:
language = stream.get('languageCode')
codec = stream.get('codec')
path = self.download_external_subtitles( path = self.download_external_subtitles(
"{server}%s" % key, '{server}%s' % stream.get('key'),
"subtitle%02d.%s.%s" % (fileindex, language, codec)) stream.get('displayTitle'),
fileindex += 1 stream.get('codec'))
# We don't know the language - no need to download if path:
else:
path = self.attach_plex_token_to_url(
"%s%s" % (app.CONN.server, key))
externalsubs.append(path) externalsubs.append(path)
kodiindex += 1
LOG.info('Found external subs: %s', externalsubs) LOG.info('Found external subs: %s', externalsubs)
return externalsubs return externalsubs
@staticmethod @staticmethod
def download_external_subtitles(url, filename): def download_external_subtitles(url, filename, extension):
""" """
One cannot pass the subtitle language for ListItems. Workaround; will One cannot pass the subtitle language for ListItems. Workaround; will
download the subtitle at url to the Kodi PKC directory in a temp dir download the subtitle at url to the Kodi PKC directory in a temp dir
Returns the path to the downloaded subtitle or None Returns the path to the downloaded subtitle or None
""" """
path = path_ops.path.join(v.EXTERNAL_SUBTITLE_TEMP_PATH, filename) path = path_ops.create_unique_path(v.EXTERNAL_SUBTITLE_TEMP_PATH,
filename,
extension)
response = DU().downloadUrl(url, return_response=True) response = DU().downloadUrl(url, return_response=True)
try: try:
response.status_code response.status_code
@ -302,8 +289,8 @@ class Media(object):
return return
else: else:
LOG.debug('Writing temp subtitle to %s', path) LOG.debug('Writing temp subtitle to %s', path)
with open(path_ops.encode_path(path), 'wb') as filer: with open(path_ops.encode_path(path), 'wb') as f:
filer.write(response.content) f.write(response.content)
return path return path
def validate_playurl(self, path, typus, force_check=False, folder=False, def validate_playurl(self, path, typus, force_check=False, folder=False,