summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authormorpheus65535 <[email protected]>2023-02-09 16:58:38 -0500
committermorpheus65535 <[email protected]>2023-02-09 16:58:38 -0500
commit3310f6aeb88fcc9a70f9e5d6f673873ff2f1af85 (patch)
treec178ea1e9630161fb0af1161f126cd9272bd1834
parent7f05f932ffb84ba8b9e5630b2adc34dbd77e2b4a (diff)
downloadbazarr-3310f6aeb88fcc9a70f9e5d6f673873ff2f1af85.tar.gz
bazarr-3310f6aeb88fcc9a70f9e5d6f673873ff2f1af85.zip
Improved audio track language detection by using our video parser instead of values provided by Sonarr/Radarr. We also added "treat as" concept for undefined languages audio and embedded subtitles tracks. #2050v1.1.5-beta.13
-rw-r--r--bazarr/api/episodes/episodes_subtitles.py15
-rw-r--r--bazarr/api/movies/movies_subtitles.py16
-rw-r--r--bazarr/app/config.py23
-rw-r--r--bazarr/app/database.py23
-rw-r--r--bazarr/radarr/sync/parser.py26
-rw-r--r--bazarr/sonarr/sync/parser.py34
-rw-r--r--bazarr/subtitles/indexer/movies.py22
-rw-r--r--bazarr/subtitles/indexer/series.py21
-rw-r--r--bazarr/subtitles/refiners/ffprobe.py2
-rw-r--r--bazarr/subtitles/upload.py11
-rw-r--r--bazarr/utilities/video_analyzer.py (renamed from bazarr/subtitles/tools/embedded_subs_reader.py)63
-rw-r--r--frontend/src/apis/hooks/system.ts5
-rw-r--r--frontend/src/pages/Series/index.tsx8
-rw-r--r--frontend/src/pages/Settings/Languages/index.tsx46
-rw-r--r--frontend/src/pages/Settings/keys.ts3
15 files changed, 186 insertions, 132 deletions
diff --git a/bazarr/api/episodes/episodes_subtitles.py b/bazarr/api/episodes/episodes_subtitles.py
index 7943ac01e..5dfaf0eaa 100644
--- a/bazarr/api/episodes/episodes_subtitles.py
+++ b/bazarr/api/episodes/episodes_subtitles.py
@@ -118,9 +118,7 @@ class EpisodesSubtitles(Resource):
args = self.post_request_parser.parse_args()
sonarrSeriesId = args.get('seriesid')
sonarrEpisodeId = args.get('episodeid')
- episodeInfo = TableEpisodes.select(TableEpisodes.title,
- TableEpisodes.path,
- TableEpisodes.sceneName,
+ episodeInfo = TableEpisodes.select(TableEpisodes.path,
TableEpisodes.audio_language) \
.where(TableEpisodes.sonarrEpisodeId == sonarrEpisodeId) \
.dicts() \
@@ -129,10 +127,13 @@ class EpisodesSubtitles(Resource):
if not episodeInfo:
return 'Episode not found', 404
- title = episodeInfo['title']
episodePath = path_mappings.path_replace(episodeInfo['path'])
- sceneName = episodeInfo['sceneName'] or "None"
- audio_language = episodeInfo['audio_language']
+
+ audio_language = get_audio_profile_languages(episodeInfo['audio_language'])
+ if len(audio_language) and isinstance(audio_language[0], dict):
+ audio_language = audio_language[0]
+ else:
+ audio_language = {'name': '', 'code2': '', 'code3': ''}
language = args.get('language')
forced = True if args.get('forced') == 'true' else False
@@ -149,8 +150,6 @@ class EpisodesSubtitles(Resource):
language=language,
forced=forced,
hi=hi,
- title=title,
- sceneName=sceneName,
media_type='series',
subtitle=subFile,
audio_language=audio_language)
diff --git a/bazarr/api/movies/movies_subtitles.py b/bazarr/api/movies/movies_subtitles.py
index 9abdd3f71..0dbd43b69 100644
--- a/bazarr/api/movies/movies_subtitles.py
+++ b/bazarr/api/movies/movies_subtitles.py
@@ -113,9 +113,7 @@ class MoviesSubtitles(Resource):
# TODO: Support Multiply Upload
args = self.post_request_parser.parse_args()
radarrId = args.get('radarrid')
- movieInfo = TableMovies.select(TableMovies.title,
- TableMovies.path,
- TableMovies.sceneName,
+ movieInfo = TableMovies.select(TableMovies.path,
TableMovies.audio_language) \
.where(TableMovies.radarrId == radarrId) \
.dicts() \
@@ -125,10 +123,12 @@ class MoviesSubtitles(Resource):
return 'Movie not found', 404
moviePath = path_mappings.path_replace_movie(movieInfo['path'])
- sceneName = movieInfo['sceneName'] or 'None'
- title = movieInfo['title']
- audioLanguage = movieInfo['audio_language']
+ audio_language = get_audio_profile_languages(movieInfo['audio_language'])
+ if len(audio_language) and isinstance(audio_language[0], dict):
+ audio_language = audio_language[0]
+ else:
+ audio_language = {'name': '', 'code2': '', 'code3': ''}
language = args.get('language')
forced = args.get('forced') == 'true'
@@ -145,11 +145,9 @@ class MoviesSubtitles(Resource):
language=language,
forced=forced,
hi=hi,
- title=title,
- sceneName=sceneName,
media_type='movie',
subtitle=subFile,
- audio_language=audioLanguage)
+ audio_language=audio_language)
if not result:
logging.debug(f"BAZARR unable to process subtitles for this movie: {moviePath}")
diff --git a/bazarr/app/config.py b/bazarr/app/config.py
index 0ea8ad489..ba4bc8a26 100644
--- a/bazarr/app/config.py
+++ b/bazarr/app/config.py
@@ -79,7 +79,9 @@ defaults = {
'subzero_mods': '[]',
'dont_notify_manual_actions': 'False',
'hi_extension': 'hi',
- 'embedded_subtitles_parser': 'ffprobe'
+ 'embedded_subtitles_parser': 'ffprobe',
+ 'default_und_audio_lang': '',
+ 'default_und_embedded_subtitles_lang': ''
},
'auth': {
'type': 'None',
@@ -381,6 +383,8 @@ def save_settings(settings_items):
sonarr_exclusion_updated = False
radarr_exclusion_updated = False
use_embedded_subs_changed = False
+ undefined_audio_track_default_changed = False
+ undefined_subtitles_track_default_changed = False
# Subzero Mods
update_subzero = False
@@ -416,6 +420,12 @@ def save_settings(settings_items):
'settings-general-ignore_vobsub_subs', 'settings-general-ignore_ass_subs']:
use_embedded_subs_changed = True
+ if key == 'settings-general-default_und_audio_lang':
+ undefined_audio_track_default_changed = True
+
+ if key == 'settings-general-default_und_embedded_subtitles_lang':
+ undefined_subtitles_track_default_changed = True
+
if key in ['settings-general-base_url', 'settings-sonarr-base_url', 'settings-radarr-base_url']:
value = base_url_slash_cleaner(value)
@@ -537,7 +547,7 @@ def save_settings(settings_items):
update_subzero = True
- if use_embedded_subs_changed:
+ if use_embedded_subs_changed or undefined_audio_track_default_changed:
from .scheduler import scheduler
from subtitles.indexer.series import list_missing_subtitles
from subtitles.indexer.movies import list_missing_subtitles_movies
@@ -546,6 +556,15 @@ def save_settings(settings_items):
if settings.general.getboolean('use_radarr'):
scheduler.add_job(list_missing_subtitles_movies, kwargs={'send_event': True})
+ if undefined_subtitles_track_default_changed:
+ from .scheduler import scheduler
+ from subtitles.indexer.series import series_full_scan_subtitles
+ from subtitles.indexer.movies import movies_full_scan_subtitles
+ if settings.general.getboolean('use_sonarr'):
+ scheduler.add_job(series_full_scan_subtitles, kwargs={'use_cache': True})
+ if settings.general.getboolean('use_radarr'):
+ scheduler.add_job(movies_full_scan_subtitles, kwargs={'use_cache': True})
+
if update_subzero:
settings.set('general', 'subzero_mods', ','.join(subzero_mods))
diff --git a/bazarr/app/database.py b/bazarr/app/database.py
index e96eccf39..85b62387c 100644
--- a/bazarr/app/database.py
+++ b/bazarr/app/database.py
@@ -650,20 +650,31 @@ def get_profile_cutoff(profile_id):
def get_audio_profile_languages(audio_languages_list_str):
- from languages.get_languages import alpha2_from_language, alpha3_from_language
+ from languages.get_languages import alpha2_from_language, alpha3_from_language, language_from_alpha2
audio_languages = []
+ und_default_language = language_from_alpha2(settings.general.default_und_audio_lang)
+
try:
audio_languages_list = ast.literal_eval(audio_languages_list_str or '[]')
except ValueError:
pass
else:
for language in audio_languages_list:
- audio_languages.append(
- {"name": language,
- "code2": alpha2_from_language(language) or None,
- "code3": alpha3_from_language(language) or None}
- )
+ if language:
+ audio_languages.append(
+ {"name": language,
+ "code2": alpha2_from_language(language) or None,
+ "code3": alpha3_from_language(language) or None}
+ )
+ else:
+ if und_default_language:
+ logging.debug(f"Undefined language audio track treated as {und_default_language}")
+ audio_languages.append(
+ {"name": und_default_language,
+ "code2": alpha2_from_language(und_default_language) or None,
+ "code3": alpha3_from_language(und_default_language) or None}
+ )
return audio_languages
diff --git a/bazarr/radarr/sync/parser.py b/bazarr/radarr/sync/parser.py
index 017d08a47..7537bcec2 100644
--- a/bazarr/radarr/sync/parser.py
+++ b/bazarr/radarr/sync/parser.py
@@ -3,7 +3,8 @@
import os
from radarr.info import get_radarr_info
-from languages.get_languages import language_from_alpha2
+from utilities.video_analyzer import embedded_audio_reader
+from utilities.path_mappings import path_mappings
from .converter import RadarrFormatAudioCodec, RadarrFormatVideoCodec
@@ -89,25 +90,10 @@ def movieParser(movie, action, tags_dict, movie_default_profile, audio_profiles)
videoCodec = None
audioCodec = None
- audio_language = []
- if get_radarr_info.is_legacy():
- if 'mediaInfo' in movie['movieFile']:
- if 'audioLanguages' in movie['movieFile']['mediaInfo']:
- audio_languages_list = movie['movieFile']['mediaInfo']['audioLanguages'].split('/')
- if len(audio_languages_list):
- for audio_language_list in audio_languages_list:
- audio_language.append(audio_language_list.strip())
- if not audio_language:
- audio_language = profile_id_to_language(movie['qualityProfileId'], audio_profiles)
- else:
- if 'languages' in movie['movieFile'] and len(movie['movieFile']['languages']):
- for item in movie['movieFile']['languages']:
- if isinstance(item, dict):
- if 'name' in item:
- language = item['name']
- if item['name'] == 'Portuguese (Brazil)':
- language = language_from_alpha2('pb')
- audio_language.append(language)
+ audio_language = embedded_audio_reader(path_mappings.path_replace_movie(movie['movieFile']['path']),
+ file_size=movie['movieFile']['size'],
+ movie_file_id=movie['movieFile']['id'],
+ use_cache=True)
tags = [d['label'] for d in tags_dict if d['id'] in movie['tags']]
diff --git a/bazarr/sonarr/sync/parser.py b/bazarr/sonarr/sync/parser.py
index 6566e0630..9fc3c4db2 100644
--- a/bazarr/sonarr/sync/parser.py
+++ b/bazarr/sonarr/sync/parser.py
@@ -2,9 +2,8 @@
import os
-from app.database import TableShows
-from sonarr.info import get_sonarr_info
from utilities.path_mappings import path_mappings
+from utilities.video_analyzer import embedded_audio_reader
from .converter import SonarrFormatVideoCodec, SonarrFormatAudioCodec
@@ -25,15 +24,6 @@ def seriesParser(show, action, tags_dict, serie_default_profile, audio_profiles)
if show['alternateTitles'] is not None:
alternate_titles = str([item['title'] for item in show['alternateTitles']])
- audio_language = []
- if get_sonarr_info.is_legacy():
- audio_language = profile_id_to_language(show['qualityProfileId'], audio_profiles)
- else:
- if 'languageProfileId' in show:
- audio_language = profile_id_to_language(show['languageProfileId'], audio_profiles)
- else:
- audio_language = []
-
tags = [d['label'] for d in tags_dict if d['id'] in show['tags']]
imdbId = show['imdbId'] if 'imdbId' in show else None
@@ -46,7 +36,7 @@ def seriesParser(show, action, tags_dict, serie_default_profile, audio_profiles)
'overview': overview,
'poster': poster,
'fanart': fanart,
- 'audio_language': str(audio_language),
+ 'audio_language': str([]),
'sortTitle': show['sortTitle'],
'year': str(show['year']),
'alternativeTitles': alternate_titles,
@@ -62,7 +52,7 @@ def seriesParser(show, action, tags_dict, serie_default_profile, audio_profiles)
'overview': overview,
'poster': poster,
'fanart': fanart,
- 'audio_language': str(audio_language),
+ 'audio_language': str([]),
'sortTitle': show['sortTitle'],
'year': str(show['year']),
'alternativeTitles': alternate_titles,
@@ -95,20 +85,10 @@ def episodeParser(episode):
else:
sceneName = None
- audio_language = []
- if 'language' in episode['episodeFile'] and len(episode['episodeFile']['language']):
- item = episode['episodeFile']['language']
- if isinstance(item, dict):
- if 'name' in item:
- audio_language.append(item['name'])
- elif 'languages' in episode['episodeFile'] and len(episode['episodeFile']['languages']):
- items = episode['episodeFile']['languages']
- if isinstance(items, list):
- for item in items:
- if 'name' in item:
- audio_language.append(item['name'])
- else:
- audio_language = TableShows.get(TableShows.sonarrSeriesId == episode['seriesId']).audio_language
+ audio_language = embedded_audio_reader(path_mappings.path_replace(episode['episodeFile']['path']),
+ file_size=episode['episodeFile']['size'],
+ episode_file_id=episode['episodeFile']['id'],
+ use_cache=True)
if 'mediaInfo' in episode['episodeFile']:
if 'videoCodec' in episode['episodeFile']['mediaInfo']:
diff --git a/bazarr/subtitles/indexer/movies.py b/bazarr/subtitles/indexer/movies.py
index 05e41506f..97c247760 100644
--- a/bazarr/subtitles/indexer/movies.py
+++ b/bazarr/subtitles/indexer/movies.py
@@ -8,12 +8,12 @@ import ast
from subliminal_patch import core, search_external_subtitles
from languages.custom_lang import CustomLanguage
-from app.database import get_profiles_list, get_profile_cutoff, TableMovies
-from languages.get_languages import alpha2_from_alpha3, language_from_alpha2, get_language_set
+from app.database import get_profiles_list, get_profile_cutoff, TableMovies, get_audio_profile_languages
+from languages.get_languages import alpha2_from_alpha3, get_language_set
from app.config import settings
from utilities.helper import get_subtitle_destination_folder
from utilities.path_mappings import path_mappings
-from subtitles.tools.embedded_subs_reader import embedded_subs_reader
+from utilities.video_analyzer import embedded_subs_reader
from app.event_handler import event_stream, show_progress, hide_progress
from subtitles.indexer.utils import guess_external_subtitles, get_external_subtitles_path
@@ -168,8 +168,8 @@ def list_missing_subtitles_movies(no=None, send_event=True):
if desired_subtitles_temp:
for language in desired_subtitles_temp['items']:
if language['audio_exclude'] == "True":
- if language_from_alpha2(language['language']) in ast.literal_eval(
- movie_subtitles['audio_language']):
+ if any(x['code2'] == language['language'] for x in get_audio_profile_languages(
+ movie_subtitles['audio_language'])):
continue
desired_subtitles_list.append([language['language'], language['forced'], language['hi']])
@@ -202,8 +202,9 @@ def list_missing_subtitles_movies(no=None, send_event=True):
if cutoff_temp_list:
for cutoff_temp in cutoff_temp_list:
cutoff_language = [cutoff_temp['language'], cutoff_temp['forced'], cutoff_temp['hi']]
- if cutoff_temp['audio_exclude'] == 'True' and language_from_alpha2(cutoff_temp['language']) in \
- ast.literal_eval(movie_subtitles['audio_language']):
+ if cutoff_temp['audio_exclude'] == 'True' and \
+ any(x['code2'] == cutoff_temp['language'] for x in
+ get_audio_profile_languages(movie_subtitles['audio_language'])):
cutoff_met = True
elif cutoff_language in actual_subtitles_list:
cutoff_met = True
@@ -251,9 +252,7 @@ def list_missing_subtitles_movies(no=None, send_event=True):
event_stream(type='badges')
-def movies_full_scan_subtitles():
- use_ffprobe_cache = settings.radarr.getboolean('use_ffprobe_cache')
-
+def movies_full_scan_subtitles(use_cache=settings.radarr.getboolean('use_ffprobe_cache')):
movies = TableMovies.select(TableMovies.path).dicts()
count_movies = len(movies)
@@ -263,8 +262,7 @@ def movies_full_scan_subtitles():
name='Movies subtitles',
value=i,
count=count_movies)
- store_subtitles_movie(movie['path'], path_mappings.path_replace_movie(movie['path']),
- use_cache=use_ffprobe_cache)
+ store_subtitles_movie(movie['path'], path_mappings.path_replace_movie(movie['path']), use_cache=use_cache)
hide_progress(id='movies_disk_scan')
diff --git a/bazarr/subtitles/indexer/series.py b/bazarr/subtitles/indexer/series.py
index c93ad8f4e..e7091bf45 100644
--- a/bazarr/subtitles/indexer/series.py
+++ b/bazarr/subtitles/indexer/series.py
@@ -8,12 +8,12 @@ import ast
from subliminal_patch import core, search_external_subtitles
from languages.custom_lang import CustomLanguage
-from app.database import get_profiles_list, get_profile_cutoff, TableEpisodes, TableShows
-from languages.get_languages import alpha2_from_alpha3, language_from_alpha2, get_language_set
+from app.database import get_profiles_list, get_profile_cutoff, TableEpisodes, TableShows, get_audio_profile_languages
+from languages.get_languages import alpha2_from_alpha3, get_language_set
from app.config import settings
from utilities.helper import get_subtitle_destination_folder
from utilities.path_mappings import path_mappings
-from subtitles.tools.embedded_subs_reader import embedded_subs_reader
+from utilities.video_analyzer import embedded_subs_reader
from app.event_handler import event_stream, show_progress, hide_progress
from subtitles.indexer.utils import guess_external_subtitles, get_external_subtitles_path
@@ -176,8 +176,8 @@ def list_missing_subtitles(no=None, epno=None, send_event=True):
if desired_subtitles_temp:
for language in desired_subtitles_temp['items']:
if language['audio_exclude'] == "True":
- if language_from_alpha2(language['language']) in ast.literal_eval(
- episode_subtitles['audio_language']):
+ if any(x['code2'] == language['language'] for x in get_audio_profile_languages(
+ episode_subtitles['audio_language'])):
continue
desired_subtitles_list.append([language['language'], language['forced'], language['hi']])
@@ -210,8 +210,9 @@ def list_missing_subtitles(no=None, epno=None, send_event=True):
if cutoff_temp_list:
for cutoff_temp in cutoff_temp_list:
cutoff_language = [cutoff_temp['language'], cutoff_temp['forced'], cutoff_temp['hi']]
- if cutoff_temp['audio_exclude'] == 'True' and language_from_alpha2(cutoff_temp['language']) in \
- ast.literal_eval(episode_subtitles['audio_language']):
+ if cutoff_temp['audio_exclude'] == 'True' and \
+ any(x['code2'] == cutoff_temp['language'] for x in
+ get_audio_profile_languages(episode_subtitles['audio_language'])):
cutoff_met = True
elif cutoff_language in actual_subtitles_list:
cutoff_met = True
@@ -261,9 +262,7 @@ def list_missing_subtitles(no=None, epno=None, send_event=True):
event_stream(type='badges')
-def series_full_scan_subtitles():
- use_ffprobe_cache = settings.sonarr.getboolean('use_ffprobe_cache')
-
+def series_full_scan_subtitles(use_cache=settings.sonarr.getboolean('use_ffprobe_cache')):
episodes = TableEpisodes.select(TableEpisodes.path).dicts()
count_episodes = len(episodes)
@@ -273,7 +272,7 @@ def series_full_scan_subtitles():
name='Episodes subtitles',
value=i,
count=count_episodes)
- store_subtitles(episode['path'], path_mappings.path_replace(episode['path']), use_cache=use_ffprobe_cache)
+ store_subtitles(episode['path'], path_mappings.path_replace(episode['path']), use_cache=use_cache)
hide_progress(id='episodes_disk_scan')
diff --git a/bazarr/subtitles/refiners/ffprobe.py b/bazarr/subtitles/refiners/ffprobe.py
index c1c69072e..22c21a67c 100644
--- a/bazarr/subtitles/refiners/ffprobe.py
+++ b/bazarr/subtitles/refiners/ffprobe.py
@@ -7,7 +7,7 @@ from subliminal import Movie
from utilities.path_mappings import path_mappings
from app.database import TableEpisodes, TableMovies
-from subtitles.tools.embedded_subs_reader import parse_video_metadata
+from utilities.video_analyzer import parse_video_metadata
def refine_from_ffprobe(path, video):
diff --git a/bazarr/subtitles/upload.py b/bazarr/subtitles/upload.py
index 19e1d965d..6891261f8 100644
--- a/bazarr/subtitles/upload.py
+++ b/bazarr/subtitles/upload.py
@@ -10,8 +10,7 @@ from subliminal_patch.core import save_subtitles
from subliminal_patch.subtitle import Subtitle
from pysubs2.formats import get_format_identifier
-from languages.get_languages import language_from_alpha3, alpha2_from_alpha3, alpha3_from_alpha2, \
- alpha2_from_language, alpha3_from_language
+from languages.get_languages import language_from_alpha3, alpha2_from_alpha3, alpha3_from_alpha2
from app.config import settings, get_array_from
from utilities.helper import get_target_folder, force_unicode
from utilities.post_processing import pp_replace
@@ -26,7 +25,7 @@ from .sync import sync_subtitles
from .post_processing import postprocessing
-def manual_upload_subtitle(path, language, forced, hi, title, sceneName, media_type, subtitle, audio_language):
+def manual_upload_subtitle(path, language, forced, hi, media_type, subtitle, audio_language):
logging.debug(f'BAZARR Manually uploading subtitles for this file: {path}')
single = settings.general.getboolean('single_language')
@@ -131,8 +130,6 @@ def manual_upload_subtitle(path, language, forced, hi, title, sceneName, media_t
uploaded_language_code3 = language + modifier_code
uploaded_language = language_from_alpha3(language) + modifier_string
uploaded_language_code2 = alpha2_from_alpha3(language) + modifier_code
- audio_language_code2 = alpha2_from_language(audio_language)
- audio_language_code3 = alpha3_from_language(audio_language)
if media_type == 'series':
if not episode_metadata:
@@ -152,8 +149,8 @@ def manual_upload_subtitle(path, language, forced, hi, title, sceneName, media_t
if use_postprocessing:
command = pp_replace(postprocessing_cmd, path, subtitle_path, uploaded_language, uploaded_language_code2,
- uploaded_language_code3, audio_language, audio_language_code2, audio_language_code3, 100,
- "1", "manual", series_id, episode_id)
+ uploaded_language_code3, audio_language['name'], audio_language['code2'],
+ audio_language['code3'], 100, "1", "manual", series_id, episode_id)
postprocessing(command, path)
if media_type == 'series':
diff --git a/bazarr/subtitles/tools/embedded_subs_reader.py b/bazarr/utilities/video_analyzer.py
index 238370d03..72c3a1b5f 100644
--- a/bazarr/subtitles/tools/embedded_subs_reader.py
+++ b/bazarr/utilities/video_analyzer.py
@@ -6,6 +6,7 @@ import pickle
from knowit.api import know, KnowitException
from languages.custom_lang import CustomLanguage
+from languages.get_languages import language_from_alpha3, alpha3_from_alpha2
from app.database import TableEpisodes, TableMovies
from utilities.path_mappings import path_mappings
from app.config import settings
@@ -24,49 +25,73 @@ def _handle_alpha3(detected_language: dict):
def embedded_subs_reader(file, file_size, episode_file_id=None, movie_file_id=None, use_cache=True):
data = parse_video_metadata(file, file_size, episode_file_id, movie_file_id, use_cache=use_cache)
+ und_default_language = alpha3_from_alpha2(settings.general.default_und_embedded_subtitles_lang)
subtitles_list = []
if not data:
return subtitles_list
+ cache_provider = None
if data["ffprobe"] and "subtitle" in data["ffprobe"]:
- for detected_language in data["ffprobe"]["subtitle"]:
- if "language" not in detected_language:
- continue
+ cache_provider = 'ffprobe'
+ elif 'mediainfo' in data and data["mediainfo"] and "subtitle" in data["mediainfo"]:
+ cache_provider = 'mediainfo'
+ if cache_provider:
+ for detected_language in data[cache_provider]["subtitle"]:
# Avoid commentary subtitles
name = detected_language.get("name", "").lower()
if "commentary" in name:
- logging.debug("Ignoring commentary subtitle: %s", name)
+ logging.debug(f"Ignoring commentary subtitle: {name}")
continue
- language = _handle_alpha3(detected_language)
+ if "language" not in detected_language:
+ language = None
+ else:
+ language = _handle_alpha3(detected_language)
+
+ if not language and und_default_language:
+ logging.debug(f"Undefined language embedded subtitles track treated as {language}")
+ language = und_default_language
+
+ if not language:
+ continue
forced = detected_language.get("forced", False)
hearing_impaired = detected_language.get("hearing_impaired", False)
codec = detected_language.get("format") # or None
subtitles_list.append([language, forced, hearing_impaired, codec])
- elif 'mediainfo' in data and data["mediainfo"] and "subtitle" in data["mediainfo"]:
- for detected_language in data["mediainfo"]["subtitle"]:
- if "language" not in detected_language:
- continue
+ return subtitles_list
- # Avoid commentary subtitles
- name = detected_language.get("name", "").lower()
- if "commentary" in name:
- logging.debug("Ignoring commentary subtitle: %s", name)
+
+def embedded_audio_reader(file, file_size, episode_file_id=None, movie_file_id=None, use_cache=True):
+ data = parse_video_metadata(file, file_size, episode_file_id, movie_file_id, use_cache=use_cache)
+
+ audio_list = []
+
+ if not data:
+ return audio_list
+
+ cache_provider = None
+ if data["ffprobe"] and "audio" in data["ffprobe"]:
+ cache_provider = 'ffprobe'
+ elif 'mediainfo' in data and data["mediainfo"] and "audio" in data["mediainfo"]:
+ cache_provider = 'mediainfo'
+
+ if cache_provider:
+ for detected_language in data[cache_provider]["audio"]:
+ if "language" not in detected_language:
+ audio_list.append(None)
continue
- language = _handle_alpha3(detected_language)
+ language = language_from_alpha3(detected_language["language"].alpha3)
- forced = detected_language.get("forced", False)
- hearing_impaired = detected_language.get("hearing_impaired", False)
- codec = detected_language.get("format") # or None
- subtitles_list.append([language, forced, hearing_impaired, codec])
+ if language not in audio_list:
+ audio_list.append(language)
- return subtitles_list
+ return audio_list
def parse_video_metadata(file, file_size, episode_file_id=None, movie_file_id=None, use_cache=True):
diff --git a/frontend/src/apis/hooks/system.ts b/frontend/src/apis/hooks/system.ts
index 24691c4b6..9be28c4d2 100644
--- a/frontend/src/apis/hooks/system.ts
+++ b/frontend/src/apis/hooks/system.ts
@@ -49,6 +49,11 @@ export function useSettingsMutation() {
{
onSuccess: () => {
client.invalidateQueries([QueryKeys.System]);
+ client.invalidateQueries([QueryKeys.Series]);
+ client.invalidateQueries([QueryKeys.Episodes]);
+ client.invalidateQueries([QueryKeys.Movies]);
+ client.invalidateQueries([QueryKeys.Wanted]);
+ client.invalidateQueries([QueryKeys.Badges]);
},
}
);
diff --git a/frontend/src/pages/Series/index.tsx b/frontend/src/pages/Series/index.tsx
index 6dfe07230..da20c4459 100644
--- a/frontend/src/pages/Series/index.tsx
+++ b/frontend/src/pages/Series/index.tsx
@@ -1,6 +1,5 @@
import { useSeriesModification, useSeriesPagination } from "@/apis/hooks";
import { Action } from "@/components";
-import { AudioList } from "@/components/bazarr";
import LanguageProfileName from "@/components/bazarr/LanguageProfile";
import { ItemEditModal } from "@/components/forms/ItemEditForm";
import { useModals } from "@/modules/modals";
@@ -45,13 +44,6 @@ const SeriesView: FunctionComponent = () => {
},
},
{
- Header: "Audio",
- accessor: "audio_language",
- Cell: ({ value }) => {
- return <AudioList audios={value}></AudioList>;
- },
- },
- {
Header: "Languages Profile",
accessor: "profileId",
Cell: ({ value }) => {
diff --git a/frontend/src/pages/Settings/Languages/index.tsx b/frontend/src/pages/Settings/Languages/index.tsx
index 726992916..4616ab1ab 100644
--- a/frontend/src/pages/Settings/Languages/index.tsx
+++ b/frontend/src/pages/Settings/Languages/index.tsx
@@ -1,8 +1,20 @@
import { useLanguageProfiles, useLanguages } from "@/apis/hooks";
import { useEnabledLanguages } from "@/utilities/languages";
import { FunctionComponent } from "react";
-import { Check, CollapseBox, Layout, Message, Section } from "../components";
-import { enabledLanguageKey, languageProfileKey } from "../keys";
+import {
+ Check,
+ CollapseBox,
+ Layout,
+ Message,
+ Section,
+ Selector,
+} from "../components";
+import {
+ defaultUndAudioLang,
+ defaultUndEmbeddedSubtitlesLang,
+ enabledLanguageKey,
+ languageProfileKey,
+} from "../keys";
import { useSettingValue } from "../utilities/hooks";
import { LanguageSelector, ProfileSelector } from "./components";
import Table from "./table";
@@ -31,6 +43,8 @@ export function useLatestProfiles() {
const SettingsLanguagesView: FunctionComponent = () => {
const { data: languages } = useLanguages();
+ const { data: und_audio_languages } = useEnabledLanguages();
+ const { data: und_embedded_subtitles_languages } = useEnabledLanguages();
return (
<Layout name="Languages">
<Section header="Subtitles Language">
@@ -54,6 +68,34 @@ const SettingsLanguagesView: FunctionComponent = () => {
options={languages ?? []}
></LanguageSelector>
</Section>
+
+ <Section header="Default Unknown Track Language">
+ <Selector
+ clearable
+ settingKey={defaultUndAudioLang}
+ label="Treat unknown language audio track as (changing this will trigger missing subtitles calculation)"
+ placeholder="Select languages"
+ options={und_audio_languages.map((v) => {
+ return { label: v.name, value: v.code2 };
+ })}
+ settingOptions={{
+ onSubmit: (v) => (v === null ? "" : v),
+ }}
+ ></Selector>
+
+ <Selector
+ clearable
+ settingKey={defaultUndEmbeddedSubtitlesLang}
+ label="Treat unknown language embedded subtitles track as (changing this will trigger full subtitles indexation using cache)"
+ placeholder="Select languages"
+ options={und_embedded_subtitles_languages.map((v) => {
+ return { label: v.name, value: v.code2 };
+ })}
+ settingOptions={{
+ onSubmit: (v) => (v === null ? "" : v),
+ }}
+ ></Selector>
+ </Section>
<Section header="Languages Profiles">
<Table></Table>
</Section>
diff --git a/frontend/src/pages/Settings/keys.ts b/frontend/src/pages/Settings/keys.ts
index a8ab17a5b..40b6a252d 100644
--- a/frontend/src/pages/Settings/keys.ts
+++ b/frontend/src/pages/Settings/keys.ts
@@ -1,4 +1,7 @@
export const enabledLanguageKey = "languages-enabled";
+export const defaultUndAudioLang = "settings-general-default_und_audio_lang";
+export const defaultUndEmbeddedSubtitlesLang =
+ "settings-general-default_und_embedded_subtitles_lang";
export const languageProfileKey = "languages-profiles";
export const notificationsKey = "notifications-providers";