2020-06-10 16:04:54 +00:00
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
from ffsubsync.ffsubsync import run
|
|
|
|
from ffsubsync.constants import *
|
|
|
|
from knowit import api
|
|
|
|
from utils import get_binary
|
2020-06-12 19:08:44 +00:00
|
|
|
from utils import history_log, history_log_movie
|
|
|
|
from get_languages import alpha2_from_alpha3, language_from_alpha3
|
|
|
|
from helper import path_mappings
|
2020-06-10 16:04:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
class SubSyncer:
|
|
|
|
def __init__(self):
|
|
|
|
self.reference = None
|
|
|
|
self.srtin = None
|
|
|
|
self.reference_stream = None
|
|
|
|
self.overwrite_input = True
|
|
|
|
self.ffmpeg_path = None
|
|
|
|
|
|
|
|
# unused attributes
|
|
|
|
self.encoding = DEFAULT_ENCODING
|
|
|
|
self.vlc_mode = None
|
|
|
|
self.make_test_case = None
|
|
|
|
self.gui_mode = None
|
|
|
|
self.srtout = None
|
|
|
|
self.vad = 'subs_then_auditok'
|
|
|
|
self.reference_encoding = None
|
|
|
|
self.frame_rate = DEFAULT_FRAME_RATE
|
|
|
|
self.start_seconds = DEFAULT_START_SECONDS
|
|
|
|
self.no_fix_framerate = None
|
|
|
|
self.serialize_speech = None
|
|
|
|
self.max_offset_seconds = DEFAULT_MAX_OFFSET_SECONDS
|
|
|
|
self.merge_with_reference = None
|
|
|
|
self.output_encoding = 'same'
|
|
|
|
|
2020-06-12 19:08:44 +00:00
|
|
|
def sync(self, video_path, srt_path, srt_lang, media_type, sonarr_series_id=None, sonarr_episode_id=None,
|
|
|
|
radarr_id=None):
|
2020-06-10 16:04:54 +00:00
|
|
|
self.reference = video_path
|
|
|
|
self.srtin = srt_path
|
|
|
|
self.srtout = None
|
|
|
|
|
|
|
|
ffprobe_exe = get_binary('ffprobe')
|
|
|
|
if not ffprobe_exe:
|
|
|
|
logging.debug('BAZARR FFprobe not found!')
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
logging.debug('BAZARR FFprobe used is %s', ffprobe_exe)
|
|
|
|
|
|
|
|
api.initialize({'provider': 'ffmpeg', 'ffmpeg': ffprobe_exe})
|
|
|
|
data = api.know(self.reference)
|
|
|
|
|
2020-06-16 02:40:08 +00:00
|
|
|
using_what = None
|
2020-08-03 18:00:41 +00:00
|
|
|
first_embedded_subs = None
|
2020-06-16 02:40:08 +00:00
|
|
|
|
2020-06-10 16:04:54 +00:00
|
|
|
if 'subtitle' in data:
|
|
|
|
for i, embedded_subs in enumerate(data['subtitle']):
|
2020-08-03 18:00:41 +00:00
|
|
|
if i == 0:
|
|
|
|
first_embedded_subs = embedded_subs
|
2020-06-10 16:04:54 +00:00
|
|
|
if 'language' in embedded_subs:
|
|
|
|
language = embedded_subs['language'].alpha3
|
2020-08-03 18:00:41 +00:00
|
|
|
forced = False
|
|
|
|
if 'forced' in embedded_subs:
|
|
|
|
if embedded_subs['forced']:
|
|
|
|
forced = True
|
|
|
|
str_format = embedded_subs['format'].lower()
|
|
|
|
if forced or str_format in ['pgs', 'vobsub']:
|
|
|
|
pass
|
2020-06-10 16:04:54 +00:00
|
|
|
if language == "eng":
|
2020-06-16 02:40:08 +00:00
|
|
|
using_what = "English embedded subtitle track"
|
2020-06-10 16:04:54 +00:00
|
|
|
self.reference_stream = "s:{}".format(i)
|
|
|
|
break
|
|
|
|
if not self.reference_stream:
|
2020-08-03 18:00:41 +00:00
|
|
|
language = None
|
|
|
|
if 'language' in first_embedded_subs:
|
|
|
|
language = language_from_alpha3(first_embedded_subs['language'].alpha3)
|
|
|
|
forced = False
|
|
|
|
if 'forced' in first_embedded_subs:
|
|
|
|
if first_embedded_subs['forced']:
|
|
|
|
forced = True
|
|
|
|
str_format = first_embedded_subs['format'].lower()
|
|
|
|
if forced or str_format in ['pgs', 'vobsub']:
|
|
|
|
pass
|
|
|
|
|
|
|
|
using_what = "{0} embedded subtitle track".format(language or
|
|
|
|
'unknown language embedded subtitles track')
|
2020-06-10 16:04:54 +00:00
|
|
|
self.reference_stream = "s:0"
|
|
|
|
elif 'audio' in data:
|
|
|
|
audio_tracks = data['audio']
|
|
|
|
for i, audio_track in enumerate(audio_tracks):
|
|
|
|
if 'language' in audio_track:
|
|
|
|
language = audio_track['language'].alpha3
|
|
|
|
if language == srt_lang:
|
2020-07-28 11:17:21 +00:00
|
|
|
using_what = "{0} audio track".format(language_from_alpha3(audio_track['language'].alpha3) or
|
|
|
|
'unknown language audio track')
|
2020-06-10 16:04:54 +00:00
|
|
|
self.reference_stream = "a:{}".format(i)
|
|
|
|
break
|
|
|
|
if not self.reference_stream:
|
|
|
|
audio_tracks = data['audio']
|
|
|
|
for i, audio_track in enumerate(audio_tracks):
|
|
|
|
if 'language' in audio_track:
|
|
|
|
language = audio_track['language'].alpha3
|
|
|
|
if language == "eng":
|
2020-06-16 02:40:08 +00:00
|
|
|
using_what = "English audio track"
|
2020-06-10 16:04:54 +00:00
|
|
|
self.reference_stream = "a:{}".format(i)
|
|
|
|
break
|
|
|
|
if not self.reference_stream:
|
2020-06-16 02:40:08 +00:00
|
|
|
using_what = "first audio track"
|
2020-06-10 16:04:54 +00:00
|
|
|
self.reference_stream = "a:0"
|
|
|
|
else:
|
|
|
|
raise NoAudioTrack
|
|
|
|
|
|
|
|
ffmpeg_exe = get_binary('ffmpeg')
|
2020-06-10 19:47:44 +00:00
|
|
|
if not ffmpeg_exe:
|
2020-06-10 16:04:54 +00:00
|
|
|
logging.debug('BAZARR FFmpeg not found!')
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
logging.debug('BAZARR FFmpeg used is %s', ffmpeg_exe)
|
|
|
|
|
|
|
|
self.ffmpeg_path = os.path.dirname(ffmpeg_exe)
|
2020-07-27 11:31:15 +00:00
|
|
|
try:
|
|
|
|
result = run(self)
|
|
|
|
except Exception as e:
|
|
|
|
logging.error('BAZARR an exception occurs during the synchronization process for this subtitles: ' +
|
|
|
|
self.srtin)
|
2020-06-12 19:08:44 +00:00
|
|
|
else:
|
2020-07-27 11:31:15 +00:00
|
|
|
if result['sync_was_successful']:
|
|
|
|
message = "{0} subtitles synchronization ended with an offset of {1} seconds and a framerate scale " \
|
|
|
|
"factor of {2} using {3} (0:{4}).".format(language_from_alpha3(srt_lang),
|
|
|
|
result['offset_seconds'],
|
|
|
|
result['framerate_scale_factor'],
|
|
|
|
using_what,
|
|
|
|
self.reference_stream)
|
|
|
|
|
|
|
|
if media_type == 'series':
|
|
|
|
history_log(action=5, sonarr_series_id=sonarr_series_id, sonarr_episode_id=sonarr_episode_id,
|
|
|
|
description=message, video_path=path_mappings.path_replace_reverse(self.reference),
|
|
|
|
language=alpha2_from_alpha3(srt_lang), subtitles_path=srt_path)
|
|
|
|
else:
|
|
|
|
history_log_movie(action=5, radarr_id=radarr_id, description=message,
|
|
|
|
video_path=path_mappings.path_replace_reverse_movie(self.reference),
|
|
|
|
language=alpha2_from_alpha3(srt_lang), subtitles_path=srt_path)
|
|
|
|
else:
|
2020-07-28 11:17:21 +00:00
|
|
|
logging.error('BAZARR unable to sync subtitles using {0}({1}): {2}'.format(using_what,
|
|
|
|
self.reference_stream,
|
|
|
|
self.srtin))
|
2020-06-12 19:08:44 +00:00
|
|
|
|
2020-07-27 11:31:15 +00:00
|
|
|
return result
|
2020-06-12 19:08:44 +00:00
|
|
|
|
2020-06-10 16:04:54 +00:00
|
|
|
|
|
|
|
class NoAudioTrack(Exception):
|
|
|
|
"""Exception raised if no audio track can be found in video file."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
subsync = SubSyncer()
|