def get_video(video_path, subtitles_path=None): if not subtitles_path: subtitles_path = get_subtitles_path(video_path) try: # Encode paths to UTF-8 to ensure subliminal support. video_path = video_path.encode('utf-8') subtitles_path = subtitles_path.encode('utf-8') except UnicodeEncodeError: # Fallback to system encoding. This should never happen. video_path = video_path.encode(sickbeard.SYS_ENCODING) subtitles_path = subtitles_path.encode(sickbeard.SYS_ENCODING) try: if not sickbeard.EMBEDDED_SUBTITLES_ALL and video_path.endswith('.mkv'): video = subliminal.scan_video(video_path, subtitles=True, embedded_subtitles=True, subtitles_dir=subtitles_path) else: video = subliminal.scan_video(video_path, subtitles=True, embedded_subtitles=False, subtitles_dir=subtitles_path) except Exception as error: logger.log(u'Exception: {}'.format(error), logger.DEBUG) return None return video
def get_video(video_path, subtitles_path=None): if not subtitles_path: try: subtitles_path = get_subtitles_path(video_path).encode( sickbeard.SYS_ENCODING) except UnicodeEncodeError as error: logger.log( u'An error occurred while encoding \'{}\' with your current locale. ' 'Rename the file or try a different locale. Error: {}'.format( video_path, ex(error)), logger.WARNING) return None try: if not sickbeard.EMBEDDED_SUBTITLES_ALL and video_path.endswith( '.mkv'): video = subliminal.scan_video(video_path, subtitles=True, embedded_subtitles=True, subtitles_dir=subtitles_path) else: video = subliminal.scan_video(video_path, subtitles=True, embedded_subtitles=False, subtitles_dir=subtitles_path) except Exception: return None return video
def get_video(video_path, subtitles_path=None): if not subtitles_path: subtitles_path = get_subtitles_path(video_path).encode(sickbeard.SYS_ENCODING) try: if not sickbeard.EMBEDDED_SUBTITLES_ALL and video_path.endswith('.mkv'): video = subliminal.scan_video(video_path, subtitles=True, embedded_subtitles=True, subtitles_dir=subtitles_path) else: video = subliminal.scan_video(video_path, subtitles=True, embedded_subtitles=False, subtitles_dir=subtitles_path) except Exception: return None return video
def import_subs(filename): if not core.GETSUBS: return try: subliminal.region.configure('dogpile.cache.dbm', arguments={'filename': 'cachefile.dbm'}) except Exception: pass languages = set() for item in core.SLANGUAGES: try: languages.add(Language(item)) except Exception: pass if not languages: return logger.info('Attempting to download subtitles for {0}'.format(filename), 'SUBTITLES') try: video = subliminal.scan_video(filename) subtitles = subliminal.download_best_subtitles({video}, languages) subliminal.save_subtitles(video, subtitles[video]) for subtitle in subtitles[video]: subtitle_path = subliminal.subtitle.get_subtitle_path( video.name, subtitle.language) os.chmod(subtitle_path, 0o644) except Exception as e: logger.error( 'Failed to download subtitles for {0} due to: {1}'.format( filename, e), 'SUBTITLES')
def on_created(event): if event.is_directory: return path = event.src_path if not mimetypes.guess_type(path)[0].startswith('video'): return try: logging.info(f"Pulling subtitles for: {path}") video = scan_video(path) provider_pool = ProviderPool( providers=ENABLED_PROVIDERS, provider_configs=PROVIDER_CONFIGURATIONS) subtitles = provider_pool.list_subtitles( video=video, languages={Language('eng'), Language('nld')}) best_subtitles = provider_pool.download_best_subtitles( subtitles=subtitles, video=video, languages={Language('eng'), Language('nld')}) save_subtitles(video, best_subtitles) logging.info(f"Subtitles saved for: {path}") except Exception as e: logging.error(f"Error: {repr(e)}")
def download_subtitles(): """Download subtitles""" if request.json: mydata = request.json if not 'path' in mydata: # check if empty log(NO_PATH_PROVIDED) return error(NO_PATH_PROVIDED, 406) # check if languages is empty, if so use english if not 'languages' in mydata or not mydata['languages']: mydata['languages'] = "eng" log(json.dumps(mydata)) path = mydata['path'] videos = [] try: videos.append(scan_video(path)) subtitles = download_best_subtitles( videos, parse_languages(mydata['languages'])) for video in videos: save_subtitles(video, subtitles[video]) return json.dumps(mydata) except Exception: log(NO_SUBTITLES_FOUND) return error(NO_SUBTITLES_FOUND, 404) else: log(NO_DATA_RECEIVED) return error(NO_DATA_RECEIVED, 406)
def get_video(video_path, subtitles_path=None, subtitles=True, embedded_subtitles=None): if not subtitles_path: subtitles_path = get_subtitles_path(video_path) try: # Encode paths to UTF-8 to ensure subliminal support. video_path = video_path.encode('utf-8') subtitles_path = subtitles_path.encode('utf-8') except UnicodeEncodeError: # Fallback to system encoding. This should never happen. video_path = video_path.encode(sickbeard.SYS_ENCODING) subtitles_path = subtitles_path.encode(sickbeard.SYS_ENCODING) try: video = subliminal.scan_video(video_path) # external subtitles if subtitles: video.subtitle_languages |= \ set(subliminal.core.search_external_subtitles(video_path, directory=subtitles_path).values()) if embedded_subtitles is None: embedded_subtitles = bool(not sickbeard.EMBEDDED_SUBTITLES_ALL and video_path.endswith('.mkv')) subliminal.refine(video, embedded_subtitles=embedded_subtitles) except Exception as error: logger.log(u'Exception: {0}'.format(error), logger.DEBUG) return None return video
def subtitlesLanguages(video_path): """Return a list detected subtitles for the given video file""" resultList = [] # Serch for embedded subtitles embedded_languages = subliminal.scan_video(video_path, subtitles=False, embedded_subtitles=not sickbeard.EMBEDDED_SUBTITLES_ALL) # Search subtitles in the absolute path if sickbeard.SUBTITLES_DIR and ek(os.path.exists, sickbeard.SUBTITLES_DIR): video_path = ek(os.path.join, sickbeard.SUBTITLES_DIR, ek(os.path.basename, video_path)) # Search subtitles in the relative path elif sickbeard.SUBTITLES_DIR: video_path = ek(os.path.join, ek(os.path.dirname, video_path), sickbeard.SUBTITLES_DIR, ek(os.path.basename, video_path)) languages = subliminal.video.scan_subtitle_languages(video_path) for language in languages.union(embedded_languages.subtitle_languages): if hasattr(language, 'opensubtitles') and language.opensubtitles: resultList.append(language.opensubtitles) elif hasattr(language, 'alpha3') and language.alpha3: resultList.append(language.alpha3) elif hasattr(language, 'alpha2') and language.alpha2: resultList.append(language.alpha2) defaultLang = wantedLanguages() if ('pob' in defaultLang or 'pb' in defaultLang) and ('pt' not in defaultLang and 'por' not in defaultLang): resultList = [x if not x in ['por', 'pt'] else u'pob' for x in resultList] return sorted(resultList)
def match_episodes(episodes, show_list): """Match episodes using subliminal.""" episode_matching = {'matched': [], 'notmatched': []} for episode_path in episodes: try: episode = subliminal.scan_video(episode_path) except ValueError: tv_data = re_tv.match(os.path.basename(episode_path)) episode = None if tv_data: episode = subliminal.video.Episode(episode_path, tv_data.group(1).replace(".", " "), tv_data.group(2), tv_data.group(3)) if not episode: episode_matching['notmatched'].append((episode_path, 'id')) continue series = None for show in show_list: if isinstance(episode, subliminal.Movie): # It's a show detected as a movie episod = EpisodePlaceholder() episod.series = episode.title episod.season = 1 episod.name = episode.name episode = episod if show.lower() == SHOW_CONVERSIONS.get(episode.series, episode.series.lower()): series = show episode.series = show if not series: episode_matching['notmatched'].append((episode_path, 'showlist')) continue episode_matching['matched'].append(episode) return episode_matching['matched'], episode_matching['notmatched']
def downloadSubtitles(subtitles_info): existing_subtitles = subtitles_info[b'subtitles'] # First of all, check if we need subtitles languages = getNeededLanguages(existing_subtitles) if not languages: sickrage.LOGGER.debug('%s: No missing subtitles for S%02dE%02d' % ( subtitles_info[b'show.indexerid'], subtitles_info[b'season'], subtitles_info[b'episode'])) return existing_subtitles, None subtitles_path = getSubtitlesPath(subtitles_info[b'location']).encode(sickrage.SYS_ENCODING) video_path = subtitles_info[b'location'].encode(sickrage.SYS_ENCODING) providers = getEnabledServiceList() try: video = subliminal.scan_video(video_path, subtitles=False, embedded_subtitles=False) except Exception: sickrage.LOGGER.debug('%s: Exception caught in subliminal.scan_video for S%02dE%02d' % (subtitles_info[b'show.indexerid'], subtitles_info[b'season'], subtitles_info[b'episode'])) return existing_subtitles, None provider_configs = {'addic7ed': {'username': sickrage.ADDIC7ED_USER, 'password': sickrage.ADDIC7ED_PASS}, 'legendastv': {'username': sickrage.LEGENDASTV_USER, 'password': sickrage.LEGENDASTV_PASS}, 'opensubtitles': {'username': sickrage.OPENSUBTITLES_USER, 'password': sickrage.OPENSUBTITLES_PASS}} pool = subliminal.api.ProviderPool(providers=providers, provider_configs=provider_configs) try: subtitles_list = pool.list_subtitles(video, languages) if not subtitles_list: sickrage.LOGGER.debug('%s: No subtitles found for S%02dE%02d on any provider' % ( subtitles_info[b'show.indexerid'], subtitles_info[b'season'], subtitles_info[b'episode'])) return existing_subtitles, None found_subtitles = pool.download_best_subtitles(subtitles_list, video, languages=languages, hearing_impaired=sickrage.SUBTITLES_HEARING_IMPAIRED, only_one=not sickrage.SUBTITLES_MULTI) save_subtitles(video, found_subtitles, directory=subtitles_path, single=not sickrage.SUBTITLES_MULTI) if not sickrage.EMBEDDED_SUBTITLES_ALL and sickrage.SUBTITLES_EXTRA_SCRIPTS and video_path.endswith( ('.mkv', '.mp4')): run_subs_extra_scripts(subtitles_info, found_subtitles, video, single=not sickrage.SUBTITLES_MULTI) current_subtitles = subtitlesLanguages(video_path)[0] new_subtitles = frozenset(current_subtitles).difference(existing_subtitles) except Exception: sickrage.LOGGER.info("Error occurred when downloading subtitles for: %s" % video_path) sickrage.LOGGER.error(traceback.format_exc()) return existing_subtitles, None if sickrage.SUBTITLES_HISTORY: for subtitle in found_subtitles: sickrage.LOGGER.debug('history.logSubtitle %s, %s' % (subtitle.provider_name, subtitle.language.opensubtitles)) History.logSubtitle(subtitles_info[b'show.indexerid'], subtitles_info[b'season'], subtitles_info[b'episode'], subtitles_info[b'status'], subtitle) return current_subtitles, new_subtitles
def get_video(video_path, subtitles_path=None, subtitles=True, embedded_subtitles=None, episode=None): if not subtitles_path: subtitles_path = get_subtitles_path(video_path) try: video = subliminal.scan_video(video_path) # external subtitles if subtitles: video.subtitle_languages |= \ set(subliminal.core.search_external_subtitles(video_path, directory=subtitles_path).values()) if embedded_subtitles is None: embedded_subtitles = bool( not sickrage.app.config.embedded_subtitles_all and video_path.endswith('.mkv')) # Let sickrage add more information to video file, based on the metadata. if episode: refine_video(video, episode) subliminal.refine(video, embedded_subtitles=embedded_subtitles) except Exception as error: sickrage.app.log.debug('Exception: {}'.format(error)) return None # remove format metadata video.format = "" return video
def import_subs(filename): if not core.GETSUBS: return try: subliminal.cache_region.configure('dogpile.cache.memory') except: pass languages = set() for item in core.SLANGUAGES: try: languages.add(Language(item)) except: pass if not languages: return logger.debug("Attempting to download subtitles for %s" % (filename), 'SUBTITLES') try: video = subliminal.scan_video(filename, subtitles=True, embedded_subtitles=True) subtitles = subliminal.download_best_subtitles([video], languages, hearing_impaired=False) subliminal.save_subtitles(subtitles) except Exception as e: logger.error( "Failed to download subtitles for %s due to: %s" % (filename, e), 'SUBTITLES')
def import_subs(filename): if not core.GETSUBS: return try: subliminal.cache_region.configure('dogpile.cache.memory') except: pass languages = set() for item in core.SLANGUAGES: try: languages.add(Language(item)) except: pass if not languages: return logger.debug("Attempting to download subtitles for %s" %(filename), 'SUBTITLES') try: # subliminal.logger = subliminal.logging.getLogger('subliminal') # subliminal.logger.setLevel(subliminal.logging.DEBUG) # ch = subliminal.logging.StreamHandler() # ch.setLevel(subliminal.logging.DEBUG) # formatter = subliminal.logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # ch.setFormatter(formatter) # subliminal.logger.addHandler(ch) video = subliminal.scan_video(filename, subtitles=True, embedded_subtitles=True) subtitles = subliminal.download_best_subtitles([video], languages, hearing_impaired=False) saved_subtitles = subliminal.save_subtitles(video, subtitles[video]) logger.debug("Saved subtitles:%s" %(saved_subtitles), 'SUBTITLES') except Exception as e: logger.error("Failed to download subtitles for %s due to: %s" %(filename, e), 'SUBTITLES')
def get_video(video_path, subtitles_path=None, subtitles=True, embedded_subtitles=None, episode=None): if not subtitles_path: subtitles_path = get_subtitles_path(video_path) try: # Encode paths to UTF-8 to ensure subliminal support. video_path = video_path.encode('utf-8') subtitles_path = subtitles_path.encode('utf-8') except UnicodeEncodeError: # Fallback to system encoding. This should never happen. video_path = video_path.encode(sickrage.srCore.SYS_ENCODING) subtitles_path = subtitles_path.encode(sickrage.srCore.SYS_ENCODING) try: video = subliminal.scan_video(video_path) # external subtitles if subtitles: video.subtitle_languages |= \ set(subliminal.core.search_external_subtitles(video_path, directory=subtitles_path).values()) if embedded_subtitles is None: embedded_subtitles = bool( not sickrage.srCore.srConfig.EMBEDDED_SUBTITLES_ALL and video_path.endswith('.mkv')) # Let sickrage add more information to video file, based on the metadata. if episode: refine_video(video, episode) subliminal.refine(video, embedded_subtitles=embedded_subtitles) except Exception as error: sickrage.srCore.srLogger.debug('Exception: {}'.format(error)) return None return video
def _scan_wanted_item_for_video(wanted_item, is_manual=False): video_path = wanted_item.videopath log.info('Scanning video') try: # Scan the video video = subliminal.scan_video(video_path) # Use our manual refiner only for manual search if enabled # Always keep this first because you may completely override the video with this! if is_manual and autosubliminal.MANUALREFINEVIDEO: refiners = ('manual',) # don't remove the , -> needs to be a tuple subliminal.refine(video, episode_refiners=refiners, movie_refiners=refiners, wanted_item=wanted_item) # Use build-in refiners if autosubliminal.REFINEVIDEO: subliminal.refine(video) # Use our namemapping refiner (always enabled to enable our name mappings) # This should always be at the end since we want to enrich the result after the build-in refiners refiners = ('namemapping',) # don't remove the , -> needs to be a tuple subliminal.refine(video, episode_refiners=refiners, movie_refiners=refiners) except Exception: log.exception('Error while scanning video, skipping %s', video_path) return # Add video to wanted item wanted_item.video = video return video
def download(self, model): """Download subtitles using subliminal""" video = subliminal.scan_video(model.series_path) subtitles = subliminal.download_best_subtitles( {video}, {Language('eng')}, ) save_subtitles(subtitles, True, config.download_path)
def test_scan_video_subtitles_languages(self): video = EPISODES[0] open(os.path.join(TEST_DIR, os.path.splitext(os.path.split(video.name)[1])[0]) + '.en.srt', 'w').close() open(os.path.join(TEST_DIR, os.path.splitext(os.path.split(video.name)[1])[0]) + '.fr.srt', 'w').close() open(os.path.join(TEST_DIR, os.path.splitext(os.path.split(video.name)[1])[0]) + '.srt', 'w').close() scanned_video = scan_video(os.path.join(TEST_DIR, os.path.split(video.name)[1])) self.assertEqual(scanned_video.subtitle_languages, {Language('eng'), Language('fra'), Language('und')})
def get_subtitles(self, entry): if ( entry.get('subtitles', eval_lazy=False) or not ('location' in entry) or ('$RECYCLE.BIN' in entry['location']) or not os.path.exists(entry['location']) ): return from subliminal import scan_video from subliminal.core import search_external_subtitles, refine try: video = scan_video(entry['location']) # grab external and internal subtitles subtitles = video.subtitle_languages refiner = ('metadata',) refine(video, episode_refiners=refiner, movie_refiners=refiner) subtitles |= set(search_external_subtitles(entry['location']).values()) if subtitles: # convert to human-readable strings subtitles = [str(l) for l in subtitles] entry['subtitles'] = subtitles log.debug('Found subtitles %s for %s', '/'.join(subtitles), entry['title']) except Exception as e: log.error('Error checking local subtitles for %s: %s', entry['title'], e)
def getSubtitle(self): if not "sub" in self.config or not os.path.isfile(self.config['sub']): self.config['sub'] = {} name = os.path.splitext(self.config['file']['name'])[0] file = os.path.join(self.config['file']['path'], name + ".srt") if os.path.isfile(file): print "found file. copying to temp" shutil.copy(file, self.config['temp']['path']) self.config['sub']['file'] = os.path.join(self.config['temp']['path'], name + ".srt") self.config['sub']['lang'] = self.config['language']['subtitle'][0] else: print "trying to download subtitle" file = self.config['file']['name'] lang = self.config['language']['subtitle'] languages = set(); for l in lang: languages.add(Language(l)) print languages videoPath = os.path.join(self.config['temp']['path'], file) video = set([subliminal.scan_video(videoPath)]) print video cache = self.config['temp']['path'] if "temp" in self.config else self.config['file']['path'] sub = subliminal.download_best_subtitles(video, languages) print sub.items() if not sub.items(): self.config['sub'] = False for item in sub.items(): subLang = item[1][0].language.alpha3 self.config['sub'][subLang] = {} self.config['sub'][subLang]['lang'] = subLang self.config['sub'][subLang]['file'] = subliminal.subtitle.get_subtitle_path(videoPath, Language(subLang)) print self.config['sub'] return self.config['sub']
def get_video(video_path, subtitles_path=None, subtitles=True, embedded_subtitles=None, episode=None): if not subtitles_path: subtitles_path = get_subtitles_path(video_path) try: video = subliminal.scan_video(video_path) # external subtitles if subtitles: video.subtitle_languages |= set( subliminal.core.search_external_subtitles( video_path, directory=subtitles_path).values()) if embedded_subtitles is None: embedded_subtitles = bool(not settings.EMBEDDED_SUBTITLES_ALL and video_path.endswith(".mkv")) # Let sickchill add more information to video file, based on the metadata. if episode: refine_video(video, episode) subliminal.refine(video, embedded_subtitles=embedded_subtitles) except Exception as error: logger.info(traceback.format_exc()) logger.debug("Exception: {0}".format(error)) return None return video
def get_subtitles(self, entry): if (entry.get('subtitles', eval_lazy=False) or not ('location' in entry) or ('$RECYCLE.BIN' in entry['location']) or not os.path.exists(entry['location'])): return from subliminal import scan_video from subliminal.core import search_external_subtitles, refine try: video = scan_video(entry['location']) # grab external and internal subtitles subtitles = video.subtitle_languages refiner = ('metadata', ) refine(video, episode_refiners=refiner, movie_refiners=refiner) subtitles |= set( search_external_subtitles(entry['location']).values()) if subtitles: # convert to human-readable strings subtitles = [str(l) for l in subtitles] entry['subtitles'] = subtitles log.debug('Found subtitles %s for %s', '/'.join(subtitles), entry['title']) except Exception as e: log.error('Error checking local subtitles for %s: %s', entry['title'], e)
def get_video(self, video_path, subtitles_path=None, subtitles=True, embedded_subtitles=None, episode_object=None): if not subtitles_path: subtitles_path = self.get_subtitles_path(video_path) try: video = subliminal.scan_video(video_path) except Exception as error: sickrage.app.log.debug('Exception: {}'.format(error)) else: if video.size > 10485760: video.hashes['itasa'] = hash_itasa(video_path) # external subtitles if subtitles: video.subtitle_languages |= set(subliminal.core.search_external_subtitles(video_path, directory=subtitles_path).values()) if embedded_subtitles is None: embedded_subtitles = bool( not sickrage.app.config.embedded_subtitles_all and video_path.endswith('.mkv')) subliminal.refine(video, episode_refiners=self.episode_refiners, embedded_subtitles=embedded_subtitles, release_name=episode_object.name, tv_episode=episode_object) from sickrage.core.scene_exceptions import get_scene_exceptions video.alternative_series = list(get_scene_exceptions(episode_object.show.indexer_id)) # remove format metadata video.format = "" return video
def get_video(video_path, subtitles_path=None, subtitles=True, embedded_subtitles=None, episode=None): if not subtitles_path: subtitles_path = get_subtitles_path(video_path) try: video = subliminal.scan_video(video_path) except Exception as error: sickrage.app.log.debug('Exception: {}'.format(error)) else: if video.size > 10485760: video.hashes['itasa'] = hash_itasa(video_path) # external subtitles if subtitles: video.subtitle_languages |= \ set(subliminal.core.search_external_subtitles(video_path, directory=subtitles_path).values()) if embedded_subtitles is None: embedded_subtitles = bool( not sickrage.app.config.embedded_subtitles_all and video_path.endswith('.mkv')) subliminal.refine(video, episode_refiners=episode_refiners, embedded_subtitles=embedded_subtitles, release_name=episode.name, tv_episode=episode) video.alternative_series = list(get_scene_exceptions(episode.show.indexerid)) # remove format metadata video.format = "" return video
def getsrt(source, srcPath=watchPath): try: video = scan_video(source) videos = [video] logging.debug(prelog + 'getting subtitles') subtitles = download_best_subtitles( videos, {Language('eng'), Language('fra')}, providers=None, provider_configs={ 'addic7ed': { 'username': '******', 'password': '******' }, 'opensubtitles': { 'username': '******', 'password': '******' } }) sourceDir = os.path.dirname(source) savePath = sourceDir.replace(srcPath, srtPath) if not os.path.isdir(savePath): logging.debug(prelog + 'creating srt directory ' + savePath) os.makedirs(savePath) save_subtitles(video, subtitles[video], directory=savePath) except: logging.exception(prelog) pass
def on_task_output(self, task, config): """ Configuration:: subliminal: languages: List of languages (3-letter ISO-639-3 code) in order of preference. At least one is required. alternatives: List of second-choice languages; subs will be downloaded but entries rejected. exact_match: Use file hash only to search for subs, otherwise Subliminal will try to guess by filename. """ if not task.accepted: log.debug('nothing accepted, aborting') return from babelfish import Language from dogpile.cache.exception import RegionAlreadyConfigured import subliminal try: subliminal.cache_region.configure('dogpile.cache.dbm', arguments={ 'filename': os.path.join( tempfile.gettempdir(), 'cachefile.dbm'), 'lock_factory': subliminal.MutexLock }) except RegionAlreadyConfigured: pass logging.getLogger("subliminal").setLevel(logging.CRITICAL) logging.getLogger("enzyme").setLevel(logging.WARNING) langs = set([Language(s) for s in config['languages']]) alts = set([Language(s) for s in config.get('alternatives', [])]) for entry in task.accepted: if not 'location' in entry: log.warning( 'Cannot act on entries that do not represent a local file.' ) elif not os.path.exists(entry['location']): entry.fail('file not found: %s' % entry['location']) elif not '$RECYCLE.BIN' in entry[ 'location']: # ignore deleted files in Windows shares try: video = subliminal.scan_video(entry['location']) msc = video.scores['hash'] if config['exact_match'] else 0 if langs & video.subtitle_languages: continue # subs for preferred lang(s) already exists elif subliminal.download_best_subtitles([video], langs, min_score=msc): log.info('Subtitles found for %s' % entry['location']) elif alts and (alts - video.subtitle_languages) and \ subliminal.download_best_subtitles([video], alts, min_score=msc): entry.fail( 'subtitles found for a second-choice language.') else: entry.fail('cannot find any subtitles for now.') except Exception as err: # don't want to abort the entire task for errors in a # single video file or for occasional network timeouts log.debug(err.message) entry.fail(err.message)
def choose_callback(self, menuitem, files): # scan the video video = scan_video(files[0].get_location().get_path()) refine(video, episode_refiners=self.config.refiners, movie_refiners=self.config.refiners, embedded_subtitles=False) # load the interface builder = Gtk.Builder() builder.set_translation_domain('subliminal') builder.add_from_file( os.path.join(os.path.dirname(__file__), 'subliminal', 'ui', 'choose.glade')) # set the video filename video_filename = builder.get_object('video_filename_label') video_filename.set_text(files[0].get_name()) # start the spinner spinner = builder.get_object('spinner') spinner.start() def _list_subtitles(): # list subtitles with AsyncProviderPool( providers=self.config.providers, provider_configs=self.config.provider_configs) as pool: subtitles = pool.list_subtitles(video, self.config.languages) # fill the subtitle liststore subtitle_liststore = builder.get_object('subtitle_liststore') for s in subtitles: scaled_score = compute_score(s, video) scores = get_scores(video) if s.hearing_impaired == self.config.hearing_impaired: scaled_score -= scores['hearing_impaired'] scaled_score *= 100 / scores['hash'] subtitle_liststore.append([ s.id, nice_language(s.language), scaled_score, s.provider_name.capitalize(), s.hearing_impaired, s.page_link, False ]) subtitle_liststore.set_sort_column_id(2, Gtk.SortType.DESCENDING) # stop the spinner spinner.stop() # connect signals builder.connect_signals( ChooseHandler(self.config, video, subtitles, spinner)) threading.Thread(target=_list_subtitles).start() # display window window = builder.get_object('subtitle_window') window.show_all() Gtk.main()
def downloadSubtitles(subtitles_info): existing_subtitles = subtitles_info['subtitles'] # First of all, check if we need subtitles languages = getNeededLanguages(existing_subtitles) if not languages: logger.log(u'%s: No missing subtitles for S%02dE%02d' % (subtitles_info['show.indexerid'], subtitles_info['season'], subtitles_info['episode']), logger.DEBUG) return (existing_subtitles, None) subtitles_path = getSubtitlesPath(subtitles_info['location']).encode(sickbeard.SYS_ENCODING) video_path = subtitles_info['location'].encode(sickbeard.SYS_ENCODING) providers = getEnabledServiceList() try: video = subliminal.scan_video(video_path, subtitles=False, embedded_subtitles=False) except Exception: logger.log(u'%s: Exception caught in subliminal.scan_video for S%02dE%02d' % (subtitles_info['show.indexerid'], subtitles_info['season'], subtitles_info['episode']), logger.DEBUG) return (existing_subtitles, None) try: # TODO: Add gui option for hearing_impaired parameter ? found_subtitles = subliminal.download_best_subtitles([video], languages=languages, hearing_impaired=False, only_one=not sickbeard.SUBTITLES_MULTI, providers=providers) if not found_subtitles: logger.log(u'%s: No subtitles found for S%02dE%02d on any provider' % (subtitles_info['show.indexerid'], subtitles_info['season'], subtitles_info['episode']), logger.DEBUG) return (existing_subtitles, None) for index, subtitle in enumerate(found_subtitles[video]): encoding = subliminal.subtitle.Subtitle.guess_encoding(subtitle) found_subtitles[video][index].encoding = encoding subliminal.save_subtitles(video, found_subtitles[video], directory=subtitles_path, single=not sickbeard.SUBTITLES_MULTI) for video, subtitles in found_subtitles.iteritems(): for subtitle in subtitles: new_video_path = subtitles_path + "/" + video.name.rsplit("/", 1)[-1] new_subtitles_path = subliminal.subtitle.get_subtitle_path(new_video_path, subtitle.language if sickbeard.SUBTITLES_MULTI else None) sickbeard.helpers.chmodAsParent(new_subtitles_path) sickbeard.helpers.fixSetGroupID(new_subtitles_path) if not sickbeard.EMBEDDED_SUBTITLES_ALL and sickbeard.SUBTITLES_EXTRA_SCRIPTS and video_path.endswith(('.mkv','.mp4')): run_subs_extra_scripts(subtitles_info, found_subtitles) current_subtitles = subtitlesLanguages(video_path)[0] new_subtitles = frozenset(current_subtitles).difference(existing_subtitles) except Exception as e: logger.log("Error occurred when downloading subtitles for: %s" % video_path) logger.log(traceback.format_exc(), logger.ERROR) return (existing_subtitles, None) if sickbeard.SUBTITLES_HISTORY: for video, subtitles in found_subtitles.iteritems(): for subtitle in subtitles: logger.log(u'history.logSubtitle %s, %s' % (subtitle.provider_name, subtitle.language.opensubtitles), logger.DEBUG) history.logSubtitle(subtitles_info['show.indexerid'], subtitles_info['season'], subtitles_info['episode'], subtitles_info['status'], subtitle) return (current_subtitles, new_subtitles)
def _get_video(filename): '''Return the subliminal.Video object from the given filename''' if os.path.exists(filename): logger.info('File `%s\' exists, parsing file contents', filename) return subliminal.scan_video(filename) else: logger.info('File `%s\' does not exist, parsing filename only', filename) return subliminal.Video.fromname(filename)
def download_callback(self, menuitem, files): # scan videos videos = [] for f in files: # ignore non-writable locations if not f.can_write(): continue # directories if f.is_directory(): try: scanned_videos = scan_videos( f.get_location().get_path(), subtitles=True, embedded_subtitles=self.config.embedded_subtitles) except: continue for video in scanned_videos: if check_video(video, languages=self.config.languages, age=self.config.age, undefined=self.config.single): videos.append(video) continue # other inputs try: video = scan_video( f.get_location().get_path(), subtitles=True, embedded_subtitles=self.config.embedded_subtitles) except: continue if check_video(video, languages=self.config.languages, undefined=self.config.single): videos.append(video) # download best subtitles downloaded_subtitles = defaultdict(list) with ProviderPool( providers=self.config.providers, provider_configs=self.config.provider_configs) as pool: for v in videos: subtitles = pool.download_best_subtitles( pool.list_subtitles( v, self.config.languages - v.subtitle_languages), v, self.config.languages, min_score=v.scores['hash'] * self.config.min_score / 100, hearing_impaired=self.config.hearing_impaired, only_one=self.config.single) downloaded_subtitles[v] = subtitles # save subtitles for v, subtitles in downloaded_subtitles.items(): save_subtitles(v, subtitles, single=self.config.single)
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 get_video(tv_episode, video_path, subtitles_dir=None, subtitles=True, embedded_subtitles=None, release_name=None): """Return the subliminal video for the given path. The video_path is used as a key to cache the video to avoid scanning and parsing the video metadata all the time :param tv_episode: :type tv_episode: medusa.tv.Episode :param video_path: the video path :type video_path: str :param subtitles_dir: the subtitles directory :type subtitles_dir: str or None :param subtitles: True if existing external subtitles should be taken into account :type subtitles: bool or None :param embedded_subtitles: True if embedded subtitles should be taken into account :type embedded_subtitles: bool or None :param release_name: the release name :type release_name: str or None :return: video :rtype: subliminal.video.Video """ key = video_key.format(video_path=video_path) payload = {'subtitles_dir': subtitles_dir, 'subtitles': subtitles, 'embedded_subtitles': embedded_subtitles, 'release_name': release_name} cached_payload = memory_cache.get(key, expiration_time=VIDEO_EXPIRATION_TIME) if cached_payload != NO_VALUE and {k: v for k, v in iteritems(cached_payload) if k != 'video'} == payload: logger.debug(u'Found cached video information under key %s', key) return cached_payload['video'] video_is_mkv = video_path.endswith('.mkv') subtitles_dir = subtitles_dir or get_subtitles_dir(video_path) logger.debug(u'Scanning video %s...', video_path) try: video = scan_video(video_path) except ValueError as error: logger.warning(u'Unable to scan video: %s. Error: %r', video_path, error) else: if subtitles: video.subtitle_languages |= set(search_external_subtitles(video_path, directory=subtitles_dir).values()) if embedded_subtitles is None: embedded_subtitles = bool(not app.IGNORE_EMBEDDED_SUBS and video_is_mkv) refine(video, episode_refiners=episode_refiners, embedded_subtitles=embedded_subtitles, release_name=release_name, tv_episode=tv_episode) video.alternative_series = [alias.title for alias in tv_episode.series.aliases] payload['video'] = video memory_cache.set(key, payload) logger.debug(u'Video information cached under key %s', key) return video
def test_scan_video_subtitles_language_eng(self): video = EPISODES[0] open( os.path.join(TEST_DIR, os.path.splitext(os.path.split(video.name)[1])[0]) + '.en.srt', 'w').close() scanned_video = scan_video( os.path.join(TEST_DIR, os.path.split(video.name)[1])) self.assertEqual(scanned_video.subtitle_languages, {Language('eng')})
def moveVideosAndSubtitles(sourceDirPath_, destDirPath_) : """Move videos and subtitles (if exist) :param String sourceDirPath_ :param String destDirPath_ """ LOGGER.info('*** START MOVING VIDEOS AND SUBTITLES ***') if (os.path.isdir(sourceDirPath_)) : for dir, dirs, files in os.walk(sourceDirPath_) : localDir = dir[len(sourceDirPath_):] for fileName in files : fileExtension = os.path.splitext(fileName)[1] filePath = os.path.join(dir, fileName) if (fileExtension in VIDEO_EXTENSIONS) : # Scan video LOGGER.debug('Scanning video \'%s\'', filePath) video = subliminal.scan_video(filePath, False, True) # TEMP: if no embedded subtitles have been found, try to find associated sub files # This should be done in 'subliminal.scan_video', but... NO. # TODO: fork subliminal to fix the method 'scan_subtitle_languages' subFileLanguages = subtitles.scanSubtitleLanguages(filePath, SUB_EXTENSIONS) # If subs found, then move video hasSubFiles = babelfish.Language('eng') in subFileLanguages hasEmbeddedSub = babelfish.Language('eng') in video.subtitle_languages or babelfish.Language('und') in video.subtitle_languages if (hasEmbeddedSub or hasSubFiles) : fileTools.transferFile(filePath, sourceDirPath_, destDirPath_) # Embedded subtitles? if (hasEmbeddedSub) : LOGGER.debug('Embedded subtitles found for %s', video.name) # If subtitles files have been found, then move if (hasSubFiles) : LOGGER.debug('Subtitles files found for %s', video.name) # Move subtitles for otherFileName in files : otherFileExtension = os.path.splitext(otherFileName)[1] if (not otherFileName == fileName and otherFileExtension in SUB_EXTENSIONS) : # Test if the subtitles have the same name as the movie otherFileRoot = os.path.splitext(otherFileName)[0] fileRoot = os.path.splitext(fileName)[0] if (otherFileRoot[:len(fileRoot)] == fileRoot) : # Move subtitles otherFilePath = os.path.join(dir, otherFileName) fileTools.transferFile(otherFilePath, sourceDirPath_, destDirPath_) else : LOGGER.warning('No subtitles found, skipping video. (%s)', video.name) else : LOGGER.warning('\'%s\' does not refer to an existing path.', sourceDirPath_)
def get_best_match(self, widget): # Open a thread to find a subtitle through get_best_subtitle try: self.video = scan_video( self.movie_entry.get_text() ) except ValueError: self.status_bar.pop(self.context_id) self.status_bar.push(self.context_id, "Error. Did you choose a video file?") self.progress_bar.set_fraction(0) return False x = Thread(target=self.get_best_subtitle) x.start()
def get_embedded_subtitles(video_path): """Return all embedded subtitles for the given video path. :param video_path: video filename to be checked :type video_path: str :return: :rtype: set of Language """ subliminal_video = scan_video(video_path) refine(subliminal_video, episode_refiners=('metadata', )) return subliminal_video.subtitle_languages
def get_embedded_subtitles(video_path): """Return all embedded subtitles for the given video path. :param video_path: video filename to be checked :type video_path: str :return: :rtype: set of Language """ subliminal_video = scan_video(video_path) refine(subliminal_video, episode_refiners=('metadata',)) return subliminal_video.subtitle_languages
def download_sub(self, lang='eng'): prov_conf = {'opensubtitles': {'username': '******', 'password': '******'}} logging.info("{}: Downloading subtitles...".format(self.filename)) vid = scan_video(self.path) best_subs = download_best_subtitles({vid}, {babelfish.Language(lang)}, only_one=True, provider_configs=prov_conf) if best_subs[vid]: sub = best_subs[vid][0] save_subtitles(vid, [sub], single=True) logging.info("{}: Subtitles successfully downloaded.".format(self.filename)) else: logging.error("{}: No subtitles found online.".format(self.filename))
def get_video(tv_episode, video_path, subtitles_dir=None, subtitles=True, embedded_subtitles=None, release_name=None): """Return the subliminal video for the given path. The video_path is used as a key to cache the video to avoid scanning and parsing the video metadata all the time :param tv_episode: :type tv_episode: sickbeard.tv.TVEpisode :param video_path: the video path :type video_path: str :param subtitles_dir: the subtitles directory :type subtitles_dir: str or None :param subtitles: True if existing external subtitles should be taken into account :type subtitles: bool or None :param embedded_subtitles: True if embedded subtitles should be taken into account :type embedded_subtitles: bool or None :param release_name: the release name :type release_name: str or None :return: video :rtype: subliminal.video.Video """ key = video_key.format(video_path=video_path) payload = {'subtitles_dir': subtitles_dir, 'subtitles': subtitles, 'embedded_subtitles': embedded_subtitles, 'release_name': release_name} cached_payload = region.get(key, expiration_time=VIDEO_EXPIRATION_TIME) if cached_payload != NO_VALUE and {k: v for k, v in iteritems(cached_payload) if k != 'video'} == payload: logger.debug(u'Found cached video information under key %s', key) return cached_payload['video'] try: video_path = _encode(video_path) subtitles_dir = _encode(subtitles_dir or get_subtitles_dir(video_path)) logger.debug(u'Scanning video %s...', video_path) video = scan_video(video_path) # external subtitles if subtitles: video.subtitle_languages |= set(search_external_subtitles(video_path, directory=subtitles_dir).values()) if embedded_subtitles is None: embedded_subtitles = bool(not sickbeard.EMBEDDED_SUBTITLES_ALL and video_path.endswith('.mkv')) refine(video, episode_refiners=episode_refiners, embedded_subtitles=embedded_subtitles, release_name=release_name, tv_episode=tv_episode) payload['video'] = video region.set(key, payload) logger.debug(u'Video information cached under key %s', key) return video except Exception as error: logger.info(u'Exception: %s', error)
def get_best_match(self, widget): # Open a thread to find a subtitle through get_best_subtitle try: self.video = scan_video(self.movie_entry.get_text()) except ValueError: self.status_bar.pop(self.context_id) self.status_bar.push(self.context_id, "Error. Did you choose a video file?") self.progress_bar.set_fraction(0) return False x = Thread(target=self.get_best_subtitle) x.start()
def get_video(video_path, subtitles_path=None): if not subtitles_path: try: subtitles_path = get_subtitles_path(video_path).encode(sickbeard.SYS_ENCODING) except UnicodeEncodeError as error: logger.log(u'An error occurred while encoding \'{}\' with your current locale. ' 'Rename the file or try a different locale. Error: {}'.format (video_path, ex(error)), logger.WARNING) return None try: if not sickbeard.EMBEDDED_SUBTITLES_ALL and video_path.endswith('.mkv'): video = subliminal.scan_video(video_path, subtitles=True, embedded_subtitles=True, subtitles_dir=subtitles_path) else: video = subliminal.scan_video(video_path, subtitles=True, embedded_subtitles=False, subtitles_dir=subtitles_path) except Exception: return None return video
def find_file_subtitles(path): """ Finds subtitles for the given video file path. :param path: The path of the video file to find subtitles to. :return: The list of subtitles file paths, or None if a problem occurred. """ logger.info('Searching subtitles for file: {}'.format(path)) try: # Get required video information. video = subliminal.scan_video(path) other_languages = [] subtitle_results = [] for language, providers in LANGUAGES_MAP.items(): # Filter providers the user didn't ask for. if not providers: other_languages.append(language) else: current_result = subliminal.download_best_subtitles( {video}, languages={language}, providers=providers).values() if len(current_result) > 0: subtitle_results.extend(list(current_result)[0]) # Download all other languages. for language in other_languages: current_result = subliminal.download_best_subtitles( {video}, languages={language}).values() if len(current_result) > 0: subtitle_results.extend(list(current_result)[0]) # Handle results. if len(subtitle_results) == 0: logger.info('No subtitles were found. Moving on...') else: logger.info('Found {} subtitles. Saving files...'.format( len(subtitle_results))) # Save subtitles alongside the video file. results_list = list() for subtitles in subtitle_results: # Filter empty subtitles files. if subtitles.content is None: logger.debug( 'Skipping subtitle {}: no content'.format(subtitles)) continue subtitles_path = get_subtitle_path(video.name, subtitles.language) logger.info('Saving {} to: {}'.format(subtitles, subtitles_path)) open(subtitles_path, 'wb').write(subtitles.content) results_list.append(subtitles_path) return results_list except ValueError: # Subliminal raises a ValueError if the given file is not a video file. logger.info('Not a video file. Moving on...')
def on_task_output(self, task, config): """ Configuration:: subliminal: languages: List of languages (3-letter ISO-639-3 code) in order of preference. At least one is required. alternatives: List of second-choice languages; subs will be downloaded but entries rejected. exact_match: Use file hash only to search for subs, otherwise Subliminal will try to guess by filename. """ if not task.accepted: log.debug('nothing accepted, aborting') return from babelfish import Language from dogpile.cache.exception import RegionAlreadyConfigured import subliminal try: subliminal.cache_region.configure('dogpile.cache.dbm', arguments={'filename': os.path.join(tempfile.gettempdir(), 'cachefile.dbm'), 'lock_factory': subliminal.MutexLock}) except RegionAlreadyConfigured: pass logging.getLogger("subliminal").setLevel(logging.CRITICAL) logging.getLogger("enzyme").setLevel(logging.WARNING) langs = set([Language(s) for s in config['languages']]) alts = set([Language(s) for s in config.get('alternatives', [])]) for entry in task.accepted: if not 'location' in entry: log.warning('Cannot act on entries that do not represent a local file.') elif not os.path.exists(entry['location']): entry.fail('file not found: %s' % entry['location']) elif not '$RECYCLE.BIN' in entry['location']: # ignore deleted files in Windows shares try: video = subliminal.scan_video(entry['location']) msc = video.scores['hash'] if config['exact_match'] else 0 if langs & video.subtitle_languages: continue # subs for preferred lang(s) already exists elif subliminal.download_best_subtitles([video], langs, min_score=msc): log.info('Subtitles found for %s' % entry['location']) elif alts and (alts - video.subtitle_languages) and \ subliminal.download_best_subtitles([video], alts, min_score=msc): entry.fail('subtitles found for a second-choice language.') else: entry.fail('cannot find any subtitles for now.') except Exception as err: # don't want to abort the entire task for errors in a # single video file or for occasional network timeouts if err.args: msg = err.args[0] else: # Subliminal errors don't always have a message, just use the name msg = 'subliminal error: %s' % err.__class__.__name__ log.debug(msg) entry.fail(msg)
def get_subtitles(self, entry): if entry.get('subtitles', eval_lazy=False) or not ('location' in entry) or \ ('$RECYCLE.BIN' in entry['location']) or not os.path.exists(entry['location']): return import subliminal try: video = subliminal.scan_video(entry['location']) lst = [l.alpha3 for l in video.subtitle_languages] if lst: entry['subtitles'] = lst log.trace('Found subtitles %s for %s' % ('/'.join(lst), entry['title'])) except Exception as e: log.debug('Error checking local subtitles for %s: %s' % (entry['title'], e))
def choose_callback(self, menuitem, files): # scan and check the video video = scan_video(files[0].get_location().get_path(), subtitles=True, embedded_subtitles=self.config.embedded_subtitles) if not check_video(video, languages=self.config.languages, undefined=self.config.single): return # list subtitles with ProviderPool( providers=self.config.providers, provider_configs=self.config.provider_configs) as pool: subtitles = pool.list_subtitles(video, self.config.languages) # load the interface builder = Gtk.Builder() builder.set_translation_domain('subliminal') builder.add_from_file( os.path.join(os.path.dirname(__file__), 'subliminal', 'ui', 'choose.glade')) # set the video filename video_filename = builder.get_object('video_filename_label') video_filename.set_text(files[0].get_name()) # fill the subtitle liststore subtitle_liststore = builder.get_object('subtitle_liststore') for s in subtitles: matches = s.get_matches( video, hearing_impaired=self.config.hearing_impaired) scaled_score = compute_score(matches, video) if s.hearing_impaired == self.config.hearing_impaired: scaled_score -= video.scores['hearing_impaired'] scaled_score *= 100 / video.scores['hash'] subtitle_liststore.append([ s.id, nice_language(s.language), scaled_score, s.provider_name.capitalize(), s.hearing_impaired, s.page_link, False ]) subtitle_liststore.set_sort_column_id(2, Gtk.SortType.DESCENDING) # connect signals builder.connect_signals(ChooseHandler(self.config, video, subtitles)) # display window window = builder.get_object('subtitle_window') window.show_all() Gtk.main()
def test_scan_video_movie(self): video = MOVIES[0] scanned_video = scan_video(os.path.join(TEST_DIR, os.path.split(video.name)[1])) self.assertEqual(scanned_video.name, os.path.join(TEST_DIR, os.path.split(video.name)[1])) self.assertEqual(scanned_video.title.lower(), video.title.lower()) self.assertEqual(scanned_video.year, video.year) self.assertEqual(scanned_video.video_codec, video.video_codec) self.assertEqual(scanned_video.resolution, video.resolution) self.assertEqual(scanned_video.release_group, video.release_group) self.assertEqual(scanned_video.subtitle_languages, set()) self.assertEqual(scanned_video.hashes, {}) self.assertIsNone(scanned_video.audio_codec) self.assertIsNone(scanned_video.imdb_id) self.assertEqual(scanned_video.size, 0)
def mixAndMove(_cls, sourceDirPath_, destDirPath_) : LOGGER.info('*** START MIXING VIDEOS ***') if (os.path.isdir(sourceDirPath_)) : for dir, dirs, files in os.walk(sourceDirPath_) : localDir = dir[len(sourceDirPath_):] for fileName in files : fileExtension = os.path.splitext(fileName)[1] filePath = os.path.join(dir, fileName) if (fileExtension in VIDEO_EXTENSIONS) : # Scan video LOGGER.debug('Scanning video \'%s\'', filePath) video = subliminal.scan_video(filePath, False, True) # TEMP: if no embedded subtitles have been found, try to find associated sub files # This should be done in 'subliminal.scan_video', but... NO. # TODO: fork subliminal to fix the method 'scan_subtitle_languages' subFileLanguages = subtitles.scanSubtitleLanguages(filePath, SUB_EXTENSIONS) # If subs found, then move video hasSubFiles = babelfish.Language('eng') in subFileLanguages hasEmbeddedSub = babelfish.Language('eng') in video.subtitle_languages if hasEmbeddedSub : LOGGER.debug('%s has already embedded subtitles, skip mixing' % fileName) fileTools.transferFile(filePath, sourceDirPath_, destDirPath_) elif hasSubFiles : LOGGER.debug('Subtitles files found for %s', video.name) # Find all subtitles files subFiles = [] for otherFileName in files : otherFileExtension = os.path.splitext(otherFileName)[1] if (not otherFileName == fileName and otherFileExtension in SUB_EXTENSIONS) : # Test if the subtitles have the same name as the movie otherFileRoot = os.path.splitext(otherFileName)[0] fileRoot = os.path.splitext(fileName)[0] if (otherFileRoot[:len(fileRoot)] == fileRoot) : # Move subtitles otherFilePath = os.path.join(dir, otherFileName) subFiles.append(otherFilePath) assert len(subFiles) > 0 MkvMixer.mixVideo(filePath, subFiles) fileTools.transferFile(filePath, sourceDirPath_, destDirPath_) # TODO: remove this when mixing is done for subFilePath in subFiles : fileTools.transferFile(subFilePath, sourceDirPath_, destDirPath_) else : LOGGER.debug('%s has already embedded subtitles, skip mixing' % fileName) else : LOGGER.warning('\'%s\' does not refer to an existing path.', sourceDirPath_)
def _scan_wanted_item_for_video(wanted_item): originalfile = wanted_item['originalFileLocationOnDisk'] log.debug("Scanning the wanted item for a video: %s" % originalfile) # Scan the video (disable scan for subtitles) # With subtitle scan enabled, enzyme looks inside for embedded subtitles # When an 'UND' subtitle language is found (f.e. Grimm.S03E04.720p.WEB-DL.DD5.1.H.264-ECI), # no other subtitles will be downloaded when using subliminal.download_best_subtitles(..., single=True) try: video = subliminal.scan_video(originalfile, subtitles=False, embedded_subtitles=False) except Exception, e: log.error("Error while scanning video, skipping %s" % originalfile) log.error("Exception: %s" % e) return
def choose_callback(self, menuitem, files): # scan the video video = scan_video(files[0].get_location().get_path()) refine(video, episode_refiners=self.config.refiners, movie_refiners=self.config.refiners, embedded_subtitles=False) # load the interface builder = Gtk.Builder() builder.set_translation_domain('subliminal') builder.add_from_file(os.path.join(os.path.dirname(__file__), 'subliminal', 'ui', 'choose.glade')) # set the video filename video_filename = builder.get_object('video_filename_label') video_filename.set_text(files[0].get_name()) # start the spinner spinner = builder.get_object('spinner') spinner.start() def _list_subtitles(): # list subtitles with AsyncProviderPool(providers=self.config.providers, provider_configs=self.config.provider_configs) as pool: subtitles = pool.list_subtitles(video, self.config.languages) # fill the subtitle liststore subtitle_liststore = builder.get_object('subtitle_liststore') for s in subtitles: scaled_score = compute_score(s, video) scores = get_scores(video) if s.hearing_impaired == self.config.hearing_impaired: scaled_score -= scores['hearing_impaired'] scaled_score *= 100 / scores['hash'] subtitle_liststore.append([s.id, nice_language(s.language), scaled_score, s.provider_name.capitalize(), s.hearing_impaired, s.page_link, False]) subtitle_liststore.set_sort_column_id(2, Gtk.SortType.DESCENDING) # stop the spinner spinner.stop() # connect signals builder.connect_signals(ChooseHandler(self.config, video, subtitles, spinner)) threading.Thread(target=_list_subtitles).start() # display window window = builder.get_object('subtitle_window') window.show_all() Gtk.main()
def download_callback(self, menuitem, files): # scan videos videos = [] for f in files: # ignore non-writable locations if not f.can_write(): continue # directories if f.is_directory(): try: scanned_videos = scan_videos(f.get_location().get_path()) except: continue for video in scanned_videos: if check_video(video, languages=self.config.languages, age=self.config.age, undefined=self.config.single): video.subtitle_languages |= set(search_external_subtitles(video.name).values()) refine(video, episode_refiners=self.config.refiners, movie_refiners=self.config.refiners, embedded_subtitles=self.config.embedded_subtitles) videos.append(video) continue # other inputs try: video = scan_video(f.get_location().get_path()) except: continue if check_video(video, languages=self.config.languages, undefined=self.config.single): video.subtitle_languages |= set(search_external_subtitles(video.name).values()) refine(video, episode_refiners=self.config.refiners, movie_refiners=self.config.refiners, embedded_subtitles=self.config.embedded_subtitles) videos.append(video) # download best subtitles downloaded_subtitles = defaultdict(list) with AsyncProviderPool(providers=self.config.providers, provider_configs=self.config.provider_configs) as pool: for v in videos: scores = get_scores(v) subtitles = pool.download_best_subtitles( pool.list_subtitles(v, self.config.languages - v.subtitle_languages), v, self.config.languages, min_score=scores['hash'] * self.config.min_score / 100, hearing_impaired=self.config.hearing_impaired, only_one=self.config.single ) downloaded_subtitles[v] = subtitles # save subtitles for v, subtitles in downloaded_subtitles.items(): save_subtitles(v, subtitles, single=self.config.single)
def download_subs(file): print(" Analyzing video file...") try: video = scan_video(file['full_path']) except ValueError as ex: print(" Failed to analyze video. ", ex) return None print(" Choosing subtitle from online providers...") best_subtitles = download_best_subtitles({video}, {Language('eng')}, only_one=True) if best_subtitles[video]: sub = best_subtitles[video][0] print(" Choosen subtitle: {f}".format(f=sub)) print(" Downloading...") save_subtitles(video, [sub], single=True) else: print(" ERROR: No subtitles found online.")
def test_scan_video_episode(self): video = EPISODES[0] scanned_video = scan_video(os.path.join(TEST_DIR, os.path.split(video.name)[1])) self.assertEqual(scanned_video.name, os.path.join(TEST_DIR, os.path.split(video.name)[1])) self.assertEqual(scanned_video.series, video.series) self.assertEqual(scanned_video.season, video.season) self.assertEqual(scanned_video.episode, video.episode) self.assertEqual(scanned_video.video_codec, video.video_codec) self.assertEqual(scanned_video.resolution, video.resolution) self.assertEqual(scanned_video.release_group, video.release_group) self.assertEqual(scanned_video.subtitle_languages, set()) self.assertEqual(scanned_video.hashes, {}) self.assertIsNone(scanned_video.title) self.assertIsNone(scanned_video.tvdb_id) self.assertIsNone(scanned_video.imdb_id) self.assertIsNone(scanned_video.audio_codec) self.assertEqual(scanned_video.size, 0)
def moveAndRenameDownloadedVideos(sourceDirPath_, destDirPath_) : """Move all videos (movies and episodes) from the source path to the destination path, and rename them. :param String sourceDirPath_ :param String destDirPath_ """ LOGGER.info('*** START MOVING AND RENAMING DOWNLOADED VIDEOS ***') if (os.path.isdir(sourceDirPath_)) : # Parse all files for dir, dirs, files in os.walk(sourceDirPath_) : for fileName in files : # Retrieve paths fileExtension = os.path.splitext(fileName)[1] filePath = os.path.join(dir, fileName) if (fileExtension in VIDEO_EXTENSIONS) : # Create video instance LOGGER.debug('Scanning video file \'%s\'', filePath) video = subliminal.scan_video(filePath, True, True) print video # Specific action according to the type of video if (not video is None) : if (isinstance(video, subliminal.video.Episode)) : if (video.title is None) : db = api.TVDB("B43FF87DE395DF56") result = db.search(video.series, "en") for s in range(1, len(result[0])) : for e in range(1, len(result[0][s])+1) : print 'season ' + str(s) + 'episode ' + str(e) + ' ' + result[0][s][e].EpisodeName video.title = unicode(result[0][video.season][video.episode].EpisodeName) moveAndRenameEpisode(video, destDirPath_); elif (isinstance(video, subliminal.video.Movie)) : moveAndRenameMovie(video, destDirPath_); else : LOGGER.info('Bad video type, skipping file. (%s)', filePath) else : LOGGER.info('Bad extension, skipping file. (%s)', filePath) else : LOGGER.warning('\'%s\' does not refer to an existing path.', sourceDirPath_)