diff --git a/bazarr/api/episodes/blacklist.py b/bazarr/api/episodes/blacklist.py index e62a7850a..7bcab005b 100644 --- a/bazarr/api/episodes/blacklist.py +++ b/bazarr/api/episodes/blacklist.py @@ -88,6 +88,7 @@ class EpisodesBlacklist(Resource): @api_ns_episodes_blacklist.response(200, 'Success') @api_ns_episodes_blacklist.response(401, 'Not Authenticated') @api_ns_episodes_blacklist.response(404, 'Episode not found') + @api_ns_episodes_blacklist.response(410, 'Subtitles file not found or permission issue.') def post(self): """Add an episodes subtitles to blacklist""" args = self.post_request_parser.parse_args() @@ -113,17 +114,19 @@ class EpisodesBlacklist(Resource): provider=provider, subs_id=subs_id, language=language) - delete_subtitles(media_type='series', - language=language, - forced=False, - hi=False, - media_path=path_mappings.path_replace(media_path), - subtitles_path=subtitles_path, - sonarr_series_id=sonarr_series_id, - sonarr_episode_id=sonarr_episode_id) - episode_download_subtitles(sonarr_episode_id) - event_stream(type='episode-history') - return '', 200 + if delete_subtitles(media_type='series', + language=language, + forced=False, + hi=False, + media_path=path_mappings.path_replace(media_path), + subtitles_path=subtitles_path, + sonarr_series_id=sonarr_series_id, + sonarr_episode_id=sonarr_episode_id): + episode_download_subtitles(sonarr_episode_id) + event_stream(type='episode-history') + return '', 200 + else: + return 'Subtitles file not found or permission issue.', 410 delete_request_parser = reqparse.RequestParser() delete_request_parser.add_argument('all', type=str, required=False, help='Empty episodes subtitles blacklist') diff --git a/bazarr/api/episodes/episodes_subtitles.py b/bazarr/api/episodes/episodes_subtitles.py index b1e786031..67f1add7b 100644 --- a/bazarr/api/episodes/episodes_subtitles.py +++ b/bazarr/api/episodes/episodes_subtitles.py @@ -37,6 +37,8 @@ class EpisodesSubtitles(Resource): @api_ns_episodes_subtitles.response(204, 'Success') @api_ns_episodes_subtitles.response(401, 'Not Authenticated') @api_ns_episodes_subtitles.response(404, 'Episode not found') + @api_ns_episodes_subtitles.response(409, 'Unable to save subtitles file. Permission of path mapping issue?') + @api_ns_episodes_subtitles.response(410, 'Episode file not found. Path mapping issue?') def patch(self): """Download an episode subtitles""" args = self.patch_request_parser.parse_args() @@ -55,10 +57,15 @@ class EpisodesSubtitles(Resource): if not episodeInfo: return 'Episode not found', 404 - title = episodeInfo.title episodePath = path_mappings.path_replace(episodeInfo.path) + + if not os.path.exists(episodePath): + return 'Episode file not found. Path mapping issue?', 410 + sceneName = episodeInfo.sceneName or "None" + title = episodeInfo.title + language = args.get('language') hi = args.get('hi').capitalize() forced = args.get('forced').capitalize() @@ -79,11 +86,10 @@ class EpisodesSubtitles(Resource): store_subtitles(result.path, episodePath) else: event_stream(type='episode', payload=sonarrEpisodeId) - except OSError: - pass - - return '', 204 + return 'Unable to save subtitles file. Permission of path mapping issue?', 409 + else: + return '', 204 post_request_parser = reqparse.RequestParser() post_request_parser.add_argument('seriesid', type=int, required=True, help='Series ID') @@ -99,6 +105,8 @@ class EpisodesSubtitles(Resource): @api_ns_episodes_subtitles.response(204, 'Success') @api_ns_episodes_subtitles.response(401, 'Not Authenticated') @api_ns_episodes_subtitles.response(404, 'Episode not found') + @api_ns_episodes_subtitles.response(409, 'Unable to save subtitles file. Permission of path mapping issue?') + @api_ns_episodes_subtitles.response(410, 'Episode file not found. Path mapping issue?') def post(self): """Upload an episode subtitles""" args = self.post_request_parser.parse_args() @@ -115,6 +123,9 @@ class EpisodesSubtitles(Resource): episodePath = path_mappings.path_replace(episodeInfo.path) + if not os.path.exists(episodePath): + return 'Episode file not found. Path mapping issue?', 410 + audio_language = get_audio_profile_languages(episodeInfo.audio_language) if len(audio_language) and isinstance(audio_language[0], dict): audio_language = audio_language[0] @@ -149,11 +160,10 @@ class EpisodesSubtitles(Resource): if not settings.general.getboolean('dont_notify_manual_actions'): send_notifications(sonarrSeriesId, sonarrEpisodeId, result.message) store_subtitles(result.path, episodePath) - except OSError: - pass - - return '', 204 + return 'Unable to save subtitles file. Permission of path mapping issue?', 409 + else: + return '', 204 delete_request_parser = reqparse.RequestParser() delete_request_parser.add_argument('seriesid', type=int, required=True, help='Series ID') @@ -168,6 +178,7 @@ class EpisodesSubtitles(Resource): @api_ns_episodes_subtitles.response(204, 'Success') @api_ns_episodes_subtitles.response(401, 'Not Authenticated') @api_ns_episodes_subtitles.response(404, 'Episode not found') + @api_ns_episodes_subtitles.response(410, 'Subtitles file not found or permission issue.') def delete(self): """Delete an episode subtitles""" args = self.delete_request_parser.parse_args() @@ -190,13 +201,14 @@ class EpisodesSubtitles(Resource): subtitlesPath = path_mappings.path_replace_reverse(subtitlesPath) - delete_subtitles(media_type='series', - language=language, - forced=forced, - hi=hi, - media_path=episodePath, - subtitles_path=subtitlesPath, - sonarr_series_id=sonarrSeriesId, - sonarr_episode_id=sonarrEpisodeId) - - return '', 204 + if delete_subtitles(media_type='series', + language=language, + forced=forced, + hi=hi, + media_path=episodePath, + subtitles_path=subtitlesPath, + sonarr_series_id=sonarrSeriesId, + sonarr_episode_id=sonarrEpisodeId): + return '', 204 + else: + return 'Subtitles file not found or permission issue.', 410 diff --git a/bazarr/api/movies/blacklist.py b/bazarr/api/movies/blacklist.py index 118d4e9cb..22bb09ce9 100644 --- a/bazarr/api/movies/blacklist.py +++ b/bazarr/api/movies/blacklist.py @@ -81,6 +81,7 @@ class MoviesBlacklist(Resource): @api_ns_movies_blacklist.response(200, 'Success') @api_ns_movies_blacklist.response(401, 'Not Authenticated') @api_ns_movies_blacklist.response(404, 'Movie not found') + @api_ns_movies_blacklist.response(410, 'Subtitles file not found or permission issue.') def post(self): """Add a movies subtitles to blacklist""" args = self.post_request_parser.parse_args() @@ -107,16 +108,18 @@ class MoviesBlacklist(Resource): provider=provider, subs_id=subs_id, language=language) - delete_subtitles(media_type='movie', - language=language, - forced=forced, - hi=hi, - media_path=path_mappings.path_replace_movie(media_path), - subtitles_path=subtitles_path, - radarr_id=radarr_id) - movies_download_subtitles(radarr_id) - event_stream(type='movie-history') - return '', 200 + if delete_subtitles(media_type='movie', + language=language, + forced=forced, + hi=hi, + media_path=path_mappings.path_replace_movie(media_path), + subtitles_path=subtitles_path, + radarr_id=radarr_id): + movies_download_subtitles(radarr_id) + event_stream(type='movie-history') + return '', 200 + else: + return 'Subtitles file not found or permission issue.', 410 delete_request_parser = reqparse.RequestParser() delete_request_parser.add_argument('all', type=str, required=False, help='Empty movies subtitles blacklist') diff --git a/bazarr/api/movies/movies.py b/bazarr/api/movies/movies.py index f2303f4cf..ec181b2f8 100644 --- a/bazarr/api/movies/movies.py +++ b/bazarr/api/movies/movies.py @@ -166,6 +166,7 @@ class Movies(Resource): @api_ns_movies.response(204, 'Success') @api_ns_movies.response(400, 'Unknown action') @api_ns_movies.response(401, 'Not Authenticated') + @api_ns_movies.response(410, 'Movie file not found. Path mapping issue?') def patch(self): """Run actions on specific movies""" args = self.patch_request_parser.parse_args() @@ -175,8 +176,12 @@ class Movies(Resource): movies_scan_subtitles(radarrid) return '', 204 elif action == "search-missing": - movies_download_subtitles(radarrid) - return '', 204 + try: + movies_download_subtitles(radarrid) + except OSError: + return 'Movie file not found. Path mapping issue?', 410 + else: + return '', 204 elif action == "search-wanted": wanted_search_missing_subtitles_movies() return '', 204 diff --git a/bazarr/api/movies/movies_subtitles.py b/bazarr/api/movies/movies_subtitles.py index fd4dd953f..10584caf7 100644 --- a/bazarr/api/movies/movies_subtitles.py +++ b/bazarr/api/movies/movies_subtitles.py @@ -1,6 +1,5 @@ # coding=utf-8 -import contextlib import os import logging @@ -37,6 +36,8 @@ class MoviesSubtitles(Resource): @api_ns_movies_subtitles.response(204, 'Success') @api_ns_movies_subtitles.response(401, 'Not Authenticated') @api_ns_movies_subtitles.response(404, 'Movie not found') + @api_ns_movies_subtitles.response(409, 'Unable to save subtitles file. Permission of path mapping issue?') + @api_ns_movies_subtitles.response(410, 'Movie file not found. Path mapping issue?') def patch(self): """Download a movie subtitles""" args = self.patch_request_parser.parse_args() @@ -55,6 +56,10 @@ class MoviesSubtitles(Resource): return 'Movie not found', 404 moviePath = path_mappings.path_replace_movie(movieInfo.path) + + if not os.path.exists(moviePath): + return 'Movie file not found. Path mapping issue?', 410 + sceneName = movieInfo.sceneName or 'None' title = movieInfo.title @@ -69,7 +74,7 @@ class MoviesSubtitles(Resource): else: audio_language = None - with contextlib.suppress(OSError): + try: result = list(generate_subtitles(moviePath, [(language, hi, forced)], audio_language, sceneName, title, 'movie', profile_id=get_profile_id(movie_id=radarrId))) if result: @@ -78,7 +83,10 @@ class MoviesSubtitles(Resource): store_subtitles_movie(result.path, moviePath) else: event_stream(type='movie', payload=radarrId) - return '', 204 + except OSError: + return 'Unable to save subtitles file. Permission of path mapping issue?', 409 + else: + return '', 204 # POST: Upload Subtitles post_request_parser = reqparse.RequestParser() @@ -94,6 +102,8 @@ class MoviesSubtitles(Resource): @api_ns_movies_subtitles.response(204, 'Success') @api_ns_movies_subtitles.response(401, 'Not Authenticated') @api_ns_movies_subtitles.response(404, 'Movie not found') + @api_ns_movies_subtitles.response(409, 'Unable to save subtitles file. Permission of path mapping issue?') + @api_ns_movies_subtitles.response(410, 'Movie file not found. Path mapping issue?') def post(self): """Upload a movie subtitles""" # TODO: Support Multiply Upload @@ -109,6 +119,9 @@ class MoviesSubtitles(Resource): moviePath = path_mappings.path_replace_movie(movieInfo.path) + if not os.path.exists(moviePath): + return 'Movie file not found. Path mapping issue?', 410 + audio_language = get_audio_profile_languages(movieInfo.audio_language) if len(audio_language) and isinstance(audio_language[0], dict): audio_language = audio_language[0] @@ -125,7 +138,7 @@ class MoviesSubtitles(Resource): if not isinstance(ext, str) or ext.lower() not in SUBTITLE_EXTENSIONS: raise ValueError('A subtitle of an invalid format was uploaded.') - with contextlib.suppress(OSError): + try: result = manual_upload_subtitle(path=moviePath, language=language, forced=forced, @@ -143,7 +156,10 @@ class MoviesSubtitles(Resource): if not settings.general.getboolean('dont_notify_manual_actions'): send_notifications_movie(radarrId, result.message) store_subtitles_movie(result.path, moviePath) - return '', 204 + except OSError: + return 'Unable to save subtitles file. Permission of path mapping issue?', 409 + else: + return '', 204 # DELETE: Delete Subtitles delete_request_parser = reqparse.RequestParser() @@ -158,6 +174,7 @@ class MoviesSubtitles(Resource): @api_ns_movies_subtitles.response(204, 'Success') @api_ns_movies_subtitles.response(401, 'Not Authenticated') @api_ns_movies_subtitles.response(404, 'Movie not found') + @api_ns_movies_subtitles.response(410, 'Subtitles file not found or permission issue.') def delete(self): """Delete a movie subtitles""" args = self.delete_request_parser.parse_args() @@ -179,12 +196,13 @@ class MoviesSubtitles(Resource): subtitlesPath = path_mappings.path_replace_reverse_movie(subtitlesPath) - delete_subtitles(media_type='movie', - language=language, - forced=forced, - hi=hi, - media_path=moviePath, - subtitles_path=subtitlesPath, - radarr_id=radarrId) - - return '', 204 + if delete_subtitles(media_type='movie', + language=language, + forced=forced, + hi=hi, + media_path=moviePath, + subtitles_path=subtitlesPath, + radarr_id=radarrId): + return '', 204 + else: + return 'Subtitles file not found or permission issue.', 410 diff --git a/bazarr/api/providers/providers_episodes.py b/bazarr/api/providers/providers_episodes.py index f8fa516b8..8b9c72228 100644 --- a/bazarr/api/providers/providers_episodes.py +++ b/bazarr/api/providers/providers_episodes.py @@ -1,5 +1,7 @@ # coding=utf-8 +import os + from flask_restx import Resource, Namespace, reqparse, fields from app.database import TableEpisodes, TableShows, get_audio_profile_languages, get_profile_id, database, select @@ -42,6 +44,7 @@ class ProviderEpisodes(Resource): @api_ns_providers_episodes.marshal_with(get_response_model, envelope='data', code=200) @api_ns_providers_episodes.response(401, 'Not Authenticated') @api_ns_providers_episodes.response(404, 'Episode not found') + @api_ns_providers_episodes.response(410, 'Episode file not found. Path mapping issue?') @api_ns_providers_episodes.doc(parser=get_request_parser) def get(self): """Search manually for an episode subtitles""" @@ -62,6 +65,10 @@ class ProviderEpisodes(Resource): title = episodeInfo.title episodePath = path_mappings.path_replace(episodeInfo.path) + + if not os.path.exists(episodePath): + return 'Episode file not found. Path mapping issue?', 410 + sceneName = episodeInfo.sceneName or "None" profileId = episodeInfo.profileId diff --git a/bazarr/api/providers/providers_movies.py b/bazarr/api/providers/providers_movies.py index fcc8241e8..07df28785 100644 --- a/bazarr/api/providers/providers_movies.py +++ b/bazarr/api/providers/providers_movies.py @@ -1,5 +1,7 @@ # coding=utf-8 +import os + from flask_restx import Resource, Namespace, reqparse, fields from app.database import TableMovies, get_audio_profile_languages, get_profile_id, database, select @@ -43,6 +45,7 @@ class ProviderMovies(Resource): @api_ns_providers_movies.marshal_with(get_response_model, envelope='data', code=200) @api_ns_providers_movies.response(401, 'Not Authenticated') @api_ns_providers_movies.response(404, 'Movie not found') + @api_ns_providers_movies.response(410, 'Movie file not found. Path mapping issue?') @api_ns_providers_movies.doc(parser=get_request_parser) def get(self): """Search manually for a movie subtitles""" @@ -61,6 +64,10 @@ class ProviderMovies(Resource): title = movieInfo.title moviePath = path_mappings.path_replace_movie(movieInfo.path) + + if not os.path.exists(moviePath): + return 'Movie file not found. Path mapping issue?', 410 + sceneName = movieInfo.sceneName or "None" profileId = movieInfo.profileId diff --git a/bazarr/api/series/series.py b/bazarr/api/series/series.py index 6a90f6190..0d6d1e8de 100644 --- a/bazarr/api/series/series.py +++ b/bazarr/api/series/series.py @@ -199,6 +199,7 @@ class Series(Resource): @api_ns_series.response(204, 'Success') @api_ns_series.response(400, 'Unknown action') @api_ns_series.response(401, 'Not Authenticated') + @api_ns_series.response(410, 'Series directory not found. Path mapping issue?') def patch(self): """Run actions on specific series""" args = self.patch_request_parser.parse_args() @@ -208,8 +209,12 @@ class Series(Resource): series_scan_subtitles(seriesid) return '', 204 elif action == "search-missing": - series_download_subtitles(seriesid) - return '', 204 + try: + series_download_subtitles(seriesid) + except OSError: + return 'Series directory not found. Path mapping issue?', 410 + else: + return '', 204 elif action == "search-wanted": wanted_search_missing_subtitles_series() return '', 204 diff --git a/bazarr/api/subtitles/subtitles.py b/bazarr/api/subtitles/subtitles.py index f71081220..bf655099a 100644 --- a/bazarr/api/subtitles/subtitles.py +++ b/bazarr/api/subtitles/subtitles.py @@ -42,6 +42,8 @@ class Subtitles(Resource): @api_ns_subtitles.response(204, 'Success') @api_ns_subtitles.response(401, 'Not Authenticated') @api_ns_subtitles.response(404, 'Episode/movie not found') + @api_ns_subtitles.response(409, 'Unable to edit subtitles file. Check logs.') + @api_ns_subtitles.response(410, 'Subtitles file not found. Path mapping issue?') def patch(self): """Apply mods/tools on external subtitles""" args = self.patch_request_parser.parse_args() @@ -52,6 +54,9 @@ class Subtitles(Resource): media_type = args.get('type') id = args.get('id') + if not os.path.exists(subtitles_path): + return 'Subtitles file not found. Path mapping issue?', 410 + if media_type == 'episode': metadata = database.execute( select(TableEpisodes.path, TableEpisodes.sonarrSeriesId) @@ -80,8 +85,11 @@ class Subtitles(Resource): srt_lang=language, media_type='series', sonarr_series_id=metadata.sonarrSeriesId, sonarr_episode_id=id) else: - subsync.sync(video_path=video_path, srt_path=subtitles_path, - srt_lang=language, media_type='movies', radarr_id=id) + try: + subsync.sync(video_path=video_path, srt_path=subtitles_path, + srt_lang=language, media_type='movies', radarr_id=id) + except OSError: + return 'Unable to edit subtitles file. Check logs.', 409 del subsync gc.collect() elif action == 'translate': @@ -89,16 +97,22 @@ class Subtitles(Resource): dest_language = language forced = True if args.get('forced') == 'true' else False hi = True if args.get('hi') == 'true' else False - translate_subtitles_file(video_path=video_path, source_srt_file=subtitles_path, - from_lang=from_language, to_lang=dest_language, forced=forced, hi=hi, - media_type="series" if media_type == "episode" else "movies", - sonarr_series_id=metadata.sonarrSeriesId if media_type == "episode" else None, - sonarr_episode_id=id, - radarr_id=id) + try: + translate_subtitles_file(video_path=video_path, source_srt_file=subtitles_path, + from_lang=from_language, to_lang=dest_language, forced=forced, hi=hi, + media_type="series" if media_type == "episode" else "movies", + sonarr_series_id=metadata.sonarrSeriesId if media_type == "episode" else None, + sonarr_episode_id=id, + radarr_id=id) + except OSError: + return 'Unable to edit subtitles file. Check logs.', 409 else: use_original_format = True if args.get('original_format') == 'true' else False - subtitles_apply_mods(language=language, subtitle_path=subtitles_path, mods=[action], - use_original_format=use_original_format, video_path=video_path) + try: + subtitles_apply_mods(language=language, subtitle_path=subtitles_path, mods=[action], + use_original_format=use_original_format, video_path=video_path) + except OSError: + return 'Unable to edit subtitles file. Check logs.', 409 # apply chmod if required chmod = int(settings.general.chmod, 8) if not sys.platform.startswith( diff --git a/bazarr/api/system/settings.py b/bazarr/api/system/settings.py index 2e9eb7a24..bad7e9dc8 100644 --- a/bazarr/api/system/settings.py +++ b/bazarr/api/system/settings.py @@ -108,7 +108,7 @@ class SystemSettings(Resource): item = json.loads(item) database.execute( update(TableSettingsNotifier).values( - enabled=int(item['enabled'] == True), + enabled=int(item['enabled'] is True), url=item['url']) .where(TableSettingsNotifier.name == item['name'])) diff --git a/bazarr/app/database.py b/bazarr/app/database.py index 645276ea5..b33bc0a40 100644 --- a/bazarr/app/database.py +++ b/bazarr/app/database.py @@ -12,7 +12,7 @@ from datetime import datetime from sqlalchemy import create_engine, inspect, DateTime, ForeignKey, Integer, LargeBinary, Text, func, text # importing here to be indirectly imported in other modules later from sqlalchemy import update, delete, select, func # noqa W0611 -from sqlalchemy.orm import scoped_session, sessionmaker, relationship, mapped_column +from sqlalchemy.orm import scoped_session, sessionmaker, mapped_column from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.pool import NullPool diff --git a/bazarr/subtitles/mass_download/movies.py b/bazarr/subtitles/mass_download/movies.py index 297f03078..ed8fec2c1 100644 --- a/bazarr/subtitles/mass_download/movies.py +++ b/bazarr/subtitles/mass_download/movies.py @@ -4,6 +4,7 @@ import ast import logging import operator +import os from functools import reduce @@ -36,6 +37,11 @@ def movies_download_subtitles(no): logging.debug("BAZARR no movie with that radarrId can be found in database:", str(no)) return + moviePath = path_mappings.path_replace_movie(movie.path) + + if not os.path.exists(moviePath): + raise OSError + if ast.literal_eval(movie.missing_subtitles): count_movie = len(ast.literal_eval(movie.missing_subtitles)) else: @@ -67,7 +73,7 @@ def movies_download_subtitles(no): value=0, count=count_movie) - for result in generate_subtitles(path_mappings.path_replace_movie(movie.path), + for result in generate_subtitles(moviePath, languages, audio_language, str(movie.sceneName), @@ -76,7 +82,7 @@ def movies_download_subtitles(no): check_if_still_required=True): if result: - store_subtitles_movie(movie.path, path_mappings.path_replace_movie(movie.path)) + store_subtitles_movie(movie.path, moviePath) history_log_movie(1, no, result) send_notifications_movie(no, result.message) diff --git a/bazarr/subtitles/mass_download/series.py b/bazarr/subtitles/mass_download/series.py index 3b4d8e58d..4a9dda021 100644 --- a/bazarr/subtitles/mass_download/series.py +++ b/bazarr/subtitles/mass_download/series.py @@ -4,6 +4,7 @@ import ast import logging import operator +import os from functools import reduce @@ -19,6 +20,14 @@ from ..download import generate_subtitles def series_download_subtitles(no): + series_row = database.execute( + select(TableShows.path) + .where(TableShows.sonarrSeriesId == no))\ + .first() + + if series_row and not os.path.exists(path_mappings.path_replace(series_row.path)): + raise OSError + conditions = [(TableEpisodes.sonarrSeriesId == no), (TableEpisodes.missing_subtitles != '[]')] conditions += get_exclusion_clause('series') diff --git a/bazarr/subtitles/tools/score.py b/bazarr/subtitles/tools/score.py index c35347bb8..11771354e 100644 --- a/bazarr/subtitles/tools/score.py +++ b/bazarr/subtitles/tools/score.py @@ -8,6 +8,7 @@ from app.config import get_settings logger = logging.getLogger(__name__) + class Score: media = None defaults = {} diff --git a/bazarr/subtitles/tools/subsyncer.py b/bazarr/subtitles/tools/subsyncer.py index 5667622ac..8e815fa25 100644 --- a/bazarr/subtitles/tools/subsyncer.py +++ b/bazarr/subtitles/tools/subsyncer.py @@ -52,24 +52,25 @@ class SubSyncer: logging.debug('BAZARR FFmpeg used is %s', ffmpeg_exe) self.ffmpeg_path = os.path.dirname(ffmpeg_exe) + unparsed_args = [self.reference, '-i', self.srtin, '-o', self.srtout, '--ffmpegpath', self.ffmpeg_path, '--vad', + self.vad, '--log-dir-path', self.log_dir_path] + if settings.subsync.getboolean('force_audio'): + unparsed_args.append('--no-fix-framerate') + unparsed_args.append('--reference-stream') + unparsed_args.append('a:0') + if settings.subsync.getboolean('debug'): + unparsed_args.append('--make-test-case') + parser = make_parser() + self.args = parser.parse_args(args=unparsed_args) + if os.path.isfile(self.srtout): + os.remove(self.srtout) + logging.debug('BAZARR deleted the previous subtitles synchronization attempt file.') try: - unparsed_args = [self.reference, '-i', self.srtin, '-o', self.srtout, '--ffmpegpath', self.ffmpeg_path, - '--vad', self.vad, '--log-dir-path', self.log_dir_path] - if settings.subsync.getboolean('force_audio'): - unparsed_args.append('--no-fix-framerate') - unparsed_args.append('--reference-stream') - unparsed_args.append('a:0') - if settings.subsync.getboolean('debug'): - unparsed_args.append('--make-test-case') - parser = make_parser() - self.args = parser.parse_args(args=unparsed_args) - if os.path.isfile(self.srtout): - os.remove(self.srtout) - logging.debug('BAZARR deleted the previous subtitles synchronization attempt file.') result = run(self.args) except Exception: logging.exception('BAZARR an exception occurs during the synchronization process for this subtitles: ' '{0}'.format(self.srtin)) + raise OSError else: if settings.subsync.getboolean('debug'): return result diff --git a/bazarr/subtitles/tools/translate.py b/bazarr/subtitles/tools/translate.py index 8d870ff3f..1761ac50a 100644 --- a/bazarr/subtitles/tools/translate.py +++ b/bazarr/subtitles/tools/translate.py @@ -81,7 +81,11 @@ def translate_subtitles_file(video_path, source_srt_file, from_lang, to_lang, fo except IndexError: logging.error(f'BAZARR is unable to translate malformed subtitles: {source_srt_file}') return False - subs.save(dest_srt_file) + try: + subs.save(dest_srt_file) + except OSError: + logging.error(f'BAZARR is unable to save translated subtitles to {dest_srt_file}') + raise OSError message = f"{language_from_alpha2(from_lang)} subtitles translated to {language_from_alpha3(to_lang)}."