diff --git a/bazarr/app/config.py b/bazarr/app/config.py
index faee369e1..0ce861856 100644
--- a/bazarr/app/config.py
+++ b/bazarr/app/config.py
@@ -78,7 +78,8 @@ defaults = {
'wanted_search_frequency_movie': '3',
'subzero_mods': '[]',
'dont_notify_manual_actions': 'False',
- 'hi_extension': 'hi'
+ 'hi_extension': 'hi',
+ 'embedded_subtitles_parser': 'ffprobe'
},
'auth': {
'type': 'None',
diff --git a/bazarr/subtitles/refiners/ffprobe.py b/bazarr/subtitles/refiners/ffprobe.py
index 2ffcac1c6..f0e1ce0bd 100644
--- a/bazarr/subtitles/refiners/ffprobe.py
+++ b/bazarr/subtitles/refiners/ffprobe.py
@@ -32,38 +32,45 @@ def refine_from_ffprobe(path, video):
data = parse_video_metadata(file=path, file_size=file_id['file_size'],
episode_file_id=file_id['episode_file_id'])
- if not data['ffprobe']:
+ if not data['ffprobe'] or data['mediainfo']:
logging.debug("No FFprobe available in cache for this file: {}".format(path))
return video
- logging.debug('FFprobe found: %s', data['ffprobe'])
-
- if 'video' not in data['ffprobe']:
- logging.debug('BAZARR FFprobe was unable to find video tracks in the file!')
+ if data['ffprobe']:
+ logging.debug('FFprobe found: %s', data['ffprobe'])
+ parser_data = data['ffprobe']
+ elif data['mediainfo']:
+ logging.debug('Mediainfo found: %s', data['mediainfo'])
+ parser_data = data['mediainfo']
else:
- if 'resolution' in data['ffprobe']['video'][0]:
+ parser_data = {}
+
+ if 'video' not in parser_data:
+ logging.debug('BAZARR parser was unable to find video tracks in the file!')
+ else:
+ if 'resolution' in parser_data['video'][0]:
if not video.resolution:
- video.resolution = data['ffprobe']['video'][0]['resolution']
- if 'codec' in data['ffprobe']['video'][0]:
+ video.resolution = parser_data['video'][0]['resolution']
+ if 'codec' in parser_data['video'][0]:
if not video.video_codec:
- video.video_codec = data['ffprobe']['video'][0]['codec']
- if 'frame_rate' in data['ffprobe']['video'][0]:
+ video.video_codec = parser_data['video'][0]['codec']
+ if 'frame_rate' in parser_data['video'][0]:
if not video.fps:
- if isinstance(data['ffprobe']['video'][0]['frame_rate'], float):
- video.fps = data['ffprobe']['video'][0]['frame_rate']
+ if isinstance(parser_data['video'][0]['frame_rate'], float):
+ video.fps = parser_data['video'][0]['frame_rate']
else:
try:
- video.fps = data['ffprobe']['video'][0]['frame_rate'].magnitude
+ video.fps = parser_data['video'][0]['frame_rate'].magnitude
except AttributeError:
- video.fps = data['ffprobe']['video'][0]['frame_rate']
+ video.fps = parser_data['video'][0]['frame_rate']
- if 'audio' not in data['ffprobe']:
- logging.debug('BAZARR FFprobe was unable to find audio tracks in the file!')
+ if 'audio' not in parser_data:
+ logging.debug('BAZARR parser was unable to find audio tracks in the file!')
else:
- if 'codec' in data['ffprobe']['audio'][0]:
+ if 'codec' in parser_data['audio'][0]:
if not video.audio_codec:
- video.audio_codec = data['ffprobe']['audio'][0]['codec']
- for track in data['ffprobe']['audio']:
+ video.audio_codec = parser_data['audio'][0]['codec']
+ for track in parser_data['audio']:
if 'language' in track:
video.audio_languages.add(track['language'].alpha3)
diff --git a/bazarr/subtitles/tools/embedded_subs_reader.py b/bazarr/subtitles/tools/embedded_subs_reader.py
index 3a6ff50c5..99c8490f6 100644
--- a/bazarr/subtitles/tools/embedded_subs_reader.py
+++ b/bazarr/subtitles/tools/embedded_subs_reader.py
@@ -11,6 +11,7 @@ from enzyme.exceptions import MalformedMKVError
from languages.custom_lang import CustomLanguage
from app.database import TableEpisodes, TableMovies
from utilities.path_mappings import path_mappings
+from app.config import settings
def _handle_alpha3(detected_language: dict):
@@ -46,6 +47,24 @@ def embedded_subs_reader(file, file_size, episode_file_id=None, movie_file_id=No
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
+
+ # Avoid commentary subtitles
+ name = detected_language.get("name", "").lower()
+ if "commentary" in name:
+ logging.debug("Ignoring commentary subtitle: %s", name)
+ continue
+
+ language = _handle_alpha3(detected_language)
+
+ 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 data["enzyme"]:
for subtitle_track in data["enzyme"].subtitle_tracks:
hearing_impaired = (
@@ -68,6 +87,7 @@ def parse_video_metadata(file, file_size, episode_file_id=None, movie_file_id=No
# Define default data keys value
data = {
"ffprobe": {},
+ "mediainfo": {},
"enzyme": {},
"file_id": episode_file_id or movie_file_id,
"file_size": file_size,
@@ -102,12 +122,19 @@ def parse_video_metadata(file, file_size, episode_file_id=None, movie_file_id=No
# if not, we retrieve the metadata from the file
from utilities.binaries import get_binary
- ffprobe_path = get_binary("ffprobe")
+ ffprobe_path = mediainfo_path = None
+ if settings.general.embedded_subtitles_parser == 'ffprobe':
+ ffprobe_path = get_binary("ffprobe")
+ elif settings.general.embedded_subtitles_parser == 'mediainfo':
+ mediainfo_path = get_binary("mediainfo")
# if we have ffprobe available
if ffprobe_path:
data["ffprobe"] = know(video_path=file, context={"provider": "ffmpeg", "ffmpeg": ffprobe_path})
- # if not, we use enzyme for mkv files
+ # or if we have mediainfo available
+ elif mediainfo_path:
+ data["mediainfo"] = know(video_path=file, context={"provider": "mediainfo", "mediainfo": mediainfo_path})
+ # else, we use enzyme for mkv files
else:
if os.path.splitext(file)[1] == ".mkv":
with open(file, "rb") as f:
@@ -116,7 +143,7 @@ def parse_video_metadata(file, file_size, episode_file_id=None, movie_file_id=No
except MalformedMKVError:
logging.error(
"BAZARR cannot analyze this MKV with our built-in MKV parser, you should install "
- "ffmpeg/ffprobe: " + file
+ "ffmpeg/ffprobe or mediainfo: " + file
)
else:
data["enzyme"] = mkv
diff --git a/frontend/src/pages/Settings/Subtitles/index.tsx b/frontend/src/pages/Settings/Subtitles/index.tsx
index 2c71b3cdc..a1927682f 100644
--- a/frontend/src/pages/Settings/Subtitles/index.tsx
+++ b/frontend/src/pages/Settings/Subtitles/index.tsx
@@ -20,6 +20,7 @@ import {
adaptiveSearchingDeltaOption,
antiCaptchaOption,
colorOptions,
+ embeddedSubtitlesParserOption,
folderOptions,
hiExtensionOptions,
} from "./options";
@@ -278,6 +279,14 @@ const SettingsSubtitlesView: FunctionComponent = () => {
Hide embedded subtitles for languages that are not currently
desired.
+ (v === undefined ? "ffprobe" : v),
+ }}
+ options={embeddedSubtitlesParserOption}
+ >
+ Embedded subtitles video parser
diff --git a/frontend/src/pages/Settings/Subtitles/options.ts b/frontend/src/pages/Settings/Subtitles/options.ts
index 5549a4128..62c4f60b2 100644
--- a/frontend/src/pages/Settings/Subtitles/options.ts
+++ b/frontend/src/pages/Settings/Subtitles/options.ts
@@ -41,6 +41,18 @@ export const antiCaptchaOption: SelectorOption[] = [
},
];
+export const embeddedSubtitlesParserOption: SelectorOption[] = [
+ {
+ label: "ffprobe (faster)",
+ value: "ffprobe",
+ },
+ {
+ label:
+ "mediainfo (slower but may give better results. Must be already installed)",
+ value: "mediainfo",
+ },
+];
+
export const adaptiveSearchingDelayOption: SelectorOption[] = [
{
label: "1 week",