mirror of
https://github.com/morpheus65535/bazarr.git
synced 2025-04-23 22:27:17 -04:00
Added option to deeply analyze audio tracks from media files or not to determine languages. Default is to use Sonarr/Radarr provided languages instead. Should prevent API limit ban for cloud user.
This commit is contained in:
parent
5b283098f9
commit
5dc4e782ae
5 changed files with 112 additions and 25 deletions
|
@ -81,7 +81,8 @@ defaults = {
|
|||
'hi_extension': 'hi',
|
||||
'embedded_subtitles_parser': 'ffprobe',
|
||||
'default_und_audio_lang': '',
|
||||
'default_und_embedded_subtitles_lang': ''
|
||||
'default_und_embedded_subtitles_lang': '',
|
||||
'parse_embedded_audio_track': 'False'
|
||||
},
|
||||
'auth': {
|
||||
'type': 'None',
|
||||
|
@ -385,6 +386,7 @@ def save_settings(settings_items):
|
|||
use_embedded_subs_changed = False
|
||||
undefined_audio_track_default_changed = False
|
||||
undefined_subtitles_track_default_changed = False
|
||||
audio_tracks_parsing_changed = False
|
||||
|
||||
# Subzero Mods
|
||||
update_subzero = False
|
||||
|
@ -423,6 +425,9 @@ def save_settings(settings_items):
|
|||
if key == 'settings-general-default_und_audio_lang':
|
||||
undefined_audio_track_default_changed = True
|
||||
|
||||
if key == 'settings-general-parse_embedded_audio_track':
|
||||
audio_tracks_parsing_changed = True
|
||||
|
||||
if key == 'settings-general-default_und_embedded_subtitles_lang':
|
||||
undefined_subtitles_track_default_changed = True
|
||||
|
||||
|
@ -565,6 +570,17 @@ def save_settings(settings_items):
|
|||
if settings.general.getboolean('use_radarr'):
|
||||
scheduler.add_job(movies_full_scan_subtitles, kwargs={'use_cache': True})
|
||||
|
||||
if audio_tracks_parsing_changed:
|
||||
from .scheduler import scheduler
|
||||
if settings.general.getboolean('use_sonarr'):
|
||||
from sonarr.sync.episodes import sync_episodes
|
||||
from sonarr.sync.series import update_series
|
||||
scheduler.add_job(update_series, kwargs={'send_event': True}, max_instances=1)
|
||||
scheduler.add_job(sync_episodes, kwargs={'send_event': True}, max_instances=1)
|
||||
if settings.general.getboolean('use_radarr'):
|
||||
from radarr.sync.movies import update_movies
|
||||
scheduler.add_job(update_movies, kwargs={'send_event': True}, max_instances=1)
|
||||
|
||||
if update_subzero:
|
||||
settings.set('general', 'subzero_mods', ','.join(subzero_mods))
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
import os
|
||||
|
||||
from app.config import settings
|
||||
from languages.get_languages import language_from_alpha2
|
||||
from radarr.info import get_radarr_info
|
||||
from utilities.video_analyzer import embedded_audio_reader
|
||||
from utilities.path_mappings import path_mappings
|
||||
|
@ -90,10 +92,31 @@ def movieParser(movie, action, tags_dict, movie_default_profile, audio_profiles)
|
|||
videoCodec = None
|
||||
audioCodec = None
|
||||
|
||||
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)
|
||||
if settings.general.getboolean('parse_embedded_audio_track'):
|
||||
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)
|
||||
else:
|
||||
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)
|
||||
|
||||
tags = [d['label'] for d in tags_dict if d['id'] in movie['tags']]
|
||||
|
||||
|
@ -146,8 +169,8 @@ def movieParser(movie, action, tags_dict, movie_default_profile, audio_profiles)
|
|||
|
||||
|
||||
def profile_id_to_language(id, profiles):
|
||||
profiles_to_return = []
|
||||
for profile in profiles:
|
||||
profiles_to_return = []
|
||||
if id == profile[0]:
|
||||
profiles_to_return.append(profile[1])
|
||||
return profiles_to_return
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
import os
|
||||
|
||||
from app.config import settings
|
||||
from app.database import TableShows
|
||||
from utilities.path_mappings import path_mappings
|
||||
from utilities.video_analyzer import embedded_audio_reader
|
||||
from sonarr.info import get_sonarr_info
|
||||
|
||||
from .converter import SonarrFormatVideoCodec, SonarrFormatAudioCodec
|
||||
|
||||
|
@ -28,6 +31,16 @@ def seriesParser(show, action, tags_dict, serie_default_profile, audio_profiles)
|
|||
|
||||
imdbId = show['imdbId'] if 'imdbId' in show else None
|
||||
|
||||
audio_language = []
|
||||
if not settings.general.getboolean('parse_embedded_audio_track'):
|
||||
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 = []
|
||||
|
||||
if action == 'update':
|
||||
return {'title': show["title"],
|
||||
'path': show["path"],
|
||||
|
@ -36,7 +49,7 @@ def seriesParser(show, action, tags_dict, serie_default_profile, audio_profiles)
|
|||
'overview': overview,
|
||||
'poster': poster,
|
||||
'fanart': fanart,
|
||||
'audio_language': str([]),
|
||||
'audio_language': str(audio_language),
|
||||
'sortTitle': show['sortTitle'],
|
||||
'year': str(show['year']),
|
||||
'alternativeTitles': alternate_titles,
|
||||
|
@ -52,7 +65,7 @@ def seriesParser(show, action, tags_dict, serie_default_profile, audio_profiles)
|
|||
'overview': overview,
|
||||
'poster': poster,
|
||||
'fanart': fanart,
|
||||
'audio_language': str([]),
|
||||
'audio_language': str(audio_language),
|
||||
'sortTitle': show['sortTitle'],
|
||||
'year': str(show['year']),
|
||||
'alternativeTitles': alternate_titles,
|
||||
|
@ -85,10 +98,28 @@ def episodeParser(episode):
|
|||
else:
|
||||
sceneName = None
|
||||
|
||||
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 settings.general.getboolean('parse_embedded_audio_track'):
|
||||
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)
|
||||
else:
|
||||
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
|
||||
|
||||
if 'mediaInfo' in episode['episodeFile']:
|
||||
if 'videoCodec' in episode['episodeFile']['mediaInfo']:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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";
|
||||
|
@ -43,6 +44,13 @@ const SeriesView: FunctionComponent = () => {
|
|||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: "Audio",
|
||||
accessor: "audio_language",
|
||||
Cell: ({ value }) => {
|
||||
return <AudioList audios={value}></AudioList>;
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: "Languages Profile",
|
||||
accessor: "profileId",
|
||||
|
|
|
@ -69,19 +69,28 @@ const SettingsLanguagesView: FunctionComponent = () => {
|
|||
></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>
|
||||
<Section header="Embedded Tracks Language">
|
||||
<Check
|
||||
label="Deep analyze media file to get audio tracks language."
|
||||
settingKey="settings-general-parse_embedded_audio_track"
|
||||
></Check>
|
||||
<CollapseBox
|
||||
indent
|
||||
settingKey="settings-general-parse_embedded_audio_track"
|
||||
>
|
||||
<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>
|
||||
</CollapseBox>
|
||||
|
||||
<Selector
|
||||
clearable
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue