mirror of
https://github.com/morpheus65535/bazarr.git
synced 2024-11-10 09:02:44 +08:00
Added languages profile settings to prevent downloaded subtitles from being converted to srt.
This commit is contained in:
parent
684797d6e4
commit
33a9e512ac
17 changed files with 71 additions and 20 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -10,6 +10,9 @@ bazarr.pid
|
|||
.idea
|
||||
.vscode
|
||||
|
||||
# LSP
|
||||
pyrightconfig.json
|
||||
|
||||
# Middleware
|
||||
VERSION
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ class ProviderEpisodes(Resource):
|
|||
|
||||
hi = request.form.get('hi').capitalize()
|
||||
forced = request.form.get('forced').capitalize()
|
||||
use_original_format = request.form.get('original_format').capitalize()
|
||||
selected_provider = request.form.get('provider')
|
||||
subtitle = request.form.get('subtitle')
|
||||
|
||||
|
@ -77,8 +78,7 @@ class ProviderEpisodes(Resource):
|
|||
|
||||
try:
|
||||
result = manual_download_subtitle(episodePath, audio_language, hi, forced, subtitle, selected_provider,
|
||||
sceneName, title, 'series',
|
||||
profile_id=get_profile_id(episode_id=sonarrEpisodeId))
|
||||
sceneName, title, 'series', use_original_format, profile_id=get_profile_id(episode_id=sonarrEpisodeId))
|
||||
if result is not None:
|
||||
message = result[0]
|
||||
path = result[1]
|
||||
|
|
|
@ -13,6 +13,7 @@ from notifier import send_notifications_movie
|
|||
from list_subtitles import store_subtitles_movie
|
||||
|
||||
from ..utils import authenticate
|
||||
import logging
|
||||
|
||||
|
||||
class ProviderMovies(Resource):
|
||||
|
@ -64,6 +65,8 @@ class ProviderMovies(Resource):
|
|||
|
||||
hi = request.form.get('hi').capitalize()
|
||||
forced = request.form.get('forced').capitalize()
|
||||
use_original_format = request.form.get('original_format').capitalize()
|
||||
logging.debug(f"use_original_format {use_original_format}")
|
||||
selected_provider = request.form.get('provider')
|
||||
subtitle = request.form.get('subtitle')
|
||||
|
||||
|
@ -75,7 +78,7 @@ class ProviderMovies(Resource):
|
|||
|
||||
try:
|
||||
result = manual_download_subtitle(moviePath, audio_language, hi, forced, subtitle, selected_provider,
|
||||
sceneName, title, 'movie', profile_id=get_profile_id(movie_id=radarrId))
|
||||
sceneName, title, 'movie', use_original_format, profile_id=get_profile_id(movie_id=radarrId))
|
||||
if result is not None:
|
||||
message = result[0]
|
||||
path = result[1]
|
||||
|
|
|
@ -73,7 +73,8 @@ class Subtitles(Resource):
|
|||
else:
|
||||
return '', 404
|
||||
else:
|
||||
subtitles_apply_mods(language, subtitles_path, [action])
|
||||
use_original_format = True if request.form.get('original_format') == 'true' else False
|
||||
subtitles_apply_mods(language, subtitles_path, [action], use_original_format)
|
||||
|
||||
# apply chmod if required
|
||||
chmod = int(settings.general.chmod, 8) if not sys.platform.startswith(
|
||||
|
|
|
@ -59,6 +59,7 @@ class SystemSettings(Resource):
|
|||
TableLanguagesProfiles.items: json.dumps(item['items']),
|
||||
TableLanguagesProfiles.mustContain: item['mustContain'],
|
||||
TableLanguagesProfiles.mustNotContain: item['mustNotContain'],
|
||||
TableLanguagesProfiles.originalFormat: item['originalFormat'] if item['originalFormat'] != 'null' else None,
|
||||
})\
|
||||
.where(TableLanguagesProfiles.profileId == item['profileId'])\
|
||||
.execute()
|
||||
|
@ -72,6 +73,7 @@ class SystemSettings(Resource):
|
|||
TableLanguagesProfiles.items: json.dumps(item['items']),
|
||||
TableLanguagesProfiles.mustContain: item['mustContain'],
|
||||
TableLanguagesProfiles.mustNotContain: item['mustNotContain'],
|
||||
TableLanguagesProfiles.originalFormat: item['originalFormat'] if item['originalFormat'] != 'null' else None,
|
||||
}).execute()
|
||||
for profileId in existing:
|
||||
# Unassign this profileId from series and movies
|
||||
|
|
|
@ -131,6 +131,7 @@ class TableHistoryMovie(BaseModel):
|
|||
|
||||
class TableLanguagesProfiles(BaseModel):
|
||||
cutoff = IntegerField(null=True)
|
||||
originalFormat = BooleanField(null=True)
|
||||
items = TextField()
|
||||
name = TextField()
|
||||
profileId = AutoField()
|
||||
|
@ -332,6 +333,7 @@ def migrate_db():
|
|||
migrator.add_column('table_history_movie', 'subtitles_path', TextField(null=True)),
|
||||
migrator.add_column('table_languages_profiles', 'mustContain', TextField(null=True)),
|
||||
migrator.add_column('table_languages_profiles', 'mustNotContain', TextField(null=True)),
|
||||
migrator.add_column('table_languages_profiles', 'originalFormat', BooleanField(null=True)),
|
||||
)
|
||||
|
||||
|
||||
|
@ -402,7 +404,8 @@ def update_profile_id_list():
|
|||
TableLanguagesProfiles.cutoff,
|
||||
TableLanguagesProfiles.items,
|
||||
TableLanguagesProfiles.mustContain,
|
||||
TableLanguagesProfiles.mustNotContain).dicts()
|
||||
TableLanguagesProfiles.mustNotContain,
|
||||
TableLanguagesProfiles.originalFormat).dicts()
|
||||
profile_id_list = list(profile_id_list)
|
||||
for profile in profile_id_list:
|
||||
profile['items'] = json.loads(profile['items'])
|
||||
|
@ -434,7 +437,7 @@ def get_desired_languages(profile_id):
|
|||
|
||||
if profile_id and profile_id != 'null':
|
||||
for profile in profile_id_list:
|
||||
profileId, name, cutoff, items, mustContain, mustNotContain = profile.values()
|
||||
profileId, name, cutoff, items, mustContain, mustNotContain, originalFormat = profile.values()
|
||||
if profileId == int(profile_id):
|
||||
languages = [x['language'] for x in items]
|
||||
break
|
||||
|
@ -450,7 +453,7 @@ def get_profile_id_name(profile_id):
|
|||
|
||||
if profile_id and profile_id != 'null':
|
||||
for profile in profile_id_list:
|
||||
profileId, name, cutoff, items, mustContain, mustNotContain = profile.values()
|
||||
profileId, name, cutoff, items, mustContain, mustNotContain, originalFormat = profile.values()
|
||||
if profileId == int(profile_id):
|
||||
name_from_id = name
|
||||
break
|
||||
|
@ -467,7 +470,7 @@ def get_profile_cutoff(profile_id):
|
|||
if profile_id and profile_id != 'null':
|
||||
cutoff_language = []
|
||||
for profile in profile_id_list:
|
||||
profileId, name, cutoff, items, mustContain, mustNotContain = profile.values()
|
||||
profileId, name, cutoff, items, mustContain, mustNotContain, originalFormat = profile.values()
|
||||
if cutoff:
|
||||
if profileId == int(profile_id):
|
||||
for item in items:
|
||||
|
|
|
@ -72,8 +72,10 @@ def generate_subtitles(path, languages, audio_language, sceneName, title, media_
|
|||
if not subtitles:
|
||||
continue
|
||||
|
||||
subtitle_formats = set()
|
||||
for s in subtitles:
|
||||
s.mods = subz_mods
|
||||
subtitle_formats.add(s.format)
|
||||
|
||||
try:
|
||||
fld = get_target_folder(path)
|
||||
|
@ -84,7 +86,7 @@ def generate_subtitles(path, languages, audio_language, sceneName, title, media_
|
|||
tags=None, # fixme
|
||||
directory=fld,
|
||||
chmod=chmod,
|
||||
# formats=("srt", "vtt")
|
||||
formats=tuple(subtitle_formats),
|
||||
path_decoder=force_unicode
|
||||
)
|
||||
except Exception as e:
|
||||
|
|
|
@ -31,7 +31,7 @@ def manual_search(path, profile_id, providers, sceneName, title, media_type):
|
|||
|
||||
pool = _get_pool(media_type, profile_id)
|
||||
|
||||
language_set, initial_language_set = _get_language_obj(profile_id=profile_id)
|
||||
language_set, initial_language_set, original_format = _get_language_obj(profile_id=profile_id)
|
||||
also_forced = any([x.forced for x in initial_language_set])
|
||||
_set_forced_providers(also_forced=also_forced, pool=pool)
|
||||
|
||||
|
@ -136,6 +136,7 @@ def manual_search(path, profile_id, providers, sceneName, title, media_type):
|
|||
provider=s.provider_name,
|
||||
subtitle=codecs.encode(pickle.dumps(s.make_picklable()), "base64").decode(),
|
||||
url=s.page_link,
|
||||
original_format=original_format,
|
||||
matches=list(matches),
|
||||
dont_matches=list(not_matched),
|
||||
release_info=releases,
|
||||
|
@ -153,7 +154,7 @@ def manual_search(path, profile_id, providers, sceneName, title, media_type):
|
|||
|
||||
@update_pools
|
||||
def manual_download_subtitle(path, audio_language, hi, forced, subtitle, provider, sceneName, title, media_type,
|
||||
profile_id):
|
||||
use_original_format, profile_id):
|
||||
logging.debug('BAZARR Manually downloading Subtitles for this file: ' + path)
|
||||
|
||||
if settings.general.getboolean('utf8_encode'):
|
||||
|
@ -170,6 +171,8 @@ def manual_download_subtitle(path, audio_language, hi, forced, subtitle, provide
|
|||
subtitle.language.forced = True
|
||||
else:
|
||||
subtitle.language.forced = False
|
||||
if use_original_format == 'True':
|
||||
subtitle.use_original_format = use_original_format
|
||||
subtitle.mods = get_array_from(settings.general.subzero_mods)
|
||||
video = get_video(force_unicode(path), title, sceneName, providers={provider}, media_type=media_type)
|
||||
if video:
|
||||
|
@ -195,7 +198,7 @@ def manual_download_subtitle(path, audio_language, hi, forced, subtitle, provide
|
|||
tags=None, # fixme
|
||||
directory=get_target_folder(path),
|
||||
chmod=chmod,
|
||||
# formats=("srt", "vtt")
|
||||
formats=(subtitle.format,),
|
||||
path_decoder=force_unicode)
|
||||
except Exception:
|
||||
logging.exception('BAZARR Error saving Subtitles file to disk for this file:' + path)
|
||||
|
@ -228,8 +231,9 @@ def _get_language_obj(profile_id):
|
|||
initial_language_set = set()
|
||||
language_set = set()
|
||||
|
||||
# where [3] is items list of dict(id, lang, forced, hi)
|
||||
language_items = get_profiles_list(profile_id=int(profile_id))['items']
|
||||
profile = get_profiles_list(profile_id=int(profile_id))
|
||||
language_items = profile['items']
|
||||
original_format = profile['originalFormat']
|
||||
|
||||
for language in language_items:
|
||||
forced = language['forced']
|
||||
|
@ -259,7 +263,7 @@ def _get_language_obj(profile_id):
|
|||
continue
|
||||
language_set.add(lang_obj_hi)
|
||||
|
||||
return language_set, initial_language_set
|
||||
return language_set, initial_language_set, original_format
|
||||
|
||||
|
||||
def _set_forced_providers(also_forced, pool):
|
||||
|
|
|
@ -63,7 +63,7 @@ def manual_upload_subtitle(path, language, forced, hi, title, scene_name, media_
|
|||
tags=None, # fixme
|
||||
directory=get_target_folder(path),
|
||||
chmod=chmod,
|
||||
# formats=("srt", "vtt")
|
||||
formats=(sub.format,),
|
||||
path_decoder=force_unicode)
|
||||
except Exception:
|
||||
logging.exception('BAZARR Error saving Subtitles file to disk for this file:' + path)
|
||||
|
|
|
@ -415,7 +415,7 @@ def delete_subtitles(media_type, language, forced, hi, media_path, subtitles_pat
|
|||
return True
|
||||
|
||||
|
||||
def subtitles_apply_mods(language, subtitle_path, mods):
|
||||
def subtitles_apply_mods(language, subtitle_path, mods, use_original_format):
|
||||
language = alpha3_from_alpha2(language)
|
||||
custom = CustomLanguage.from_value(language, "alpha3")
|
||||
if custom is None:
|
||||
|
@ -423,7 +423,7 @@ def subtitles_apply_mods(language, subtitle_path, mods):
|
|||
else:
|
||||
lang_obj = custom.subzero_language()
|
||||
|
||||
sub = Subtitle(lang_obj, mods=mods)
|
||||
sub = Subtitle(lang_obj, mods=mods, original_format=use_original_format)
|
||||
with open(subtitle_path, 'rb') as f:
|
||||
sub.content = f.read()
|
||||
|
||||
|
@ -431,6 +431,9 @@ def subtitles_apply_mods(language, subtitle_path, mods):
|
|||
logging.exception('BAZARR Invalid subtitle file: ' + subtitle_path)
|
||||
return
|
||||
|
||||
if use_original_format:
|
||||
return
|
||||
|
||||
content = sub.get_modified_content()
|
||||
if content:
|
||||
if os.path.exists(subtitle_path):
|
||||
|
|
2
frontend/src/@types/api.d.ts
vendored
2
frontend/src/@types/api.d.ts
vendored
|
@ -35,6 +35,7 @@ declare namespace Language {
|
|||
items: ProfileItem[];
|
||||
mustContain: string[];
|
||||
mustNotContain: string[];
|
||||
originalFormat: boolean | null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,6 +253,7 @@ interface SearchResultType {
|
|||
subtitle: any;
|
||||
uploader?: string;
|
||||
url?: string;
|
||||
original_format: PythonBoolean;
|
||||
}
|
||||
|
||||
interface ReleaseInfo {
|
||||
|
|
1
frontend/src/@types/form.d.ts
vendored
1
frontend/src/@types/form.d.ts
vendored
|
@ -72,5 +72,6 @@ declare namespace FormType {
|
|||
forced: PythonBoolean;
|
||||
provider: string;
|
||||
subtitle: any;
|
||||
original_format: PythonBoolean;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ const Table: FunctionComponent<Props> = ({
|
|||
forced,
|
||||
provider,
|
||||
subtitle,
|
||||
original_format,
|
||||
} = result;
|
||||
const { sonarrSeriesId: seriesId, sonarrEpisodeId: episodeId } = item;
|
||||
|
||||
|
@ -64,6 +65,7 @@ const Table: FunctionComponent<Props> = ({
|
|||
forced,
|
||||
provider,
|
||||
subtitle,
|
||||
original_format: original_format,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
|
@ -60,6 +60,7 @@ const MovieDetailView: FunctionComponent<Props> = ({ match }) => {
|
|||
forced,
|
||||
provider,
|
||||
subtitle,
|
||||
original_format,
|
||||
} = result;
|
||||
const { radarrId } = item;
|
||||
|
||||
|
@ -71,6 +72,7 @@ const MovieDetailView: FunctionComponent<Props> = ({ match }) => {
|
|||
forced,
|
||||
provider,
|
||||
subtitle,
|
||||
original_format,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
|
@ -34,6 +34,7 @@ function createDefaultProfile(): Language.Profile {
|
|||
cutoff: null,
|
||||
mustContain: [],
|
||||
mustNotContain: [],
|
||||
originalFormat: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -285,6 +286,18 @@ const LanguagesProfileModal: FunctionComponent<Props & BaseModalProps> = (
|
|||
will be excluded from search results (regex supported).
|
||||
</Message>
|
||||
</Input>
|
||||
<Input name="Original Format">
|
||||
<Selector
|
||||
clearable
|
||||
options={[
|
||||
{ label: "Enable", value: true },
|
||||
{ label: "Disable", value: false },
|
||||
]}
|
||||
value={current.originalFormat}
|
||||
onChange={(value) => updateProfile("originalFormat", value)}
|
||||
></Selector>
|
||||
<Message>Download subtitle file without format conversion</Message>
|
||||
</Input>
|
||||
</BaseModal>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -166,6 +166,7 @@ const Table: FunctionComponent = () => {
|
|||
cutoff: null,
|
||||
mustContain: [],
|
||||
mustNotContain: [],
|
||||
originalFormat: false,
|
||||
};
|
||||
showModal("profile", profile);
|
||||
}}
|
||||
|
|
|
@ -61,8 +61,10 @@ class Subtitle(Subtitle_):
|
|||
pack_data = None
|
||||
_guessed_encoding = None
|
||||
_is_valid = False
|
||||
use_original_format = False
|
||||
format = "srt" # default format is srt
|
||||
|
||||
def __init__(self, language, hearing_impaired=False, page_link=None, encoding=None, mods=None):
|
||||
def __init__(self, language, hearing_impaired=False, page_link=None, encoding=None, mods=None, original_format=False):
|
||||
# set subtitle language to hi if it's hearing_impaired
|
||||
if hearing_impaired:
|
||||
language = Language.rebuild(language, hi=True)
|
||||
|
@ -71,6 +73,7 @@ class Subtitle(Subtitle_):
|
|||
encoding=encoding)
|
||||
self.mods = mods
|
||||
self._is_valid = False
|
||||
self.use_original_format = original_format
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %r [%s:%s]>' % (
|
||||
|
@ -257,7 +260,7 @@ class Subtitle(Subtitle_):
|
|||
return encoding
|
||||
|
||||
def is_valid(self):
|
||||
"""Check if a :attr:`text` is a valid SubRip format.
|
||||
"""Check if a :attr:`text` is a valid SubRip format. Note that orignal format will pypass the checking
|
||||
|
||||
:return: whether or not the subtitle is valid.
|
||||
:rtype: bool
|
||||
|
@ -289,6 +292,12 @@ class Subtitle(Subtitle_):
|
|||
logger.info("Got FPS from MicroDVD subtitle: %s", subs.fps)
|
||||
else:
|
||||
logger.info("Got format: %s", subs.format)
|
||||
if self.use_original_format:
|
||||
self.format = subs.format
|
||||
self._is_valid = True
|
||||
logger.debug("Using original format")
|
||||
return True
|
||||
|
||||
except pysubs2.UnknownFPSError:
|
||||
# if parsing failed, use frame rate from provider
|
||||
sub_fps = self.get_fps()
|
||||
|
|
Loading…
Reference in a new issue