Added caching of video files analyzing to prevent useless disk IO

pull/1391/head
Abdulmohsen 4 years ago committed by GitHub
parent 25c99362b2
commit 8e5dbcd8f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -108,6 +108,7 @@ def db_upgrade():
['table_episodes', 'audio_codec', 'text'], ['table_episodes', 'audio_codec', 'text'],
['table_episodes', 'episode_file_id', 'integer'], ['table_episodes', 'episode_file_id', 'integer'],
['table_episodes', 'audio_language', 'text'], ['table_episodes', 'audio_language', 'text'],
['table_episodes', 'file_ffprobe', 'text'],
['table_movies', 'sortTitle', 'text'], ['table_movies', 'sortTitle', 'text'],
['table_movies', 'year', 'text'], ['table_movies', 'year', 'text'],
['table_movies', 'alternativeTitles', 'text'], ['table_movies', 'alternativeTitles', 'text'],
@ -120,6 +121,7 @@ def db_upgrade():
['table_movies', 'movie_file_id', 'integer'], ['table_movies', 'movie_file_id', 'integer'],
['table_movies', 'tags', 'text', '[]'], ['table_movies', 'tags', 'text', '[]'],
['table_movies', 'profileId', 'integer'], ['table_movies', 'profileId', 'integer'],
['table_movies', 'file_ffprobe', 'text'],
['table_history', 'video_path', 'text'], ['table_history', 'video_path', 'text'],
['table_history', 'language', 'text'], ['table_history', 'language', 'text'],
['table_history', 'provider', 'text'], ['table_history', 'provider', 'text'],

@ -10,21 +10,28 @@ from knowit import api
class EmbeddedSubsReader: class EmbeddedSubsReader:
def __init__(self): def __init__(self):
self.ffprobe = None self.ffprobe = None
self.cache = None
def list_languages(self, file): self.data = None
from utils import get_binary
def list_languages(self, file, original_path):
from utils import get_binary, cache_get_ffprobe, cache_save_ffprobe
self.cache = cache_get_ffprobe(original_path)
if self.cache['ffprobe'] is not None:
logging.debug('returning cached results for: %s', original_path)
return self.cache['ffprobe']
self.ffprobe = get_binary("ffprobe") self.ffprobe = get_binary("ffprobe")
subtitles_list = [] subtitles_list = []
if self.ffprobe: if self.ffprobe:
api.initialize({'provider': 'ffmpeg', 'ffmpeg': self.ffprobe}) api.initialize({'provider': 'ffmpeg', 'ffmpeg': self.ffprobe})
data = api.know(file) self.data = api.know(file)
traditional_chinese = ["cht", "tc", "traditional", "zht", "hant", "big5", u"", u"雙語"] traditional_chinese = ["cht", "tc", "traditional", "zht", "hant", "big5", u"", u"雙語"]
brazilian_portuguese = ["pt-br", "pob", "pb", "brazilian", "brasil", "brazil"] brazilian_portuguese = ["pt-br", "pob", "pb", "brazilian", "brasil", "brazil"]
if 'subtitle' in data: if 'subtitle' in self.data:
for detected_language in data['subtitle']: for detected_language in self.data['subtitle']:
if 'language' in detected_language: if 'language' in detected_language:
language = detected_language['language'].alpha3 language = detected_language['language'].alpha3
if language == 'zho' and 'name' in detected_language: if language == 'zho' and 'name' in detected_language:
@ -44,11 +51,11 @@ class EmbeddedSubsReader:
if os.path.splitext(file)[1] == '.mkv': if os.path.splitext(file)[1] == '.mkv':
with open(file, 'rb') as f: with open(file, 'rb') as f:
try: try:
mkv = enzyme.MKV(f) self.data = enzyme.MKV(f)
except MalformedMKVError: except MalformedMKVError:
logging.error('BAZARR cannot analyze this MKV with our built-in MKV parser, you should install ffmpeg: ' + file) logging.error('BAZARR cannot analyze this MKV with our built-in MKV parser, you should install ffmpeg: ' + file)
else: else:
for subtitle_track in mkv.subtitle_tracks: for subtitle_track in self.data.subtitle_tracks:
hearing_impaired = False hearing_impaired = False
if subtitle_track.name: if subtitle_track.name:
if 'sdh' in subtitle_track.name.lower(): if 'sdh' in subtitle_track.name.lower():
@ -56,6 +63,9 @@ class EmbeddedSubsReader:
subtitles_list.append([subtitle_track.language, subtitle_track.forced, hearing_impaired, subtitles_list.append([subtitle_track.language, subtitle_track.forced, hearing_impaired,
subtitle_track.codec_id]) subtitle_track.codec_id])
if subtitles_list is not None:
cache_save_ffprobe(original_path, self.cache['id'], self.cache['type'], subtitles_list)
return subtitles_list return subtitles_list

@ -24,7 +24,7 @@ def sync_episodes():
apikey_sonarr = settings.sonarr.apikey apikey_sonarr = settings.sonarr.apikey
# Get current episodes id in DB # Get current episodes id in DB
current_episodes_db = database.execute("SELECT sonarrEpisodeId, path, sonarrSeriesId FROM table_episodes") current_episodes_db = database.execute("SELECT sonarrEpisodeId, path, sonarrSeriesId, file_ffprobe FROM table_episodes")
current_episodes_db_list = [x['sonarrEpisodeId'] for x in current_episodes_db] current_episodes_db_list = [x['sonarrEpisodeId'] for x in current_episodes_db]
@ -32,7 +32,14 @@ def sync_episodes():
episodes_to_update = [] episodes_to_update = []
episodes_to_add = [] episodes_to_add = []
altered_episodes = [] altered_episodes = []
path_episodes = {}
for item in current_episodes_db:
path_episodes[str(item['sonarrEpisodeId'])] = {
'path': item['path'],
'file_ffprobe': item['file_ffprobe']
}
# Get sonarrId for each series from database # Get sonarrId for each series from database
seriesIdList = database.execute("SELECT sonarrSeriesId, title FROM table_shows") seriesIdList = database.execute("SELECT sonarrSeriesId, title FROM table_shows")
@ -102,37 +109,33 @@ def sync_episodes():
# Add episodes in sonarr to current episode list # Add episodes in sonarr to current episode list
current_episodes_sonarr.append(episode['id']) current_episodes_sonarr.append(episode['id'])
info = {
'sonarrSeriesId': episode['seriesId'],
'sonarrEpisodeId': episode['id'],
'title': episode['title'],
'path': episode['episodeFile']['path'],
'season': episode['seasonNumber'],
'episode': episode['episodeNumber'],
'scene_name': sceneName,
'monitored': str(bool(episode['monitored'])),
'format': format,
'resolution': resolution,
'video_codec': videoCodec,
'audio_codec': audioCodec,
'episode_file_id': episode['episodeFile']['id'],
'audio_language': str(audio_language),
'file_ffprobe': None,
}
if episode['id'] in current_episodes_db_list: if episode['id'] in current_episodes_db_list:
episodes_to_update.append({'sonarrSeriesId': episode['seriesId'], if info['path'] == path_episodes[str(info['sonarrEpisodeId'])]['path'] and path_episodes[str(info['sonarrEpisodeId'])]['file_ffprobe'] is not None:
'sonarrEpisodeId': episode['id'], logging.debug('path is the same. Preserving ffprobe old results for: %s.', str(info['sonarrEpisodeId']))
'title': episode['title'], info['file_ffprobe'] = path_episodes[str(episode['id'])]['file_ffprobe']
'path': episode['episodeFile']['path'],
'season': episode['seasonNumber'], episodes_to_update.append(info)
'episode': episode['episodeNumber'],
'scene_name': sceneName,
'monitored': str(bool(episode['monitored'])),
'format': format,
'resolution': resolution,
'video_codec': videoCodec,
'audio_codec': audioCodec,
'episode_file_id': episode['episodeFile']['id'],
'audio_language': str(audio_language)})
else: else:
episodes_to_add.append({'sonarrSeriesId': episode['seriesId'], episodes_to_add.append(info)
'sonarrEpisodeId': episode['id'],
'title': episode['title'],
'path': episode['episodeFile']['path'],
'season': episode['seasonNumber'],
'episode': episode['episodeNumber'],
'scene_name': sceneName,
'monitored': str(bool(episode['monitored'])),
'format': format,
'resolution': resolution,
'video_codec': videoCodec,
'audio_codec': audioCodec,
'episode_file_id': episode['episodeFile']['id'],
'audio_language': str(audio_language)})
# Remove old episodes from DB # Remove old episodes from DB
removed_episodes = list(set(current_episodes_db_list) - set(current_episodes_sonarr)) removed_episodes = list(set(current_episodes_db_list) - set(current_episodes_sonarr))

@ -63,14 +63,21 @@ def update_movies():
return return
else: else:
# Get current movies in DB # Get current movies in DB
current_movies_db = database.execute("SELECT tmdbId, path, radarrId FROM table_movies") current_movies_db = database.execute("SELECT tmdbId, path, radarrId, file_ffprobe FROM table_movies")
current_movies_db_list = [x['tmdbId'] for x in current_movies_db] current_movies_db_list = [x['tmdbId'] for x in current_movies_db]
current_movies_radarr = [] current_movies_radarr = []
movies_to_update = [] movies_to_update = []
movies_to_add = [] movies_to_add = []
altered_movies = [] altered_movies = []
path_movies = {}
for item in current_movies_db:
path_movies[str(item['tmdbId'])] = {
'path': item['path'],
'file_ffprobe': item['file_ffprobe']
}
moviesIdListLength = len(r.json()) moviesIdListLength = len(r.json())
for i, movie in enumerate(r.json(), 1): for i, movie in enumerate(r.json(), 1):
@ -167,51 +174,40 @@ def update_movies():
# Add movies in radarr to current movies list # Add movies in radarr to current movies list
current_movies_radarr.append(str(movie['tmdbId'])) current_movies_radarr.append(str(movie['tmdbId']))
info = {
'radarrId': int(movie['id']),
'title': movie['title'],
'path': movie['path'] + separator + movie['movieFile']['relativePath'],
'tmdbId': str(movie['tmdbId']),
'poster': poster,
'fanart': fanart,
'audio_language': str(audio_language),
'sceneName': sceneName,
'monitored': str(bool(movie['monitored'])),
'year': str(movie['year']),
'sortTitle': movie['sortTitle'],
'alternativeTitles': alternativeTitles,
'format': format,
'resolution': resolution,
'video_codec': videoCodec,
'audio_codec': audioCodec,
'overview': overview,
'imdbId': imdbId,
'movie_file_id': int(movie['movieFile']['id']),
'tags': str(tags),
'file_ffprobe': None,
}
if str(movie['tmdbId']) in current_movies_db_list: if str(movie['tmdbId']) in current_movies_db_list:
movies_to_update.append({'radarrId': int(movie["id"]), if info['path'] == path_movies[str(info['tmdbId'])]['path'] and path_movies[str(info['tmdbId'])]['file_ffprobe'] is not None:
'title': movie["title"], logging.debug('path is the same. Preserving ffprobe old results for: %s.', str(info['tmdbId']))
'path': movie["path"] + separator + movie['movieFile']['relativePath'], info['file_ffprobe'] = path_movies[str(info['tmdbId'])]['file_ffprobe']
'tmdbId': str(movie["tmdbId"]),
'poster': poster, movies_to_update.append(info)
'fanart': fanart,
'audio_language': str(audio_language),
'sceneName': sceneName,
'monitored': str(bool(movie['monitored'])),
'year': str(movie['year']),
'sortTitle': movie['sortTitle'],
'alternativeTitles': alternativeTitles,
'format': format,
'resolution': resolution,
'video_codec': videoCodec,
'audio_codec': audioCodec,
'overview': overview,
'imdbId': imdbId,
'movie_file_id': int(movie['movieFile']['id']),
'tags': str(tags)})
else: else:
movies_to_add.append({'radarrId': int(movie["id"]), info['profileId'] = movie_default_profile
'title': movie["title"], movies_to_add.append(info)
'path': movie["path"] + separator + movie['movieFile']['relativePath'],
'tmdbId': str(movie["tmdbId"]),
'subtitles': '[]',
'overview': overview,
'poster': poster,
'fanart': fanart,
'audio_language': str(audio_language),
'sceneName': sceneName,
'monitored': str(bool(movie['monitored'])),
'sortTitle': movie['sortTitle'],
'year': str(movie['year']),
'alternativeTitles': alternativeTitles,
'format': format,
'resolution': resolution,
'video_codec': videoCodec,
'audio_codec': audioCodec,
'imdbId': imdbId,
'movie_file_id': int(movie['movieFile']['id']),
'tags': str(tags),
'profileId': movie_default_profile})
else: else:
logging.error( logging.error(
'BAZARR Radarr returned a movie without a file path: ' + movie["path"] + separator + 'BAZARR Radarr returned a movie without a file path: ' + movie["path"] + separator +

@ -31,7 +31,7 @@ def store_subtitles(original_path, reversed_path):
if settings.general.getboolean('use_embedded_subs'): if settings.general.getboolean('use_embedded_subs'):
logging.debug("BAZARR is trying to index embedded subtitles.") logging.debug("BAZARR is trying to index embedded subtitles.")
try: try:
subtitle_languages = embedded_subs_reader.list_languages(reversed_path) subtitle_languages = embedded_subs_reader.list_languages(reversed_path, original_path)
for subtitle_language, subtitle_forced, subtitle_hi, subtitle_codec in subtitle_languages: for subtitle_language, subtitle_forced, subtitle_hi, subtitle_codec in subtitle_languages:
try: try:
if (settings.general.getboolean("ignore_pgs_subs") and subtitle_codec.lower() == "pgs") or \ if (settings.general.getboolean("ignore_pgs_subs") and subtitle_codec.lower() == "pgs") or \
@ -145,7 +145,7 @@ def store_subtitles_movie(original_path, reversed_path):
if settings.general.getboolean('use_embedded_subs'): if settings.general.getboolean('use_embedded_subs'):
logging.debug("BAZARR is trying to index embedded subtitles.") logging.debug("BAZARR is trying to index embedded subtitles.")
try: try:
subtitle_languages = embedded_subs_reader.list_languages(reversed_path) subtitle_languages = embedded_subs_reader.list_languages(reversed_path, original_path)
for subtitle_language, subtitle_forced, subtitle_hi, subtitle_codec in subtitle_languages: for subtitle_language, subtitle_forced, subtitle_hi, subtitle_codec in subtitle_languages:
try: try:
if (settings.general.getboolean("ignore_pgs_subs") and subtitle_codec.lower() == "pgs") or \ if (settings.general.getboolean("ignore_pgs_subs") and subtitle_codec.lower() == "pgs") or \

@ -399,7 +399,53 @@ def translate_subtitles_file(video_path, source_srt_file, to_lang, forced, hi):
return dest_srt_file return dest_srt_file
def check_credentials(user, pw): def check_credentials(user, pw):
username = settings.auth.username username = settings.auth.username
password = settings.auth.password password = settings.auth.password
return hashlib.md5(pw.encode('utf-8')).hexdigest() == password and user == username return hashlib.md5(pw.encode('utf-8')).hexdigest() == password and user == username
def cache_get_ffprobe(file):
record = {}
item = database.execute("SELECT sonarrEpisodeId, file_ffprobe FROM table_episodes WHERE path = ?",
(file,), only_one=True)
if item is not None:
record['id'] = item['sonarrEpisodeId']
record['type'] = 'episode'
if item['file_ffprobe']:
record['ffprobe'] = json.JSONDecoder().decode(item['file_ffprobe'])
else:
record['ffprobe'] = None
return record
item = database.execute("SELECT tmdbId, file_ffprobe FROM table_movies WHERE path = ?",
(file,), only_one=True)
if item is not None:
record['id'] = item['tmdbId']
record['type'] = 'movie'
if item['file_ffprobe']:
record['ffprobe'] = json.JSONDecoder().decode(item['file_ffprobe'])
else:
record['ffprobe'] = None
return record
return {'type': None, 'id': None, 'ffprobe': None}
def cache_save_ffprobe(file, record_id, record_type, ffprobe):
logging.debug('Saving ffprobe records [%s, %s, %s] data: %s', record_type, record_id, file, ffprobe)
if record_type == 'movie':
database.execute("UPDATE table_movies SET file_ffprobe = ? WHERE path = ? AND tmdbId = ?",
(json.JSONEncoder().encode(ffprobe), file, record_id))
if record_type == 'episode':
database.execute("UPDATE table_episodes SET file_ffprobe = ? WHERE path = ? AND sonarrEpisodeId = ?",
(json.JSONEncoder().encode(ffprobe), file, record_id))

Loading…
Cancel
Save