def test_replacing_video_for_path_removes_downloads(self): path = "/data/Series/Season 1/01 Title.mkv" video = Video.fromname("Series.S01E02.Title.720p.WEB-DL.DD5.1.H264-ReleaseGroup.mkv") self.datastore.add_video(path, video) provider = "davessubs" sub_id = "ABC123" lang = Language.fromietf("en") score = 123 self.datastore.add_download(path, provider, sub_id, lang, score) video2 = Video.fromname("Series.S01E02.Title.720p.BDRip-ReleaseGroup2.mkv") self.datastore.add_video(path, video) downloads = self.datastore.get_downloads_for_video(path) self.assertEqual(downloads, {})
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 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 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 test_added_subs_are_returned_by_lang(self): path = "/data/Series/Season 1/01 Title.mkv" video = Video.fromname("Series.S01E02.Title.720p.WEB-DL.DD5.1.H264-ReleaseGroup.mkv") self.datastore.add_video(path, video) provider1 = "davessubs" sub_id1 = "ABC123" lang1 = Language.fromietf("en") score1 = 123 provider2 = "stevesubs" sub_id2 = "steve123" lang2 = lang1 score2 = 120 provider3 = "pablosubs" sub_id3 = "umdoistres" lang3 = Language.fromietf("pt-BR") score3 = 150 self.datastore.add_download(path, provider1, sub_id1, lang1, score1) self.datastore.add_download(path, provider2, sub_id2, lang2, score2) self.datastore.add_download(path, provider3, sub_id3, lang3, score3) downloads = self.datastore.get_downloads_for_video(path) self.assertEqual( downloads, { lang1: [ {"provider": provider1, "sub_id": sub_id1, "lang": lang1, "score": score1}, {"provider": provider2, "sub_id": sub_id2, "lang": lang2, "score": score2}, ], lang3: [{"provider": provider3, "sub_id": sub_id3, "lang": lang3, "score": score3}], }, )
def data(): return { 'release_name': 'Show.Name.2012.S01E02.Episode.Title.1080p.HDTV.x265.AC3-Group', 'release_properties': { 'series': 'Show Name', 'season': 1, 'episode': 2, 'title': 'Episode Title', 'year': 2012, 'source': 'HDTV', 'resolution': '1080p', 'release_group': 'Group', 'video_codec': 'H.265', 'audio_codec': 'AC3' }, 'another_release_name': 'Different.Show.2013.S03E04.Another.Episode.720p.BluRay.x264-NoGroup', 'video': Video.fromname('Show.Name.S01E02.mkv'), 'video_properties': { 'series': 'Show Name', 'season': 1, 'episode': 2, 'title': None, 'year': None, 'source': None, 'resolution': None, 'release_group': None, 'video_codec': None, 'audio_codec': None, } }
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 scan_video(path, dont_use_actual_file=False, hints=None): """Scan a video from a `path`. patch: - allow passing of hints/options to guessit - allow dry-run with dont_use_actual_file - add crap removal (obfuscated/scrambled) - trust plex's movie name :param str path: existing path to the video. :return: the scanned video. :rtype: :class:`~subliminal.video.Video` """ hints = hints or {} video_type = hints.get("type") # check for non-existing path if not dont_use_actual_file and not os.path.exists(path): raise ValueError('Path does not exist') # check video extension if not path.lower().endswith(VIDEO_EXTENSIONS): raise ValueError('%r is not a valid video extension' % os.path.splitext(path)[1]) dirpath, filename = os.path.split(path) logger.info('Scanning video %r in %r', filename, dirpath) # hint guessit the filename itself and its 2 parent directories if we're an episode (most likely # Series name/Season/filename), else only one guess_from = os.path.join(*os.path.normpath(path).split(os.path.sep)[-3 if video_type == "episode" else -2:]) guess_from = REMOVE_CRAP_FROM_FILENAME.sub(r"\2", guess_from) # guess hints["single_value"] = True guessed_result = guessit(guess_from, options=hints) logger.debug('GuessIt found: %s', json.dumps(guessed_result, cls=GuessitEncoder, indent=4, ensure_ascii=False)) video = Video.fromguess(path, guessed_result) # trust plex's movie name if video_type == "movie" and hints.get("expected_title"): video.title = hints.get("expected_title")[0] if dont_use_actual_file: return video # size and hashes video.size = os.path.getsize(path) if video.size > 10485760: logger.debug('Size is %d', video.size) video.hashes['opensubtitles'] = hash_opensubtitles(path) video.hashes['shooter'] = hash_shooter(path) video.hashes['thesubdb'] = hash_thesubdb(path) video.hashes['napiprojekt'] = hash_napiprojekt(path) logger.debug('Computed hashes %r', video.hashes) else: logger.warning('Size is lower than 10MB: hashes not computed') return video
def test_newly_added_video_has_no_downloads(self): path = "/data/Series/Season 1/01 Title.mkv" video = Video.fromname("Series.S01E02.Title.720p.WEB-DL.DD5.1.H264-ReleaseGroup.mkv") self.datastore.add_video(path, video) downloads = self.datastore.get_downloads_for_video(path) self.assertEqual(downloads, {})
def test_added_sub_is_returned(self): path = "/data/Series/Season 1/01 Title.mkv" video = Video.fromname("Series.S01E02.Title.720p.WEB-DL.DD5.1.H264-ReleaseGroup.mkv") self.datastore.add_video(path, video) provider = "davessubs" sub_id = "ABC123" lang = Language.fromietf("en") score = 123 self.datastore.add_download(path, provider, sub_id, lang, score) downloads = self.datastore.get_downloads_for_video(path) self.assertEqual(downloads, {lang: [{"provider": provider, "sub_id": sub_id, "lang": lang, "score": score}]})
def data(create_tvshow, create_tvepisode): show_name = 'Enhanced Show Name' show_year = 2012 tvshow = create_tvshow(indexerid=12, name='{0} ({1})'.format(show_name, show_year), imdb_id='tt0000000') tvepisode = create_tvepisode(show=tvshow, indexer=34, season=3, episode=4, name='Episode Title', file_size=1122334455, status=Quality.composite_status( DOWNLOADED, Quality.FULLHDBLURAY), release_group='SuperGroup') return { 'tvshow': tvshow, 'tvshow_properties': { 'series': show_name, 'year': show_year, 'series_tvdb_id': tvshow.tvdb_id, 'series_imdb_id': tvshow.imdb_id, }, 'tvepisode': tvepisode, 'tvepisode_properties': { 'season': tvepisode.season, 'episode': tvepisode.episode, 'title': tvepisode.name, 'resolution': '1080p', 'format': 'BluRay', 'release_group': tvepisode.release_group, 'size': tvepisode.file_size, 'tvdb_id': tvepisode.tvdb_id, }, 'video': Video.fromname('Show.Name.S01E02.mkv'), 'video_properties': { 'series': 'Show Name', 'season': 1, 'episode': 2, 'title': None, 'year': None, 'resolution': None, 'format': None, 'release_group': None, 'size': None, 'series_tvdb_id': None, 'series_imdb_id': None, 'tvdb_id': None, } }
def test_video_fromname_movie(movies): video = Video.fromname(movies['man_of_steel'].name) assert type(video) is Movie assert video.name == movies['man_of_steel'].name assert video.format == movies['man_of_steel'].format assert video.release_group == movies['man_of_steel'].release_group assert video.resolution == movies['man_of_steel'].resolution assert video.video_codec == movies['man_of_steel'].video_codec assert video.audio_codec is None assert video.imdb_id is None assert video.hashes == {} assert video.size is None assert video.subtitle_languages == set() assert video.title == movies['man_of_steel'].title assert video.year == movies['man_of_steel'].year
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 test_video_fromname_episode(episodes): video = Video.fromname(episodes['bbt_s07e05'].name) assert type(video) is Episode assert video.name == episodes['bbt_s07e05'].name assert video.format == episodes['bbt_s07e05'].format assert video.release_group == episodes['bbt_s07e05'].release_group assert video.resolution == episodes['bbt_s07e05'].resolution assert video.video_codec == episodes['bbt_s07e05'].video_codec assert video.audio_codec is None assert video.imdb_id is None assert video.hashes == {} assert video.size is None assert video.subtitle_languages == set() assert video.series == episodes['bbt_s07e05'].series assert video.season == episodes['bbt_s07e05'].season assert video.episode == episodes['bbt_s07e05'].episode assert video.title is None assert video.year is None assert video.tvdb_id is None
def test_video_fromname_episode(episodes): video = Video.fromname(episodes['bbt_s07e05'].name) assert type(video) is Episode assert video.name == episodes['bbt_s07e05'].name assert video.source == episodes['bbt_s07e05'].source assert video.release_group == episodes['bbt_s07e05'].release_group assert video.resolution == episodes['bbt_s07e05'].resolution assert video.video_codec == episodes['bbt_s07e05'].video_codec assert video.audio_codec is None assert video.imdb_id is None assert video.hashes == {} assert video.size is None assert video.subtitle_languages == set() assert video.series == episodes['bbt_s07e05'].series assert video.season == episodes['bbt_s07e05'].season assert video.episode == episodes['bbt_s07e05'].episode assert video.title is None assert video.year is None assert video.tvdb_id is None
def test_video_fromname_episode_no_season(episodes): video = Video.fromname(episodes['the_jinx_e05'].name) assert type(video) is Episode assert video.name == episodes['the_jinx_e05'].name assert video.format == episodes['the_jinx_e05'].format assert video.release_group == episodes['the_jinx_e05'].release_group assert video.resolution == episodes['the_jinx_e05'].resolution assert video.video_codec == episodes['the_jinx_e05'].video_codec assert video.audio_codec is None assert video.imdb_id is None assert video.hashes == {} assert video.size is None assert video.subtitle_languages == set() assert sanitize(video.series) == sanitize(episodes['the_jinx_e05'].series) assert video.season == episodes['the_jinx_e05'].season assert video.episode == episodes['the_jinx_e05'].episode assert video.title is None assert video.year is None assert video.tvdb_id is None
def test_get_incomplete_videos(self, name, videos, expected): for video in videos: added = datetime.utcnow() - video["age"] if "age" in video else timedelta(0) self.datastore.add_video(video["path"], Video.fromname(video["name"]), added) for provider, sub_id, lang, score in video["downloads"]: self.datastore.add_download(video["path"], provider, sub_id, Language.fromietf(lang), score) lang1 = Language.fromietf("en") lang2 = Language.fromietf("pt-BR") incomplete = self.datastore.get_incomplete_videos( [lang1, lang2], 80, 100, datetime.utcnow() - timedelta(days=1) ) self.assertEqual(len(incomplete), len(expected)) for video_idx, needs in expected: actual = next(video for video in incomplete if video["path"] == videos[video_idx]["path"]) self.assertEqual(actual["video"].name, videos[video_idx]["name"]) self.assertEqual(len(actual["needs"]), len(needs)) for lang, score in needs: actual_need = next(need for need in actual["needs"] if str(need["lang"]) == lang) self.assertEqual(actual_need["current_score"], score)
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 video(): return Video.fromname('Show.Name.S03E04.mkv')
def scan_video(path, subtitles=True, embedded_subtitles=True, video_type=None): """Scan a video and its subtitle languages from a video `path`. :param str path: existing path to the video. :param bool subtitles: scan for subtitles with the same name. :param bool embedded_subtitles: scan for embedded subtitles. :return: the scanned video. :rtype: :class:`Video` # patch: suggest video type to guessit beforehand """ # check for non-existing path if not os.path.exists(path): raise ValueError('Path does not exist') # check video extension if not path.endswith(VIDEO_EXTENSIONS): raise ValueError('%s is not a valid video extension' % os.path.splitext(path)[1]) dirpath, filename = os.path.split(path) logger.info('Scanning video (type: %s) %r in %r', video_type, filename, dirpath) # guess video = Video.fromguess(path, guess_file_info(path, options={"type": video_type})) # size and hashes video.size = os.path.getsize(path) if video.size > 10485760: logger.debug('Size is %d', video.size) video.hashes['opensubtitles'] = hash_opensubtitles(path) video.hashes['thesubdb'] = hash_thesubdb(path) logger.debug('Computed hashes %r', video.hashes) else: logger.warning('Size is lower than 10MB: hashes not computed') # external subtitles if subtitles: video.subtitle_languages |= set(patched_search_external_subtitles(path).values()) # video metadata with enzyme try: if filename.endswith('.mkv'): with open(path, 'rb') as f: mkv = MKV(f) # main video track if mkv.video_tracks: video_track = mkv.video_tracks[0] # resolution if video_track.height in (480, 720, 1080): if video_track.interlaced: video.resolution = '%di' % video_track.height else: video.resolution = '%dp' % video_track.height logger.debug('Found resolution %s with enzyme', video.resolution) # video codec if video_track.codec_id == 'V_MPEG4/ISO/AVC': video.video_codec = 'h264' logger.debug('Found video_codec %s with enzyme', video.video_codec) elif video_track.codec_id == 'V_MPEG4/ISO/SP': video.video_codec = 'DivX' logger.debug('Found video_codec %s with enzyme', video.video_codec) elif video_track.codec_id == 'V_MPEG4/ISO/ASP': video.video_codec = 'XviD' logger.debug('Found video_codec %s with enzyme', video.video_codec) else: logger.warning('MKV has no video track') # main audio track if mkv.audio_tracks: audio_track = mkv.audio_tracks[0] # audio codec if audio_track.codec_id == 'A_AC3': video.audio_codec = 'AC3' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) elif audio_track.codec_id == 'A_DTS': video.audio_codec = 'DTS' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) elif audio_track.codec_id == 'A_AAC': video.audio_codec = 'AAC' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) else: logger.warning('MKV has no audio track') # subtitle tracks if mkv.subtitle_tracks: if embedded_subtitles: embedded_subtitle_languages = set() for st in mkv.subtitle_tracks: if st.language: try: embedded_subtitle_languages.add(Language.fromalpha3b(st.language)) except BabelfishError: logger.error('Embedded subtitle track language %r is not a valid language', st.language) embedded_subtitle_languages.add(Language('und')) elif st.name: try: embedded_subtitle_languages.add(Language.fromname(st.name)) except BabelfishError: logger.debug('Embedded subtitle track name %r is not a valid language', st.name) embedded_subtitle_languages.add(Language('und')) else: embedded_subtitle_languages.add(Language('und')) logger.debug('Found embedded subtitle %r with enzyme', embedded_subtitle_languages) video.subtitle_languages |= embedded_subtitle_languages else: logger.debug('MKV has no subtitle track') except EnzymeError: logger.exception('Parsing video metadata with enzyme failed') return video
def test_video_fromguess_episode(episodes, monkeypatch): guess = {"type": "episode"} monkeypatch.setattr(Episode, "fromguess", Mock()) Video.fromguess(episodes["bbt_s07e05"].name, guess) assert Episode.fromguess.called
def test_video_fromguess_wrong_type(episodes): guess = {'type': 'subtitle'} with pytest.raises(ValueError) as excinfo: Video.fromguess(episodes['bbt_s07e05'].name, guess) assert str(excinfo.value) == 'The guess must be an episode or a movie guess'
def scan_video(path, subtitles=True, embedded_subtitles=True, video_type=None): """Scan a video and its subtitle languages from a video `path`. :param str path: existing path to the video. :param bool subtitles: scan for subtitles with the same name. :param bool embedded_subtitles: scan for embedded subtitles. :return: the scanned video. :rtype: :class:`Video` # patch: suggest video type to guessit beforehand """ # check for non-existing path if not os.path.exists(path): raise ValueError('Path does not exist') # check video extension if not path.endswith(VIDEO_EXTENSIONS): raise ValueError('%s is not a valid video extension' % os.path.splitext(path)[1]) dirpath, filename = os.path.split(path) logger.info('Scanning video (type: %s) %r in %r', video_type, filename, dirpath) # guess video = Video.fromguess( path, guess_file_info(path, options={"type": video_type})) # size and hashes video.size = os.path.getsize(path) if video.size > 10485760: logger.debug('Size is %d', video.size) video.hashes['opensubtitles'] = hash_opensubtitles(path) video.hashes['thesubdb'] = hash_thesubdb(path) logger.debug('Computed hashes %r', video.hashes) else: logger.warning('Size is lower than 10MB: hashes not computed') # external subtitles if subtitles: video.subtitle_languages |= set( patched_search_external_subtitles(path).values()) # video metadata with enzyme try: if filename.endswith('.mkv'): with open(path, 'rb') as f: mkv = MKV(f) # main video track if mkv.video_tracks: video_track = mkv.video_tracks[0] # resolution if video_track.height in (480, 720, 1080): if video_track.interlaced: video.resolution = '%di' % video_track.height else: video.resolution = '%dp' % video_track.height logger.debug('Found resolution %s with enzyme', video.resolution) # video codec if video_track.codec_id == 'V_MPEG4/ISO/AVC': video.video_codec = 'h264' logger.debug('Found video_codec %s with enzyme', video.video_codec) elif video_track.codec_id == 'V_MPEG4/ISO/SP': video.video_codec = 'DivX' logger.debug('Found video_codec %s with enzyme', video.video_codec) elif video_track.codec_id == 'V_MPEG4/ISO/ASP': video.video_codec = 'XviD' logger.debug('Found video_codec %s with enzyme', video.video_codec) else: logger.warning('MKV has no video track') # main audio track if mkv.audio_tracks: audio_track = mkv.audio_tracks[0] # audio codec if audio_track.codec_id == 'A_AC3': video.audio_codec = 'AC3' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) elif audio_track.codec_id == 'A_DTS': video.audio_codec = 'DTS' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) elif audio_track.codec_id == 'A_AAC': video.audio_codec = 'AAC' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) else: logger.warning('MKV has no audio track') # subtitle tracks if mkv.subtitle_tracks: if embedded_subtitles: embedded_subtitle_languages = set() for st in mkv.subtitle_tracks: if st.language: try: embedded_subtitle_languages.add( Language.fromalpha3b(st.language)) except BabelfishError: logger.error( 'Embedded subtitle track language %r is not a valid language', st.language) embedded_subtitle_languages.add( Language('und')) elif st.name: try: embedded_subtitle_languages.add( Language.fromname(st.name)) except BabelfishError: logger.debug( 'Embedded subtitle track name %r is not a valid language', st.name) embedded_subtitle_languages.add( Language('und')) else: embedded_subtitle_languages.add(Language('und')) logger.debug('Found embedded subtitle %r with enzyme', embedded_subtitle_languages) video.subtitle_languages |= embedded_subtitle_languages else: logger.debug('MKV has no subtitle track') except EnzymeError: logger.exception('Parsing video metadata with enzyme failed') return video
def scan_video(path, dont_use_actual_file=False, hints=None, providers=None, skip_hashing=False): """Scan a video from a `path`. patch: - allow passing of hints/options to guessit - allow dry-run with dont_use_actual_file - add crap removal (obfuscated/scrambled) - trust plex's movie name :param str path: existing path to the video. :return: the scanned video. :rtype: :class:`~subliminal.video.Video` """ hints = hints or {} video_type = hints.get("type") # check for non-existing path if not dont_use_actual_file and not os.path.exists(path): raise ValueError('Path does not exist') # check video extension if not path.lower().endswith(VIDEO_EXTENSIONS): raise ValueError('%r is not a valid video extension' % os.path.splitext(path)[1]) dirpath, filename = os.path.split(path) logger.info('Determining basic video properties for %r in %r', filename, dirpath) # hint guessit the filename itself and its 2 parent directories if we're an episode (most likely # Series name/Season/filename), else only one split_path = os.path.normpath(path).split(os.path.sep)[-3 if video_type == "episode" else -2:] # remove crap from folder names if video_type == "episode": if len(split_path) > 2: split_path[-3] = remove_crap_from_fn(split_path[-3]) else: if len(split_path) > 1: split_path[-2] = remove_crap_from_fn(split_path[-2]) guess_from = os.path.join(*split_path) # remove crap from file name guess_from = remove_crap_from_fn(guess_from) # guess hints["single_value"] = True if "title" in hints: hints["expected_title"] = [hints["title"]] guessed_result = guessit(guess_from, options=hints) logger.debug('GuessIt found: %s', json.dumps(guessed_result, cls=GuessitEncoder, indent=4, ensure_ascii=False)) video = Video.fromguess(path, guessed_result) video.hints = hints # get possibly alternative title from the filename itself alt_guess = guessit(filename, options=hints) if "title" in alt_guess and alt_guess["title"] != guessed_result["title"]: if video_type == "episode": video.alternative_series.append(alt_guess["title"]) else: video.alternative_titles.append(alt_guess["title"]) logger.debug("Adding alternative title: %s", alt_guess["title"]) if dont_use_actual_file: return video # size and hashes if not skip_hashing: video.size = os.path.getsize(path) if video.size > 10485760: logger.debug('Size is %d', video.size) if "opensubtitles" in providers: video.hashes['opensubtitles'] = hash_opensubtitles(path) if "shooter" in providers: video.hashes['shooter'] = hash_shooter(path) if "thesubdb" in providers: video.hashes['thesubdb'] = hash_thesubdb(path) if "napiprojekt" in providers: try: video.hashes['napiprojekt'] = hash_napiprojekt(path) except MemoryError: logger.warning(u"Couldn't compute napiprojekt hash for %s", path) logger.debug('Computed hashes %r', video.hashes) else: logger.warning('Size is lower than 10MB: hashes not computed') return video
def test_video_fromguess_wrong_type(episodes): guess = {'type': 'subtitle'} with pytest.raises(ValueError) as excinfo: Video.fromguess(episodes['bbt_s07e05'].name, guess) assert str( excinfo.value) == 'The guess must be an episode or a movie guess'
def test_video_fromguess_movie(movies, monkeypatch): guess = {'type': 'movie'} monkeypatch.setattr(Movie, 'fromguess', Mock()) Video.fromguess(movies['man_of_steel'].name, guess) assert Movie.fromguess.called
def test_video_fromguess_episode(episodes, monkeypatch): guess = {'type': 'episode'} monkeypatch.setattr(Episode, 'fromguess', Mock()) Video.fromguess(episodes['bbt_s07e05'].name, guess) assert Episode.fromguess.called
def scan_video(path, subtitles=True, embedded_subtitles=True, hints=None, video_fps=None, dont_use_actual_file=False, forced_tag=False, known_embedded_subtitle_streams=None): """Scan a video and its subtitle languages from a video `path`. :param dont_use_actual_file: guess on filename, but don't use the actual file itself :param str path: existing path to the video. :param bool subtitles: scan for subtitles with the same name. :param bool embedded_subtitles: scan for embedded subtitles. :param hints: hints dict for guessit :return: the scanned video. :rtype: :class:`Video` # patch: suggest video type to guessit beforehand """ hints = hints or {} video_type = hints.get("type") # check for non-existing path if not dont_use_actual_file and not os.path.exists(path): raise ValueError('Path does not exist') # check video extension if not path.endswith(VIDEO_EXTENSIONS): raise ValueError('%s is not a valid video extension' % os.path.splitext(path)[1]) dirpath, filename = os.path.split(path) # hint guessit the filename itself and its 2 parent directories if we're an episode (most likely Series name/Season/filename), else only one guess_from = os.path.join(*os.path.normpath(path).split(os.path.sep) [-3 if video_type == "episode" else -2:]) hints = hints or {} logger.info('Scanning video (hints: %s) %r', hints, guess_from) # guess video = Video.fromguess(path, guess_file_info(guess_from, options=hints)) video.fps = video_fps # trust plex's movie name if video_type == "movie" and hints.get("expected_title"): video.title = hints.get("expected_title")[0] if dont_use_actual_file: return video # size and hashes video.size = os.path.getsize(path) if video.size > 10485760: logger.debug('Size is %d', video.size) video.hashes['opensubtitles'] = hash_opensubtitles(path) video.hashes['thesubdb'] = hash_thesubdb(path) logger.debug('Computed hashes %r', video.hashes) else: logger.warning('Size is lower than 10MB: hashes not computed') # external subtitles if subtitles: video.subtitle_languages |= set( patched_search_external_subtitles(path, forced_tag=forced_tag).values()) if embedded_subtitles and known_embedded_subtitle_streams: embedded_subtitle_languages = set() # mp4 and stuff, check burned in for language in known_embedded_subtitle_streams: try: embedded_subtitle_languages.add(Language.fromalpha3b(language)) except BabelfishError: logger.error( 'Embedded subtitle track language %r is not a valid language', language) embedded_subtitle_languages.add(Language('und')) logger.debug('Found embedded subtitle %r', embedded_subtitle_languages) video.subtitle_languages |= embedded_subtitle_languages # video metadata with enzyme try: if filename.endswith('.mkv'): with open(path, 'rb') as f: mkv = MKV(f) # main video track if mkv.video_tracks: video_track = mkv.video_tracks[0] # resolution if video_track.height in (480, 720, 1080): if video_track.interlaced: video.resolution = '%di' % video_track.height else: video.resolution = '%dp' % video_track.height logger.debug('Found resolution %s with enzyme', video.resolution) # video codec if video_track.codec_id == 'V_MPEG4/ISO/AVC': video.video_codec = 'h264' logger.debug('Found video_codec %s with enzyme', video.video_codec) elif video_track.codec_id == 'V_MPEG4/ISO/SP': video.video_codec = 'DivX' logger.debug('Found video_codec %s with enzyme', video.video_codec) elif video_track.codec_id == 'V_MPEG4/ISO/ASP': video.video_codec = 'XviD' logger.debug('Found video_codec %s with enzyme', video.video_codec) else: logger.warning('MKV has no video track') # main audio track if mkv.audio_tracks: audio_track = mkv.audio_tracks[0] # audio codec if audio_track.codec_id == 'A_AC3': video.audio_codec = 'AC3' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) elif audio_track.codec_id == 'A_DTS': video.audio_codec = 'DTS' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) elif audio_track.codec_id == 'A_AAC': video.audio_codec = 'AAC' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) else: logger.warning('MKV has no audio track') except EnzymeError: logger.error('Parsing video metadata with enzyme failed') except Exception: logger.error("Parsing video with enzyme has gone terribly wrong: %s", traceback.format_exc()) return video
def test_video_fromguess_wrong_type(episodes): guess = {"type": "subtitle"} with pytest.raises(ValueError) as excinfo: Video.fromguess(episodes["bbt_s07e05"].name, guess) assert str(excinfo.value) == "The guess must be an episode or a movie guess"
def scan_video(path, dont_use_actual_file=False, hints=None, providers=None, skip_hashing=False, hash_from=None): """Scan a video from a `path`. patch: - allow passing of hints/options to guessit - allow dry-run with dont_use_actual_file - add crap removal (obfuscated/scrambled) - trust plex's movie name :param str path: existing path to the video. :return: the scanned video. :rtype: :class:`~subliminal.video.Video` """ hints = hints or {} video_type = hints.get("type") # check for non-existing path if not dont_use_actual_file and not os.path.exists(path): raise ValueError('Path does not exist') # check video extension if not path.lower().endswith(VIDEO_EXTENSIONS): raise ValueError('%r is not a valid video extension' % os.path.splitext(path)[1]) dirpath, filename = os.path.split(path) logger.info('Determining basic video properties for %r in %r', filename, dirpath) # hint guessit the filename itself and its 2 parent directories if we're an episode (most likely # Series name/Season/filename), else only one split_path = os.path.normpath(path).split( os.path.sep)[-3 if video_type == "episode" else -2:] # remove crap from folder names if video_type == "episode": if len(split_path) > 2: split_path[-3] = remove_crap_from_fn(split_path[-3]) else: if len(split_path) > 1: split_path[-2] = remove_crap_from_fn(split_path[-2]) guess_from = os.path.join(*split_path) # remove crap from file name guess_from = remove_crap_from_fn(guess_from) # guess hints["single_value"] = True if "title" in hints: hints["expected_title"] = [hints["title"]] guessed_result = guessit(guess_from, options=hints) logger.debug( 'GuessIt found: %s', json.dumps(guessed_result, cls=GuessitEncoder, indent=4, ensure_ascii=False)) video = Video.fromguess(path, guessed_result) video.hints = hints # get possibly alternative title from the filename itself alt_guess = guessit(filename, options=hints) if "title" in alt_guess and alt_guess["title"] != guessed_result["title"]: if video_type == "episode": video.alternative_series.append(alt_guess["title"]) else: video.alternative_titles.append(alt_guess["title"]) logger.debug("Adding alternative title: %s", alt_guess["title"]) if dont_use_actual_file and not hash_from: return video # if all providers are throttled, skip hashing if not providers: skip_hashing = True # size and hashes if not skip_hashing: hash_path = hash_from or path video.size = os.path.getsize(hash_path) if video.size > 10485760: logger.debug('Size is %d', video.size) osub_hash = None if "bsplayer" in providers: video.hashes['bsplayer'] = osub_hash = hash_opensubtitles( hash_path) if "opensubtitles" in providers: video.hashes[ 'opensubtitles'] = osub_hash = osub_hash or hash_opensubtitles( hash_path) if "opensubtitlescom" in providers: video.hashes[ 'opensubtitlescom'] = osub_hash = osub_hash or hash_opensubtitles( hash_path) if "shooter" in providers: video.hashes['shooter'] = hash_shooter(hash_path) if "thesubdb" in providers: video.hashes['thesubdb'] = hash_thesubdb(hash_path) if "napiprojekt" in providers: try: video.hashes['napiprojekt'] = hash_napiprojekt(hash_path) except MemoryError: logger.warning(u"Couldn't compute napiprojekt hash for %s", hash_path) if "napisy24" in providers: # Napisy24 uses the same hash as opensubtitles video.hashes['napisy24'] = osub_hash or hash_opensubtitles( hash_path) logger.debug('Computed hashes %r', video.hashes) else: logger.warning('Size is lower than 10MB: hashes not computed') return video
def test_video_fromguess_movie(movies, monkeypatch): guess = {"type": "movie"} monkeypatch.setattr(Movie, "fromguess", Mock()) Video.fromguess(movies["man_of_steel"].name, guess) assert Movie.fromguess.called
def scan_video(path, subtitles=True, embedded_subtitles=True, hints=None, video_fps=None, dont_use_actual_file=False): """Scan a video and its subtitle languages from a video `path`. :param dont_use_actual_file: guess on filename, but don't use the actual file itself :param str path: existing path to the video. :param bool subtitles: scan for subtitles with the same name. :param bool embedded_subtitles: scan for embedded subtitles. :param hints: hints dict for guessit :return: the scanned video. :rtype: :class:`Video` # patch: suggest video type to guessit beforehand """ hints = hints or {} # check for non-existing path if not dont_use_actual_file and not os.path.exists(path): raise ValueError('Path does not exist') # check video extension if not path.endswith(VIDEO_EXTENSIONS): raise ValueError('%s is not a valid video extension' % os.path.splitext(path)[1]) dirpath, filename = os.path.split(path) # hint guessit the filename itself and its 2 parent directories if we're an episode (most likely Series name/Season/filename), else only one guess_from = os.path.join(*os.path.normpath(path).split(os.path.sep)[-3 if hints.get("type") == "episode" else -2:]) hints = hints or {} logger.info('Scanning video (hints: %s) %r', hints, guess_from) # guess try: video = Video.fromguess(path, guess_file_info(guess_from, options=hints)) video.fps = video_fps if dont_use_actual_file: return video # size and hashes video.size = os.path.getsize(path) if video.size > 10485760: logger.debug('Size is %d', video.size) video.hashes['opensubtitles'] = hash_opensubtitles(path) video.hashes['thesubdb'] = hash_thesubdb(path) logger.debug('Computed hashes %r', video.hashes) else: logger.warning('Size is lower than 10MB: hashes not computed') # external subtitles if subtitles: video.subtitle_languages |= set(patched_search_external_subtitles(path).values()) except Exception: logger.error("Something went wrong when running guessit: %s", traceback.format_exc()) return # video metadata with enzyme try: if filename.endswith('.mkv'): with open(path, 'rb') as f: mkv = MKV(f) # main video track if mkv.video_tracks: video_track = mkv.video_tracks[0] # resolution if video_track.height in (480, 720, 1080): if video_track.interlaced: video.resolution = '%di' % video_track.height else: video.resolution = '%dp' % video_track.height logger.debug('Found resolution %s with enzyme', video.resolution) # video codec if video_track.codec_id == 'V_MPEG4/ISO/AVC': video.video_codec = 'h264' logger.debug('Found video_codec %s with enzyme', video.video_codec) elif video_track.codec_id == 'V_MPEG4/ISO/SP': video.video_codec = 'DivX' logger.debug('Found video_codec %s with enzyme', video.video_codec) elif video_track.codec_id == 'V_MPEG4/ISO/ASP': video.video_codec = 'XviD' logger.debug('Found video_codec %s with enzyme', video.video_codec) else: logger.warning('MKV has no video track') # main audio track if mkv.audio_tracks: audio_track = mkv.audio_tracks[0] # audio codec if audio_track.codec_id == 'A_AC3': video.audio_codec = 'AC3' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) elif audio_track.codec_id == 'A_DTS': video.audio_codec = 'DTS' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) elif audio_track.codec_id == 'A_AAC': video.audio_codec = 'AAC' logger.debug('Found audio_codec %s with enzyme', video.audio_codec) else: logger.warning('MKV has no audio track') # subtitle tracks if mkv.subtitle_tracks: if embedded_subtitles: embedded_subtitle_languages = set() for st in mkv.subtitle_tracks: if st.forced: logger.debug("Ignoring forced subtitle track %r", st) continue if st.language: try: embedded_subtitle_languages.add(Language.fromalpha3b(st.language)) except BabelfishError: logger.error('Embedded subtitle track language %r is not a valid language', st.language) embedded_subtitle_languages.add(Language('und')) elif st.name: try: embedded_subtitle_languages.add(Language.fromname(st.name)) except BabelfishError: logger.debug('Embedded subtitle track name %r is not a valid language', st.name) embedded_subtitle_languages.add(Language('und')) else: embedded_subtitle_languages.add(Language('und')) logger.debug('Found embedded subtitle %r with enzyme', embedded_subtitle_languages) video.subtitle_languages |= embedded_subtitle_languages else: logger.debug('MKV has no subtitle track') except EnzymeError: logger.error('Parsing video metadata with enzyme failed') except Exception: logger.error("Parsing video with enzyme has gone terribly wrong: %s", traceback.format_exc()) return video
x = 'n' while x != 'y': index = randint(0, countGS - 1) print("Launching " + str(stashnames[index])) findGenre(stashnames[index]) print("\n\n......Good enough? Y/N\n") x = str(getch(), 'utf-8') print( "\n=================================================================================\n" ) if x.lower() == 'y': if dlSub == True: print("\n\nGetting subtitles..Please Wait..\n\n") try: region.configure('dogpile.cache.dbm', arguments={'filename': 'cachefile.dbm'}) videos = Video.fromname(stash[index]) subtitles = download_best_subtitles([videos], {Language('eng')}) best_subtitle = subtitles[videos][0] save_subtitles(videos, [best_subtitle]) print("\nSubtitle downloaded.\n") except: print("\nCould not get subtitle :\\\n") os.startfile(stash[index]) elif x.lower() == 'n': print("Moving on...\n") else: print("\nWut? wut? i'll just assume it wasn't of your taste sire.\n")
def test_episode_from_guess_multi_episode(episodes): video = Video.fromname( episodes['Marvels.Agents.of.S.H.I.E.L.D.S05E01-E02'].name) # Multi-ep is converted to single-ep by taking the lowest episode number assert video.episode == episodes[ 'Marvels.Agents.of.S.H.I.E.L.D.S05E01-E02'].episode