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
from os import path # allows to use path_ops.path.join, for example
from distutils import dir_util
import re
import xbmc
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_ENCODING = 'utf-8'
REGEX_FILE_NUMBERING = re.compile(r'''_(\d\d)\.\w+$''')
def encode_path(path):
@ -216,3 +219,25 @@ def basename(path):
return path.rsplit('\\', 1)[1]
except IndexError:
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:
# Since Plex returns all possible tracks together, have to sort
# them.
index = stream.attrib.get('id')
typus = stream.attrib.get('streamType')
index = stream.get('id')
typus = stream.get('streamType')
# Audio
if typus == "2":
codec = stream.attrib.get('codec')
channellayout = stream.attrib.get('audioChannelLayout', "")
codec = stream.get('codec')
channellayout = stream.get('audioChannelLayout', "")
try:
track = "%s %s - %s %s" % (audio_numb + 1,
stream.attrib['language'],
@ -368,48 +368,42 @@ def audio_subtitle_prefs(api, listitem):
codec,
channellayout)
audio_streams_list.append(index)
audio_streams.append(utils.try_encode(track))
audio_streams.append(track.encode('utf-8'))
audio_numb += 1
# Subtitles
elif typus == "3":
try:
track = "%s %s" % (sub_num + 1, stream.attrib['language'])
track = '{} {}'.format(sub_num, stream.attrib['displayTitle'])
except KeyError:
track = "%s %s (%s)" % (sub_num + 1,
track = '{} {} ({})'.format(sub_num + 1,
utils.lang(39707), # unknown
stream.attrib.get('codec'))
default = stream.attrib.get('default')
forced = stream.attrib.get('forced')
downloadable = stream.attrib.get('key')
stream.get('codec'))
default = stream.get('default')
forced = stream.get('forced')
downloadable = stream.get('key')
if default:
track = "%s - %s" % (track, utils.lang(39708)) # Default
if forced:
track = "%s - %s" % (track, utils.lang(39709)) # Forced
if downloadable:
# We do know the language - temporarily download
if 'language' in stream.attrib:
path = api.download_external_subtitles(
'{server}%s' % stream.attrib['key'],
"subtitle.%s.%s" % (stream.attrib['languageCode'],
stream.attrib['codec']))
# We don't know the language - no need to download
else:
path = api.attach_plex_token_to_url(
"%s%s" % (app.CONN.server,
stream.attrib['key']))
'{{server}}{}'.format(stream.get('key')),
stream.get('displayTitle'),
stream.get('codec'))
if path:
downloadable_streams.append(index)
download_subs.append(utils.try_encode(path))
download_subs.append(path.encode('utf-8'))
else:
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
# turned off
default_sub = index
subtitle_streams_list.append(index)
subtitle_streams.append(utils.try_encode(track))
subtitle_streams.append(track.encode('utf-8'))
sub_num += 1
if audio_numb > 1:

View file

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