def play_video(filepath): size = os.path.getsize(filepath) # 150MB is our lower limit for checking subtitles if size > 157286400: download_subtitles(filepath) if os.path.exists(get_subtitle_path(filepath)): sub = get_subtitle_path(filepath) run_in_bg(['omxplayer', '-b', '--subtitles', sub, filepath]) else: run_in_bg(['omxplayer', '-b', filepath])
def get_subtitle(magnet, lang): print("Explorando torrent") lt_session = session() lt_session.listen_on(6881, 6891) params = {"save_path": "/tmp"} handle = add_magnet_uri(lt_session, magnet, params) lt_session.start_dht() print "esperando" while (not handle.has_metadata()): sleep(.1) print "esperando" info = handle.get_torrent_info() print "esperando", info files = info.files() biggest_file = ("", 0) for file_ in files: if file_.size > biggest_file[1]: biggest_file = [file_.path, file_.size] print("Adivinando data") filepath = biggest_file[0] guess = guess_video_info(filepath, info = ['filename']) video = Video.fromguess(filepath, guess) video.size = biggest_file[1] print("Bajando el subtitulo para lang = " + lang) subtitle = download_best_subtitles([video], {Language(lang)}, single=True) if not len(subtitle): subtitle = None else: subtitle = get_subtitle_path(video.name) lt_session.remove_torrent(handle) return subtitle
def get_subtitle(magnet, lang): print("Obtaining subtitle (experimental, might take a while)") lt_session = session() params = {"save_path": "/tmp"} handle = add_magnet_uri(lt_session, magnet, params) while (not handle.has_metadata()): sleep(.1) info = handle.get_torrent_info() files = info.files() biggest_file = ("", 0) for file_ in files: if file_.size > biggest_file[1]: biggest_file = [file_.path, file_.size] print("Guessing data") filepath = biggest_file[0] guess = guess_video_info(filepath, info = ['filename']) video = Video.fromguess(filepath, guess) video.size = biggest_file[1] print("Donwloading Subtitle") subtitle = download_best_subtitles([video], {Language(lang)}, single=True) if not len(subtitle): subtitle = None else: subtitle = get_subtitle_path(video.name) lt_session.remove_torrent(handle) return subtitle
def download_sub(self, language): l = Language(language) v = scan_video(self.path) sub_path = get_subtitle_path(v.name, l) if not os.path.isfile(sub_path): sub = download_best_subtitles((v,), {l}) # TODO Save in tmp folder if regular is not available save_subtitles(sub) return sub_path
def compute_subtitle_path(subtitle, video_path, subtitles_dir): """Return the full subtitle path that's computed by subliminal. :param subtitle: the subtitle :type subtitle: subliminal.Subtitle :param video_path: the video path :type video_path: str :param subtitles_dir: the subtitles directory :type subtitles_dir: str :return: the computed subtitles path :rtype: str """ subtitle_path = get_subtitle_path(video_path, subtitle.language if sickbeard.SUBTITLES_MULTI else None) return os.path.join(subtitles_dir, os.path.split(subtitle_path)[1]) if subtitles_dir else subtitle_path
def compute_subtitle_path(subtitle, video_path, subtitles_dir): """Return the full subtitle path that's computed by subliminal. :param subtitle: the subtitle :type subtitle: subliminal.Subtitle :param video_path: the video path :type video_path: str :param subtitles_dir: the subtitles directory :type subtitles_dir: str or None :return: the computed subtitles path :rtype: str """ subtitle_path = get_subtitle_path(video_path, subtitle.language if app.SUBTITLES_MULTI else None) return os.path.join(subtitles_dir, os.path.split(subtitle_path)[1]) if subtitles_dir else subtitle_path
def search_movie_subtitle(serie_episode): video = Movie.fromname(serie_episode) subtitles = download_best_subtitles({video}, {Language('spa')}) try: best_sub = subtitles[video][0] except IndexError: logger.info("No subs found for %s. Subs", serie_episode, subtitles) return None saved_subs = save_subtitles(video, [best_sub], directory=SUBS_DIR) if saved_subs: sub_filename = get_subtitle_path(video.name, language=Language('spa')) return os.path.join(SUBS_DIR, sub_filename) else: return None
def download(self, video_file): settings = get_settings() download_dir = settings['save_path'] print("Downloading subtitle") log.info("Downloading subtitle") filepath = join(download_dir, video_file[0]) guess = guess_video_info(filepath, info=['filename']) video = Video.fromguess(filepath, guess) video.size = video_file[1] subtitle = download_best_subtitles([video], {Language(self.lang)}, single=True) if not len(subtitle): subtitle = None else: subtitle = get_subtitle_path(join(download_dir, video.name)) log.info("video_file: %s, filepath: %s, guess: %s, video: %s" "subtitle: %s", video_file, filepath, guess, video, subtitle) return subtitle
def download(self, video_file): subtitle = None settings = get_settings() download_dir = settings.save_path log.info("Downloading subtitle") filepath = join(download_dir, video_file[0]) guess = guess_video_info(filepath, info=['filename']) video = Video.fromguess(filepath, guess) video.size = video_file[1] try: subtitle = download_best_subtitles([video], {Language(self.lang)}, single=True) except ValueError: pass if subtitle is not None and len(subtitle): log.info("CLAH %s %s", download_dir, video.name) subtitle = get_subtitle_path(join(download_dir, video.name.replace("(", "\(") .replace(")", "\)") .replace(" ", "\ "))) log.info("video_file: %s, filepath: %s, guess: %s, video: %s, " "subtitle: %s", video_file, filepath, guess, video, subtitle) return subtitle
def download(self, video_file): subtitle = None settings = get_settings() download_dir = settings.save_path log.info("Downloading subtitle") filepath = join(download_dir, video_file[0]) guess = guessit(filepath) video = Video.fromguess(filepath, guess) video.size = video_file[1] try: subtitles = download_best_subtitles([video], {Language(self.lang)}, only_one=True) except ValueError: pass if subtitles is not None and len(subtitles): subs = subtitles.values()[0] if len(subs): save_subtitles(video, subs, single=True, encoding="utf-8") subtitle = get_subtitle_path(video.name, None) log.info( "video_file: %s, filepath: %s, guess: %s, video: %s, " "subtitle: %s", video_file, filepath, guess, video, subtitle) return subtitle
def usage(): print "Usage: " + sys.argv[0] + " lang series season episode" sys.exit(1) numargs = len(sys.argv) if numargs != 5: usage() lang = sys.argv[1] series = sys.argv[2] season = int(sys.argv[3]) episode = int(sys.argv[4]) e = Episode(series + '.mp4', series, season, episode) l = Language(lang) pathname = None subtitles = download_best_subtitles(set((e, )), set((l, ))) for video, video_subtitles in subtitles.items(): for video_subtitle in video_subtitles: filename = get_subtitle_path(video.name, video_subtitle.language) pathname = os.path.join(OUT_DIR, filename) break save_subtitles(subtitles, directory=OUT_DIR, encoding='utf-8') if pathname is not None: print('{"filename":"' + pathname + '"}') else: print("{}")
def test_get_subtitle_path(movies): video = movies['man_of_steel'] assert get_subtitle_path(video.name, extension='.sub') == os.path.splitext(video.name)[0] + '.sub'
def test_get_subtitle_path_with_language_undefined(movies): video = movies['man_of_steel'] assert get_subtitle_path(video.name, Language('und')) == os.path.splitext(video.name)[0] + '.srt'
def test_get_subtitle_path_with_language(movies): video = movies['man_of_steel'] assert get_subtitle_path(video.name, Language('por', 'BR')) == os.path.splitext(video.name)[0] + '.pt-BR.srt'
def download_subtitles(subtitles_info): # pylint: disable=too-many-locals, too-many-branches, too-many-statements existing_subtitles = subtitles_info['subtitles'] if not needs_subtitles(existing_subtitles): logger.log(u'Episode already has all needed subtitles, skipping {} {}'.format (subtitles_info['show_name'], episode_num(subtitles_info['season'], subtitles_info['episode']) or episode_num(subtitles_info['season'], subtitles_info['episode'], numbering='absolute')), logger.DEBUG) return existing_subtitles, None languages = get_needed_languages(existing_subtitles) if not languages: logger.log(u'No subtitles needed for {} {}'.format (subtitles_info['show_name'], episode_num(subtitles_info['season'], subtitles_info['episode']) or episode_num(subtitles_info['season'], subtitles_info['episode'], numbering='absolute')), logger.DEBUG) return existing_subtitles, None logger.log(u'Checking subtitle candidates for {} {} ({})'.format (subtitles_info['show_name'], episode_num(subtitles_info['season'], subtitles_info['episode']) or episode_num(subtitles_info['season'], subtitles_info['episode'], numbering='absolute'), os.path.basename(subtitles_info['location'])), logger.DEBUG) subtitles_path = get_subtitles_path(subtitles_info['location']) video_path = subtitles_info['location'] # Perfect match = hash score - hearing impaired score - resolution score (subtitle for 720p is the same as for 1080p) # Perfect match = 215 - 1 - 1 = 213 # Non-perfect match = series + year + season + episode # Non-perfect match = 108 + 54 + 18 + 18 = 198 # From latest subliminal code: # episode_scores = {'hash': 215, 'series': 108, 'year': 54, 'season': 18, 'episode': 18, 'release_group': 9, # 'format': 4, 'audio_codec': 2, 'resolution': 1, 'hearing_impaired': 1, 'video_codec': 1} user_score = 213 if sickbeard.SUBTITLES_PERFECT_MATCH else 198 video = get_video(video_path, subtitles_path=subtitles_path) if not video: logger.log(u'Exception caught in subliminal.scan_video for {} {}'.format (subtitles_info['show_name'], episode_num(subtitles_info['season'], subtitles_info['episode']) or episode_num(subtitles_info['season'], subtitles_info['episode'], numbering='absolute')), logger.DEBUG) return existing_subtitles, None providers = enabled_service_list() provider_configs = {'addic7ed': {'username': sickbeard.ADDIC7ED_USER, 'password': sickbeard.ADDIC7ED_PASS}, 'itasa': {'username': sickbeard.ITASA_USER, 'password': sickbeard.ITASA_PASS}, 'legendastv': {'username': sickbeard.LEGENDASTV_USER, 'password': sickbeard.LEGENDASTV_PASS}, 'opensubtitles': {'username': sickbeard.OPENSUBTITLES_USER, 'password': sickbeard.OPENSUBTITLES_PASS}} pool = ProviderPool(providers=providers, provider_configs=provider_configs) try: subtitles_list = pool.list_subtitles(video, languages) for provider in providers: if provider in pool.discarded_providers: logger.log(u'Could not search in {} provider. Discarding for now'.format(provider), logger.DEBUG) if not subtitles_list: logger.log(u'No subtitles found for {} {}'.format (subtitles_info['show_name'], episode_num(subtitles_info['season'], subtitles_info['episode']) or episode_num(subtitles_info['season'], subtitles_info['episode'], numbering='absolute'))) return existing_subtitles, None for subtitle in subtitles_list: score = compute_score(subtitle, video, hearing_impaired=sickbeard.SUBTITLES_HEARING_IMPAIRED) logger.log(u'[{}] Subtitle score for {} is: {} (min={})'.format (subtitle.provider_name, subtitle.id, score, user_score), logger.DEBUG) found_subtitles = pool.download_best_subtitles(subtitles_list, video, languages=languages, hearing_impaired=sickbeard.SUBTITLES_HEARING_IMPAIRED, min_score=user_score, only_one=not sickbeard.SUBTITLES_MULTI) save_subtitles(video, found_subtitles, directory=subtitles_path, single=not sickbeard.SUBTITLES_MULTI) except IOError as error: if 'No space left on device' in ex(error): logger.log(u'Not enough space on the drive to save subtitles', logger.WARNING) else: logger.log(traceback.format_exc(), logger.WARNING) except Exception: logger.log(u'Error occurred when downloading subtitles for: {}'.format(video_path)) logger.log(traceback.format_exc(), logger.ERROR) return existing_subtitles, None if not found_subtitles: logger.log(u'No subtitles matched for {} {}'.format (subtitles_info['show_name'], episode_num(subtitles_info['season'], subtitles_info['episode']) or episode_num(subtitles_info['season'], subtitles_info['episode'], numbering='absolute'))) return existing_subtitles, None for subtitle in found_subtitles: subtitle_path = get_subtitle_path(video.name, None if not sickbeard.SUBTITLES_MULTI else subtitle.language) if subtitles_path: subtitle_path = os.path.join(subtitles_path, os.path.split(subtitle_path)[1]) sickbeard.helpers.chmodAsParent(subtitle_path) sickbeard.helpers.fixSetGroupID(subtitle_path) if sickbeard.SUBTITLES_HISTORY: logger.log(u'history.logSubtitle {}, {}'.format (subtitle.provider_name, subtitle.language.opensubtitles), logger.DEBUG) history.logSubtitle(subtitles_info['show_indexerid'], subtitles_info['season'], subtitles_info['episode'], subtitles_info['status'], subtitle) if sickbeard.SUBTITLES_EXTRA_SCRIPTS and isMediaFile(video_path) and not sickbeard.EMBEDDED_SUBTITLES_ALL: run_subs_scripts(subtitles_info, subtitle.language, subtitle_path, video.name) new_subtitles = sorted({subtitle.language.opensubtitles for subtitle in found_subtitles}) current_subtitles = sorted({subtitle for subtitle in new_subtitles + existing_subtitles}) if existing_subtitles else new_subtitles if not sickbeard.SUBTITLES_MULTI and len(found_subtitles) == 1: new_code = found_subtitles[0].language.opensubtitles if new_code not in existing_subtitles: current_subtitles.remove(new_code) current_subtitles.append('und') return current_subtitles, new_subtitles
def subtitles_download_in_pp(): # pylint: disable=too-many-locals, too-many-branches, too-many-statements logger.log(u'Checking for needed subtitles in Post-Process folder', logger.INFO) providers = enabled_service_list() provider_configs = {'addic7ed': {'username': sickbeard.ADDIC7ED_USER, 'password': sickbeard.ADDIC7ED_PASS}, 'itasa': {'username': sickbeard.ITASA_USER, 'password': sickbeard.ITASA_PASS}, 'legendastv': {'username': sickbeard.LEGENDASTV_USER, 'password': sickbeard.LEGENDASTV_PASS}, 'opensubtitles': {'username': sickbeard.OPENSUBTITLES_USER, 'password': sickbeard.OPENSUBTITLES_PASS}} pool = ProviderPool(providers=providers, provider_configs=provider_configs) # Search for all wanted languages languages = {from_code(language) for language in wanted_languages()} if not languages: return # Dict of language exceptions to use with subliminal language_exceptions = {'pt-br': 'pob'} run_post_process = False # Check if PP folder is set if sickbeard.TV_DOWNLOAD_DIR and os.path.isdir(sickbeard.TV_DOWNLOAD_DIR): for root, _, files in os.walk(sickbeard.TV_DOWNLOAD_DIR, topdown=False): rar_files = [rar_file for rar_file in files if isRarFile(rar_file)] if rar_files and sickbeard.UNPACK: video_files = [video_file for video_file in files if isMediaFile(video_file)] if u'_UNPACK' not in root and (not video_files or root == sickbeard.TV_DOWNLOAD_DIR): logger.log(u'Found rar files in post-process folder: {}'.format(rar_files), logger.DEBUG) result = processTV.ProcessResult() processTV.unRAR(root, rar_files, False, result) elif rar_files and not sickbeard.UNPACK: logger.log(u'Unpack is disabled. Skipping: {}'.format(rar_files), logger.WARNING) for root, _, files in os.walk(sickbeard.TV_DOWNLOAD_DIR, topdown=False): for filename in sorted(files): try: # Remove non release groups from video file. Needed to match subtitles new_filename = remove_non_release_groups(filename) if new_filename != filename: os.rename(filename, new_filename) filename = new_filename except Exception as error: logger.log(u"Couldn't remove non release groups from video file. Error: {}".format (ex(error)), logger.DEBUG) # Delete unwanted subtitles before downloading new ones if sickbeard.SUBTITLES_MULTI and sickbeard.SUBTITLES_KEEP_ONLY_WANTED and filename.rpartition('.')[2] in subtitle_extensions: subtitle_language = filename.rsplit('.', 2)[1].lower() if len(subtitle_language) == 2 and subtitle_language in language_converters['opensubtitles'].codes: subtitle_language = Language.fromcode(subtitle_language, 'alpha2').opensubtitles elif subtitle_language in language_exceptions: subtitle_language = language_exceptions.get(subtitle_language, subtitle_language) elif subtitle_language not in language_converters['opensubtitles'].codes: subtitle_language = 'unknown' if subtitle_language not in sickbeard.SUBTITLES_LANGUAGES: try: os.remove(os.path.join(root, filename)) logger.log(u"Deleted '{}' because we don't want subtitle language '{}'. We only want '{}' language(s)".format (filename, subtitle_language, ','.join(sickbeard.SUBTITLES_LANGUAGES)), logger.DEBUG) except Exception as error: logger.log(u"Couldn't delete subtitle: {}. Error: {}".format(filename, ex(error)), logger.DEBUG) if isMediaFile(filename): subtitles_enabled = processTV.subtitles_enabled(filename) if subtitles_enabled: if sickbeard.SUBTITLES_PRE_SCRIPTS and not sickbeard.EMBEDDED_SUBTITLES_ALL: run_subs_scripts(None, None, None, filename, is_pre=True) try: video = scan_video(os.path.join(root, filename)) subtitles_list = pool.list_subtitles(video, languages) for provider in providers: if provider in pool.discarded_providers: logger.log(u'Could not search in {} provider. Discarding for now'.format(provider), logger.DEBUG) if not subtitles_list: logger.log(u'No subtitles found for {}'.format (os.path.join(root, filename)), logger.DEBUG) continue logger.log(u'Found subtitle(s) canditate(s) for {}'.format(filename), logger.INFO) hearing_impaired = sickbeard.SUBTITLES_HEARING_IMPAIRED user_score = 213 if sickbeard.SUBTITLES_PERFECT_MATCH else 198 found_subtitles = pool.download_best_subtitles(subtitles_list, video, languages=languages, hearing_impaired=hearing_impaired, min_score=user_score, only_one=not sickbeard.SUBTITLES_MULTI) for subtitle in subtitles_list: score = compute_score(subtitle, video, hearing_impaired=sickbeard.SUBTITLES_HEARING_IMPAIRED) logger.log(u'[{}] Subtitle score for {} is: {} (min={})'.format (subtitle.provider_name, subtitle.id, score, user_score), logger.DEBUG) downloaded_languages = set() for subtitle in found_subtitles: logger.log(u'Found subtitle for {} in {} provider with language {}'.format (os.path.join(root, filename), subtitle.provider_name, subtitle.language.opensubtitles), logger.INFO) save_subtitles(video, found_subtitles, directory=root, single=not sickbeard.SUBTITLES_MULTI) subtitles_multi = not sickbeard.SUBTITLES_MULTI subtitle_path = get_subtitle_path(video.name, None if subtitles_multi else subtitle.language) if root: subtitle_path = os.path.join(root, os.path.split(subtitle_path)[1]) sickbeard.helpers.chmodAsParent(subtitle_path) sickbeard.helpers.fixSetGroupID(subtitle_path) downloaded_languages.add(subtitle.language.opensubtitles) # Don't run post processor unless at least one file has all of the needed subtitles if not needs_subtitles(downloaded_languages): run_post_process = True except Exception as error: logger.log(u'Error occurred when downloading subtitles for: {}. Error: {}'.format (os.path.join(root, filename), ex(error))) elif subtitles_enabled is False: logger.log(u"Subtitle disabled for show: {}".format(filename), logger.DEBUG) if run_post_process: logger.log(u'Starting post-process with default settings now that we found subtitles') processTV.processDir(sickbeard.TV_DOWNLOAD_DIR) else: logger.log(u'You must set a valid post-process folder in "Post Processing" settings', logger.WARNING)
# Download all shooters shooter_providers = ['shooter'] shooter_subtitles = list_subtitles(videos, {Language('zho')}, providers=shooter_providers) for movie, subtitles in shooter_subtitles.items(): try: download_subtitles(subtitles) for subtitle in subtitles: if subtitle.content is None: logger.error('Skipping subtitle %r: no content' % subtitle) continue # create subtitle path subtitle_path = get_subtitle_path(movie.name, subtitle.language) filename_language, file_extension = os.path.splitext(subtitle_path) filename, language = os.path.splitext(filename_language) subtitle_path = "%s.shooter-%s%s%s" % ( filename, str( subtitles.index(subtitle)), language, file_extension) # save content as is or in the specified encoding with io.open(subtitle_path, 'wb') as f: f.write(subtitle.content) except Exception: pass # Providers providers = [ 'addic7ed', 'opensubtitles',
def test_get_subtitle_path_with_language_undefined(movies): video = movies['man_of_steel'] assert get_subtitle_path( video.name, Language('und')) == os.path.splitext(video.name)[0] + '.srt'
def test_get_subtitle_path(movies): video = movies['man_of_steel'] assert get_subtitle_path( video.name, extension='.sub') == os.path.splitext(video.name)[0] + '.sub'
def download_subtitle(path, language, hi, providers, providers_auth, sceneName, media_type): logging.debug('BAZARR Searching subtitles for this file: ' + path) if hi == "True": hi = True else: hi = False language_set = set() if language == 'pob': language_set.add(Language('por', 'BR')) else: language_set.add(Language(language)) use_scenename = settings.general.getboolean('use_scenename') minimum_score = settings.general.minimum_score minimum_score_movie = settings.general.minimum_score_movie use_postprocessing = settings.general.getboolean('use_postprocessing') postprocessing_cmd = settings.general.postprocessing_cmd try: if sceneName == "None" or use_scenename is False: used_sceneName = False video = scan_video(path) else: used_sceneName = True video = Video.fromname(sceneName) except Exception as e: logging.exception("BAZARR Error trying to get video information for this file: " + path) pass else: if media_type == "movie": max_score = 120.0 elif media_type == "series": max_score = 360.0 try: with AsyncProviderPool(max_workers=None, providers=providers, provider_configs=providers_auth) as p: subtitles = p.list_subtitles(video, language_set) except Exception as e: logging.exception("BAZARR Error trying to get subtitle list from provider for this file: " + path) else: subtitles_list = [] try: sorted_subtitles = sorted([(s, compute_score(s, video, hearing_impaired=hi)) for s in subtitles], key=operator.itemgetter(1), reverse=True) except Exception as e: logging.exception('BAZARR Exception raised while trying to compute score for this file: ' + path) return None else: for s, preliminary_score in sorted_subtitles: if media_type == "movie": if (preliminary_score / max_score * 100) < int(minimum_score_movie): continue matched = set(s.get_matches(video)) if hi == s.hearing_impaired: matched.add('hearing_impaired') not_matched = set(score.movie_scores.keys()) - matched required = set(['title']) if any(elem in required for elem in not_matched): continue elif media_type == "series": if (preliminary_score / max_score * 100) < int(minimum_score): continue matched = set(s.get_matches(video)) if hi == s.hearing_impaired: matched.add('hearing_impaired') not_matched = set(score.episode_scores.keys()) - matched required = set(['series', 'season', 'episode']) if any(elem in required for elem in not_matched): continue subtitles_list.append(s) logging.debug('BAZARR ' + str(len(subtitles_list)) + " subtitles have been found for this file: " + path) if len(subtitles_list) > 0: try: download_result = False for subtitle in subtitles_list: download_result = p.download_subtitle(subtitle) if download_result: logging.debug('BAZARR Subtitles file downloaded from ' + str(subtitle.provider_name) + ' for this file: ' + path) break else: logging.warning('BAZARR Subtitles file skipped from ' + str(subtitle.provider_name) + ' for this file: ' + path + ' because no content was returned by the provider (probably throttled).') continue if not download_result: logging.error('BAZARR Tried to download a subtitles for file: ' + path + " but we weren't able to do it this time (probably being throttled). Going to retry on next search.") return None except Exception as e: logging.exception('BAZARR Error downloading subtitles for this file ' + path) return None else: try: calculated_score = round(float(compute_score(subtitle, video, hearing_impaired=hi)) / max_score * 100, 2) if used_sceneName: video = scan_video(path) single = settings.general.getboolean('single_language') if single is True: result = save_subtitles(video, [subtitle], single=True, encoding='utf-8') else: result = save_subtitles(video, [subtitle], encoding='utf-8') except Exception as e: logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path) pass else: downloaded_provider = result[0].provider_name downloaded_language = language_from_alpha3(result[0].language.alpha3) downloaded_language_code2 = alpha2_from_alpha3(result[0].language.alpha3) downloaded_language_code3 = result[0].language.alpha3 downloaded_path = get_subtitle_path(path, downloaded_language_code2) logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path) if used_sceneName: message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(calculated_score) + "% using this scene name: " + sceneName else: message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(calculated_score) + "% using filename guessing." if use_postprocessing is True: command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3) try: if os.name == 'nt': codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out_codepage, err_codepage = codepage.communicate() encoding = out_codepage.split(':')[-1].strip() process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out, err = process.communicate() if os.name == 'nt': out = out.decode(encoding) except: if out == "": logging.error('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.error('BAZARR Post-processing result for file ' + path + ' : ' + out) else: if out == "": logging.info('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.info('BAZARR Post-processing result for file ' + path + ' : ' + out) return message else: logging.debug('BAZARR No subtitles were found for this file: ' + path) return None logging.debug('BAZARR Ended searching subtitles for file: ' + path)
def manual_download_subtitle(path, language, hi, subtitle, provider, providers_auth, sceneName, media_type): logging.debug('BAZARR Manually downloading subtitles for this file: ' + path) if hi == "True": hi = True else: hi = False subtitle = pickle.loads(codecs.decode(subtitle.encode(), "base64")) if media_type == 'series': type_of_score = 360 elif media_type == 'movie': type_of_score = 120 use_scenename = settings.general.getboolean('use_scenename') use_postprocessing = settings.general.getboolean('use_postprocessing') postprocessing_cmd = settings.general.postprocessing_cmd language = alpha3_from_alpha2(language) if language == 'pob': lang_obj = Language('por', 'BR') else: lang_obj = Language(language) try: if sceneName is None or use_scenename is False: used_sceneName = False video = scan_video(path) else: used_sceneName = True video = Video.fromname(sceneName) except Exception as e: logging.exception("BAZARR Error trying to get video information for this file: " + path) pass else: try: download_subtitles([subtitle], providers=provider, provider_configs=providers_auth) logging.debug('BAZARR Subtitles file downloaded for this file:' + path) except Exception as e: logging.exception('BAZARR Error downloading subtitles for this file ' + path) return None else: single = settings.general.getboolean('single_language') try: score = round(float(compute_score(subtitle, video, hearing_impaired=hi)) / type_of_score * 100, 2) if used_sceneName == True: video = scan_video(path) if single is True: result = save_subtitles(video, [subtitle], single=True, encoding='utf-8') else: result = save_subtitles(video, [subtitle], encoding='utf-8') except Exception as e: logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path) return None else: if len(result) > 0: downloaded_provider = result[0].provider_name downloaded_language = language_from_alpha3(result[0].language.alpha3) downloaded_language_code2 = alpha2_from_alpha3(result[0].language.alpha3) downloaded_language_code3 = result[0].language.alpha3 downloaded_path = get_subtitle_path(path, downloaded_language_code2) logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path) message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(score) + "% using manual search." if use_postprocessing is True: command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3) try: if os.name == 'nt': codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out_codepage, err_codepage = codepage.communicate() encoding = out_codepage.split(':')[-1].strip() process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out, err = process.communicate() if os.name == 'nt': out = out.decode(encoding) except: if out == "": logging.error('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.error('BAZARR Post-processing result for file ' + path + ' : ' + out) else: if out == "": logging.info('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.info('BAZARR Post-processing result for file ' + path + ' : ' + out) return message else: logging.error("BAZARR Tried to manually download a subtitles for file: " + path + " but we weren't able to do (probably throttled by " + str(subtitle.provider_name) + ". Please retry later or select a subtitles from another provider.") return None logging.debug('BAZARR Ended manually downloading subtitles for file: ' + path)
def test_get_subtitle_path_with_language(movies): video = movies['man_of_steel'] assert get_subtitle_path(video.name, Language( 'por', 'BR')) == os.path.splitext(video.name)[0] + '.pt-BR.srt'
def get_subtitle_path(video_file, language): return get_subtitle_path(video_file, language=language)
OUT_DIR = "/tmp" def usage(): print "Usage: " + sys.argv[0] + " lang series season episode" sys.exit(1) numargs = len(sys.argv) if numargs != 5: usage() lang = sys.argv[1] series = sys.argv[2] season = int(sys.argv[3]) episode = int(sys.argv[4]) e = Episode(series + '.mp4', series, season, episode) l = Language(lang) pathname = None subtitles = download_best_subtitles(set((e,)), set((l,))) for video, video_subtitles in subtitles.items(): for video_subtitle in video_subtitles: filename = get_subtitle_path(video.name, video_subtitle.language) pathname = os.path.join(OUT_DIR, filename) break save_subtitles(subtitles, directory=OUT_DIR, encoding='utf-8') if pathname is not None: print('{"filename":"' + pathname + '"}') else: print("{}")
def manual_download_subtitle(path, language, hi, subtitle, provider, providers_auth, sceneName, media_type): if hi == "True": hi = True else: hi = False subtitle = pickle.loads(codecs.decode(subtitle.encode(), "base64")) if media_type == 'series': type_of_score = 360 elif media_type == 'movie': type_of_score = 120 use_scenename = get_general_settings()[9] use_postprocessing = get_general_settings()[10] postprocessing_cmd = get_general_settings()[11] language = alpha3_from_alpha2(language) if language == 'pob': lang_obj = Language('por', 'BR') else: lang_obj = Language(language) try: if sceneName is None or use_scenename is False: used_sceneName = False video = scan_video(path) else: used_sceneName = True video = Video.fromname(sceneName) except Exception as e: logging.exception('Error trying to extract information from this filename: ' + path) return None else: try: best_subtitle = subtitle download_subtitles([best_subtitle], providers=provider, provider_configs=providers_auth) except Exception as e: logging.exception('Error downloading subtitles for ' + path) return None else: single = get_general_settings()[7] try: score = round(float(compute_score(best_subtitle, video, hearing_impaired=hi)) / type_of_score * 100, 2) if used_sceneName == True: video = scan_video(path) if single is True: result = save_subtitles(video, [best_subtitle], single=True, encoding='utf-8') else: result = save_subtitles(video, [best_subtitle], encoding='utf-8') except Exception as e: logging.exception('Error saving subtitles file to disk.') return None else: if len(result) > 0: downloaded_provider = result[0].provider_name downloaded_language = language_from_alpha3(result[0].language.alpha3) downloaded_language_code2 = alpha2_from_alpha3(result[0].language.alpha3) downloaded_language_code3 = result[0].language.alpha3 downloaded_path = get_subtitle_path(path, language=lang_obj) message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(score) + "% using manual search." if use_postprocessing is True: command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3) try: if os.name == 'nt': codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out_codepage, err_codepage = codepage.communicate() encoding = out_codepage.split(':')[-1].strip() process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out, err = process.communicate() if os.name == 'nt': out = out.decode(encoding) except: if out == "": logging.error('Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.error('Post-processing result for file ' + path + ' : ' + out) else: if out == "": logging.info('Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.info('Post-processing result for file ' + path + ' : ' + out) return message else: return None
def run(self, scan_path, scan_age, languages, encoding, min_score, providers, provider_configs, max_workers, plex_url=None, plex_token=None, *args, **kwargs): if not os.path.isdir(scan_path): raise IOError('Path \'%s\' doesn\'t exist!' % scan_path) if not scan_age >= 1: raise ValueError('\'scan_age\' must by at least 1!') if not len(languages) >= 1: raise ValueError('\'languages\' list can\'t be empty!') if not providers: raise ValueError('\'providers\' argument can\'t be empty!') if not max_workers >= 1: raise ValueError('\'max_workers\' must be at least 1!') if not provider_configs: provider_configs = {} __tree_dict = lambda: defaultdict(__tree_dict) result = __tree_dict() encoding = codecs.lookup(encoding).name age = timedelta(weeks=scan_age) languages = set([Language(l) for l in languages]) plex = None if plex_url and plex_token: plex = PlexServer(plex_url, plex_token) scan_start = datetime.now() videos = [] ignored_videos = [] if not region.is_configured: region.configure('dogpile.cache.dbm', expiration_time=timedelta(days=30), arguments={ 'filename': 'subliminal.dbm', 'lock_factory': MutexLock }) # scan videos scanned_videos = scan_videos(scan_path, age=age) for video in scanned_videos: video.subtitle_languages |= set( search_external_subtitles(video.name).values()) if check_video(video, languages=languages, age=age, undefined=False): refine(video) if languages - video.subtitle_languages: videos.append(video) else: ignored_videos.append(video) else: ignored_videos.append(video) if videos: result['videos']['collected'] = [ os.path.split(v.name)[1] for v in videos ] if ignored_videos: result['videos']['ignored'] = len(ignored_videos) if videos: # download best subtitles downloaded_subtitles = defaultdict(list) with AsyncProviderPool(max_workers=max_workers, providers=providers, provider_configs=provider_configs) as p: for video in videos: scores = get_scores(video) subtitles_to_download = p.list_subtitles( video, languages - video.subtitle_languages) downloaded_subtitles[video] = p.download_best_subtitles( subtitles_to_download, video, languages, min_score=scores['hash'] * min_score / 100) if p.discarded_providers: result['providers']['discarded'] = list( p.discarded_providers) # filter subtitles with TinyDB('subtitle_db.json') as db: table = db.table('downloaded') query = Query() for video, subtitles in downloaded_subtitles.items(): discarded_subtitles = list() discarded_subtitles_info = list() for s in subtitles: subtitle_hash = hashlib.sha256(s.content).hexdigest() subtitle_file = get_subtitle_path( os.path.split(video.name)[1], s.language) dbo = {'hash': subtitle_hash, 'file': subtitle_file} if table.search((query.hash == subtitle_hash) & (query.file == subtitle_file)): discarded_subtitles.append(s) discarded_subtitles_info.append(dbo) else: table.insert(dbo) downloaded_subtitles[video] = [ x for x in subtitles if x not in discarded_subtitles ] if discarded_subtitles_info: result['subtitles'][ 'discarded'] = result['subtitles'].get( 'discarded', []) + discarded_subtitles_info downloaded_subtitles = { k: v for k, v in downloaded_subtitles.items() if v } # save subtitles saved_subtitles = {} for video, subtitles in downloaded_subtitles.items(): saved_subtitles[video] = save_subtitles(video, subtitles, directory=None, encoding=encoding) for key, group in groupby(saved_subtitles[video], lambda x: x.provider_name): subtitle_filenames = [ get_subtitle_path( os.path.split(video.name)[1], s.language) for s in list(group) ] result['subtitles'][key] = result['subtitles'].get( key, []) + subtitle_filenames result['subtitles']['total'] = sum( len(v) for v in saved_subtitles.values()) # refresh plex for video, subtitles in saved_subtitles.items(): if plex and subtitles: item_found = False for section in plex.library.sections(): try: if isinstance(section, MovieSection) and isinstance( video, Movie): results = section.search(title=video.title, year=video.year, libtype='movie', sort='addedAt:desc', maxresults=1) if not results: raise NotFound plex_item = results[0] elif isinstance(section, ShowSection) and isinstance( video, Episode): results = section.search(title=video.series, year=video.year, libtype='show', sort='addedAt:desc', maxresults=1) if not results: raise NotFound plex_item = results[0].episode( season=video.season, episode=video.episode) else: continue except NotFound: continue except BadRequest: continue if plex_item: plex_item.refresh() result['plex']['refreshed'] = result['plex'].get( 'refreshed', []) + [ '%s%s' % (repr(plex_item.section()), repr(video)) ] item_found = True if not item_found: result['plex']['failed'] = result['plex'].get( 'failed', []) + [repr(video)] # convert subtitles for video, subtitles in saved_subtitles.items(): target_format = aeidon.formats.SUBRIP for s in subtitles: subtitle_path = get_subtitle_path(video.name, s.language) source_format = aeidon.util.detect_format( subtitle_path, encoding) source_file = aeidon.files.new( source_format, subtitle_path, aeidon.encodings.detect_bom(subtitle_path) or encoding) if source_format != target_format: format_info = { 'file': get_subtitle_path( os.path.split(video.name)[1], s.language), 'from': source_format.label, 'to': target_format.label } result['subtitles'][ 'converted'] = result['subtitles'].get( 'converted', []) + [format_info] aeidon_subtitles = source_file.read() for f in [ aeidon.formats.SUBRIP, aeidon.formats.MICRODVD, aeidon.formats.MPL2 ]: markup = aeidon.markups.new(f) for s in aeidon_subtitles: s.main_text = markup.decode(s.main_text) markup = aeidon.markups.new(target_format) for s in aeidon_subtitles: s.main_text = markup.encode(s.main_text) target_file = aeidon.files.new(target_format, subtitle_path, encoding) target_file.write(aeidon_subtitles, aeidon.documents.MAIN) scan_end = datetime.now() result['meta']['start'] = scan_start.isoformat() result['meta']['end'] = scan_end.isoformat() result['meta']['duration'] = str(scan_end - scan_start) return result
def download_subtitle(path, language, hi, providers, providers_auth, sceneName, media_type): if hi == "True": hi = True else: hi = False language_set = set() if language == 'pob': language_set.add(Language('por', 'BR')) else: language_set.add(Language(language)) use_scenename = get_general_settings()[9] minimum_score = get_general_settings()[8] minimum_score_movie = get_general_settings()[22] use_postprocessing = get_general_settings()[10] postprocessing_cmd = get_general_settings()[11] try: if sceneName == "None" or use_scenename is False: used_sceneName = False video = scan_video(path) else: used_sceneName = True video = Video.fromname(sceneName) except Exception as e: logging.exception("Error trying to get video information for this file: " + path) else: if media_type == "movie": max_score = 120.0 elif media_type == "series": max_score = 360.0 try: with AsyncProviderPool(max_workers=None, providers=providers, provider_configs=providers_auth) as p: subtitles = p.list_subtitles(video, language_set) except Exception as e: logging.exception("Error trying to get subtitle list from provider") else: subtitles_list = [] sorted_subtitles = sorted([(s, compute_score(s, video, hearing_impaired=hi)) for s in subtitles], key=operator.itemgetter(1), reverse=True) for s, preliminary_score in sorted_subtitles: if media_type == "movie": if (preliminary_score / max_score * 100) < int(minimum_score_movie): continue matched = set(s.get_matches(video)) if hi == s.hearing_impaired: matched.add('hearing_impaired') not_matched = set(score.movie_scores.keys()) - matched required = set(['title']) if any(elem in required for elem in not_matched): continue elif media_type == "series": if (preliminary_score / max_score * 100) < int(minimum_score): continue matched = set(s.get_matches(video)) if hi == s.hearing_impaired: matched.add('hearing_impaired') not_matched = set(score.episode_scores.keys()) - matched required = set(['series', 'season', 'episode']) if any(elem in required for elem in not_matched): continue subtitles_list.append(s) if len(subtitles_list) > 0: best_subtitle = subtitles_list[0] download_subtitles([best_subtitle], providers=providers, provider_configs=providers_auth) try: calculated_score = round(float(compute_score(best_subtitle, video, hearing_impaired=hi)) / max_score * 100, 2) if used_sceneName == True: video = scan_video(path) single = get_general_settings()[7] if single is True: result = save_subtitles(video, [best_subtitle], single=True, encoding='utf-8') else: result = save_subtitles(video, [best_subtitle], encoding='utf-8') except Exception as e: logging.exception('Error saving subtitles file to disk.') return None else: if len(result) > 0: downloaded_provider = result[0].provider_name downloaded_language = language_from_alpha3(result[0].language.alpha3) downloaded_language_code2 = alpha2_from_alpha3(result[0].language.alpha3) downloaded_language_code3 = result[0].language.alpha3 downloaded_path = get_subtitle_path(path, language=language_set) if used_sceneName == True: message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(calculated_score) + "% using this scene name: " + sceneName else: message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(calculated_score) + "% using filename guessing." if use_postprocessing is True: command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3) try: if os.name == 'nt': codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out_codepage, err_codepage = codepage.communicate() encoding = out_codepage.split(':')[-1].strip() process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out, err = process.communicate() if os.name == 'nt': out = out.decode(encoding) except: if out == "": logging.error('Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.error('Post-processing result for file ' + path + ' : ' + out) else: if out == "": logging.info('Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.info('Post-processing result for file ' + path + ' : ' + out) return message else: return None else: return None