Example #1
0
 def test_converter_alpha3b(self):
     self.assertEqual(Language('fra').alpha3b, 'fre')
     self.assertEqual(Language.fromalpha3b('fre'), Language('fra'))
     self.assertEqual(Language.fromcode('fre', 'alpha3b'), Language('fra'))
     self.assertRaises(LanguageReverseError, lambda: Language.fromalpha3b('zzz'))
     self.assertRaises(LanguageConvertError, lambda: Language('aaa').alpha3b)
     self.assertEqual(len(language_converters['alpha3b'].codes), 418)
Example #2
0
 def test_converter_alpha3b(self):
     self.assertEqual(Language('fra').alpha3b, 'fre')
     self.assertEqual(Language.fromalpha3b('fre'), Language('fra'))
     self.assertEqual(Language.fromcode('fre', 'alpha3b'), Language('fra'))
     with self.assertRaises(LanguageReverseError):
         Language.fromalpha3b('zzz')
     with self.assertRaises(LanguageConvertError):
         Language('aaa').alpha3b
     self.assertEqual(len(get_language_converter('alpha3b').codes), 418)
Example #3
0
def _get_embedded_subtitles(dirname, filename):
    """
    Based on subliminal.video.scan_video(...) but only keep the check for embedded subtitles
    """
    log.debug("Checking for embedded subtitle")
    embedded_subtitle_languages = set()
    try:
        path = os.path.join(dirname, filename)
        if filename.endswith('.mkv'):
            with open(path, 'rb') as f:
                mkv = MKV(f)

            # subtitle tracks
            if mkv.subtitle_tracks:
                for st in mkv.subtitle_tracks:
                    if st.language:
                        try:
                            embedded_subtitle_languages.add(Language.fromalpha3b(st.language))
                        except BabelfishError:
                            log.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:
                            log.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'))
                log.debug('Found embedded subtitles %r with enzyme', embedded_subtitle_languages)
            else:
                log.debug('MKV has no subtitle track')
    except:
        log.exception('Parsing video metadata with enzyme failed')
    return embedded_subtitle_languages
Example #4
0
    def _language(self) -> Language:
        og_lang = self.tags.get("language")
        last_exc = None

        if og_lang is not None:
            if og_lang in _extra_languages:
                extra = _extra_languages[og_lang]
                title = self.tags.get("title", "n/a").lower()
                if any(possible in title for possible in extra["matches"]):
                    logger.debug("Found extra language %s",
                                 extra["language_args"])
                    return Language(*extra["language_args"])

            try:
                lang = Language.fromalpha3b(og_lang)
                # Test for suffix
                assert lang.alpha2

                return lang
            except LanguageError as error:
                last_exc = error
                logger.debug("Error with '%s' language: %s", og_lang, error)

        raise LanguageNotFound(
            f"Couldn't detect language for stream: {self.tags}") from last_exc
def getAlpha3TCode(code):  # We need to make sure that language codes are alpha3T
    """
        :param    code: Alpha2, Alpha3, or Alpha3b code.
        :type     code: C{str}

        :return: Alpha3t language code (ISO 639-2/T) as C{str}
    """
    lang = 'und'
    code = code.strip().lower()

    if len(code) == 3:
        try:
            lang = Language(code).alpha3t
        except:
            try:
                lang = Language.fromalpha3b(code).alpha3t
            except:
                try:
                    lang = Language.fromalpha3t(code).alpha3t
                except:
                    pass

    elif len(code) == 2:
        lang = Language.fromalpha2(code).alpha3t

    return lang
Example #6
0
def getEmbeddedLanguages(video_path):
    embedded_subtitle_languages = set()
    try:
        with ek(io.open, video_path, 'rb') as f:
            mkv = MKV(f)
            if mkv.subtitle_tracks:
                for st in mkv.subtitle_tracks:
                    if st.language:
                        try:
                            embedded_subtitle_languages.add(Language.fromalpha3b(st.language))
                        except BabelfishError:
                            logging.debug('Embedded subtitle track is not a valid language')
                            embedded_subtitle_languages.add(Language('und'))
                    elif st.name:
                        try:
                            embedded_subtitle_languages.add(Language.fromname(st.name))
                        except BabelfishError:
                            logging.debug('Embedded subtitle track is not a valid language')
                            embedded_subtitle_languages.add(Language('und'))
                    else:
                        embedded_subtitle_languages.add(Language('und'))
            else:
                logging.debug('MKV has no subtitle track')
    except MalformedMKVError:
        logging.info('MKV seems to be malformed ( %s ), ignoring embedded subtitles' % video_path)

    return embedded_subtitle_languages
Example #7
0
def getAlpha3TCode(code):  # We need to make sure that language codes are alpha3T
    """
        :param    code: Alpha2, Alpha3, or Alpha3b code.
        :type     code: C{str}

        :return: Alpha3t language code (ISO 639-2/T) as C{str}
    """
    lang = 'und'
    code = code.strip().lower()

    if len(code) == 3:
        try:
            lang = Language(code).alpha3t
        except:
            try:
                lang = Language.fromalpha3b(code).alpha3t
            except:
                try:
                    lang = Language.fromalpha3t(code).alpha3t
                except:
                    pass

    elif len(code) == 2:
        lang = Language.fromalpha2(code).alpha3t

    return lang
Example #8
0
def getEmbeddedLanguages(video_path):
    embedded_subtitle_languages = set()
    try:
        with ek(io.open, video_path, 'rb') as f:
            mkv = MKV(f)
            if mkv.subtitle_tracks:
                for st in mkv.subtitle_tracks:
                    if st.language:
                        try:
                            embedded_subtitle_languages.add(
                                Language.fromalpha3b(st.language))
                        except BabelfishError:
                            logging.debug(
                                'Embedded subtitle track is not a valid language'
                            )
                            embedded_subtitle_languages.add(Language('und'))
                    elif st.name:
                        try:
                            embedded_subtitle_languages.add(
                                Language.fromname(st.name))
                        except BabelfishError:
                            logging.debug(
                                'Embedded subtitle track is not a valid language'
                            )
                            embedded_subtitle_languages.add(Language('und'))
                    else:
                        embedded_subtitle_languages.add(Language('und'))
            else:
                logging.debug('MKV has no subtitle track')
    except MalformedMKVError:
        logging.info(
            'MKV seems to be malformed ( %s ), ignoring embedded subtitles' %
            video_path)

    return embedded_subtitle_languages
Example #9
0
def subtitlesLanguages(video_path):
    """Return a list detected subtitles for the given video file"""
    resultList = []
    embedded_subtitle_languages = set()

    # Serch for embedded subtitles
    if not sickbeard.EMBEDDED_SUBTITLES_ALL:
        if video_path.endswith('mkv'):
            try:
                with open(video_path.encode(sickbeard.SYS_ENCODING), 'rb') as f:
                    mkv = MKV(f)
                if mkv.subtitle_tracks:
                    for st in mkv.subtitle_tracks:
                        if st.language:
                            try:
                                embedded_subtitle_languages.add(Language.fromalpha3b(st.language))
                            except BabelfishError:
                                logger.log('Embedded subtitle track is not a valid language', logger.DEBUG)
                                embedded_subtitle_languages.add(Language('und'))
                        elif st.name:
                            try:
                                embedded_subtitle_languages.add(Language.fromname(st.name))
                            except BabelfishError:
                                logger.log('Embedded subtitle track is not a valid language', logger.DEBUG)
                                embedded_subtitle_languages.add(Language('und'))
                        else:
                            embedded_subtitle_languages.add(Language('und'))
                else:
                    logger.log('MKV has no subtitle track', logger.DEBUG)
            except MalformedMKVError:
                logger.log('MKV seems to be malformed, ignoring embedded subtitles', logger.WARNING)

    # 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))

    external_subtitle_languages = subliminal.video.scan_subtitle_languages(video_path)
    subtitle_languages = external_subtitle_languages.union(embedded_subtitle_languages)

    if (len(subtitle_languages) is 1 and len(wantedLanguages()) is 1) and Language('und') in subtitle_languages:
        subtitle_languages.remove(Language('und'))
        subtitle_languages.add(fromietf(wantedLanguages()[0]))

    for language in 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 checkLanguage(self, language):
        if not language:
            return None

        if len(language) < 2:
            self.log.error("Unable to set tag language, not enough characters [tag-language].")
            return None

        try:
            from babelfish import Language
        except:
            self.log.exception("Unable to important Language from babelfish [tag-language].")
            return None

        if len(language) == 2:
            try:
                return Language.fromalpha2(language).alpha3
                self.log.exception("Unable to set tag language [tag-language].")
            except:
                return None

        try:
            return Language(language).alpha3
        except:
            try:
                return Language.fromalpha3b(language).alpha3
            except:
                try:
                    return Language.fromalpha3t(language).alpha3
                except:
                    self.log.exception("Unable to set tag language [tag-language].")
        return None
Example #11
0
def getEmbeddedLanguages(video_path):
    embedded_subtitle_languages = set()
    try:
        with open(video_path, 'rb') as f:
            mkv = MKV(f)
            if mkv.subtitle_tracks:
                for st in mkv.subtitle_tracks:
                    if st.language:
                        try:
                            embedded_subtitle_languages.add(Language.fromalpha3b(st.language))
                        except BabelfishError:
                            logger.log('Embedded subtitle track is not a valid language', logger.DEBUG)
                            embedded_subtitle_languages.add(Language('und'))
                    elif st.name:
                        try:
                            embedded_subtitle_languages.add(Language.fromname(st.name))
                        except BabelfishError:
                            logger.log('Embedded subtitle track is not a valid language', logger.DEBUG)
                            embedded_subtitle_languages.add(Language('und'))
                    else:
                        embedded_subtitle_languages.add(Language('und'))
            else:
                logger.log('MKV has no subtitle track', logger.DEBUG)
    except MalformedMKVError:
        logger.log('MKV seems to be malformed, ignoring embedded subtitles', logger.WARNING)

    return embedded_subtitle_languages
Example #12
0
class BSPlayerProvider(Provider):
    """BSPlayer Provider.
    """
    languages = {
        Language.fromalpha3b(l)
        for l in language_converters['alpha3b'].codes
    }
    server_url = 'https://api.bsplayer.org/xml-rpc'
    user_agent = 'subliminal v%s' % __short_version__

    def __init__(self, search_url=None):
        self.server = ServerProxy(self.server_url, TimeoutSafeTransport(10))
        # None values not allowed for logging in, so replace it by ''
        self.token = None
        self.session = Session()
        self.search_url = search_url or get_sub_domain()

    def _api_request(self, func_name='logIn', params='', tries=5):
        headers = {
            'User-Agent':
            'BSPlayer/2.x (1022.12360)',
            'Content-Type':
            'text/xml; charset=utf-8',
            'Connection':
            'close',
            'SOAPAction':
            '"http://api.bsplayer-subtitles.com/v1.php#{func_name}"'.format(
                func_name=func_name)
        }
        data = (
            '<?xml version="1.0" encoding="UTF-8"?>\n'
            '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" '
            'xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" '
            'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
            'xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="{search_url}">'
            '<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">'
            '<ns1:{func_name}>{params}</ns1:{func_name}></SOAP-ENV:Body></SOAP-ENV:Envelope>'
        ).format(search_url=self.search_url,
                 func_name=func_name,
                 params=params)

        for i in xrange(tries):
            try:
                res = self.session.post(self.search_url,
                                        data=data,
                                        headers=headers)
                return ElementTree.fromstring(res.content)
            except Exception, ex:
                logger.error("[BSPlayer] ERROR: %s." % ex)
                if func_name == 'logIn':
                    self.search_url = get_sub_domain()
                sleep(1)
        logger.error('[BSPlayer] ERROR: Too many tries (%d)...' % tries)
Example #13
0
def get_embedded_subtitles(dirname, filename, log_scan=False):
    """Get the embedded subtitle languages for a video file.

    Based on subliminal.video.scan_video(...) but only keep the check for embedded subtitles.
    """
    log.debug('Checking for embedded subtitle(s)')

    embedded_subtitle_languages = set()
    path = os.path.join(dirname, filename)
    try:
        if filename.endswith('.mkv'):
            with open(path, mode='rb') as f:
                mkv = MKV(f)

            # subtitle tracks
            if mkv.subtitle_tracks:
                for st in mkv.subtitle_tracks:
                    if st.language:
                        try:
                            embedded_subtitle_languages.add(
                                Language.fromalpha3b(st.language))
                        except BabelfishError:
                            log_scan and log.error(
                                'Embedded subtitle track language %r is not a valid language',
                                st.language)
                    elif st.name:
                        try:
                            embedded_subtitle_languages.add(
                                Language.fromname(st.name))
                        except BabelfishError:
                            log_scan and log.error(
                                'Embedded subtitle track name %r is not a valid language',
                                st.name)
                    else:
                        log_scan and log.error(
                            'Embedded subtitle track language %r is not a valid language',
                            st.language)
                log_scan and log.debug(
                    'Found embedded subtitles %r with enzyme',
                    embedded_subtitle_languages)
            else:
                log_scan and log.debug('MKV has no subtitle track')
        else:
            log_scan and log.debug(
                'Check is only supported for MKV containers, skipping')
    except Exception:
        log_scan and log.error('Parsing video metadata with enzyme failed')

    return [
        Subtitle(EMBEDDED, text_type(language), path)
        for language in embedded_subtitle_languages
        if language != Language('und')
    ]
Example #14
0
    def query(self, languages, hash=None, size=None):
        # fill the search criteria
        root = self._api_request(
            func_name='searchSubtitles',
            params=('<handle>{token}</handle>'
                    '<movieHash>{movie_hash}</movieHash>'
                    '<movieSize>{movie_size}</movieSize>'
                    '<languageId>{language_ids}</languageId>'
                    '<imdbId>*</imdbId>').format(token=self.token,
                                                 movie_hash=hash,
                                                 movie_size=size,
                                                 language_ids=','.join(
                                                     map(
                                                         lambda l: l.alpha3,
                                                         languages))))
        res = root.find('.//return/result')
        if res.find('status').text != 'OK':
            return []

        items = root.findall('.//return/data/item')
        subtitles = []
        if items:
            for item in items:
                subtitle_id = item.find('subID').text
                size = item.find('subSize').text
                download_link = item.find('subDownloadLink').text
                language = Language.fromalpha3b(item.find('subLang').text)
                filename = item.find('subName').text
                subtitle_format = item.find('subFormat').text
                subtitle_hash = item.find('subHash').text
                rating = item.find('subRating').text
                season = item.find('season').text
                episode = item.find('episode').text
                encoding = item.find('encsubtitle').text
                imdb_id = item.find('movieIMBDID').text
                imdb_rating = item.find('movieIMBDRating').text
                movie_year = item.find('movieYear').text
                movie_name = item.find('movieName').text
                movie_hash = item.find('movieHash').text
                movie_size = item.find('movieSize').text
                movie_fps = item.find('movieFPS').text

                subtitle = BSPlayerSubtitle(
                    subtitle_id, size, download_link, language, filename,
                    subtitle_format, subtitle_hash, rating, season, episode,
                    encoding, imdb_id, imdb_rating, movie_year, movie_name,
                    movie_hash, movie_size, movie_fps)
                logger.debug('Found subtitle %s', subtitle)

                subtitles.append(subtitle)

        return subtitles
Example #15
0
    def handle(self, value, context):
        """Handle languages."""
        try:
            if len(value) == 3:
                return BabelfishLanguage.fromalpha3b(value)

            return BabelfishLanguage.fromietf(value)
        except (BabelfishError, ValueError):
            pass

        try:
            return BabelfishLanguage.fromname(value)
        except BabelfishError:
            pass

        logger.info('Invalid language: %r', value)
        return BabelfishLanguage('und')
Example #16
0
def _get_embedded_subtitles(dirname, filename):
    """
    Based on subliminal.video.scan_video(...) but only keep the check for embedded subtitles
    """
    log.debug("Checking for embedded subtitle")
    embedded_subtitle_languages = set()
    try:
        path = os.path.join(dirname, filename)
        if filename.endswith('.mkv'):
            with open(path, 'rb') as f:
                mkv = MKV(f)

            # subtitle tracks
            if mkv.subtitle_tracks:
                for st in mkv.subtitle_tracks:
                    if st.language:
                        try:
                            embedded_subtitle_languages.add(
                                Language.fromalpha3b(st.language))
                        except BabelfishError:
                            log.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:
                            log.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'))
                log.debug('Found embedded subtitles %r with enzyme',
                          embedded_subtitle_languages)
            else:
                log.debug('MKV has no subtitle track')
    except:
        log.exception('Parsing video metadata with enzyme failed')
    return embedded_subtitle_languages
Example #17
0
    def has_subtitle(self, language):
        """ Returns true if the video has already
        a subtitle for a specific language. """
        has_subtitle = False

        # Look for embedded subtitle in mkv video
        if Video.is_mkv(self.signature):
            with open(self.filename, 'rb') as file_handler:
                mkv_video = enzyme.MKV(file_handler)

            for sub in mkv_video.subtitle_tracks:
                try:
                    if sub.language and \
                            Language.fromalpha3b(sub.language) == language:
                        has_subtitle = True
                        break
                    elif sub.name and \
                            Language.fromname(sub.name) == language:
                        has_subtitle = True
                        break
                except BabelfishError:
                    LOG.error(
                        "Embedded subtitle track"
                        "language {} is not a valid language"
                        .format(sub.language))

        # Look for external subtitle
        dir_name = os.path.dirname(self.filename)
        base_name, _ = os.path.splitext(os.path.basename(self.filename))

        search_subtitle = os.path.join(
            dir_name, "{}.{}.*".format(base_name, language.alpha2))
        existing_subtitles = [
            sub_file for sub_file in glob.glob(search_subtitle)
            if os.path.splitext(sub_file)[1] in Subtitle.EXTENSIONS
        ]

        if existing_subtitles:
            has_subtitle = True

        return has_subtitle
Example #18
0
def get_embedded_subtitles(dirname, filename, log_scan=False):
    """Get the embedded subtitle languages for a video file.

    Based on subliminal.video.scan_video(...) but only keep the check for embedded subtitles.
    """
    log.debug('Checking for embedded subtitle(s)')

    embedded_subtitle_languages = set()
    path = os.path.join(dirname, filename)
    try:
        if filename.endswith('.mkv'):
            with open(path, mode='rb') as f:
                mkv = MKV(f)

            # subtitle tracks
            if mkv.subtitle_tracks:
                for st in mkv.subtitle_tracks:
                    if st.language:
                        try:
                            embedded_subtitle_languages.add(Language.fromalpha3b(st.language))
                        except BabelfishError:
                            log_scan and log.error('Embedded subtitle track language %r is not a valid language',
                                                   st.language)
                    elif st.name:
                        try:
                            embedded_subtitle_languages.add(Language.fromname(st.name))
                        except BabelfishError:
                            log_scan and log.error('Embedded subtitle track name %r is not a valid language', st.name)
                    else:
                        log_scan and log.error('Embedded subtitle track language %r is not a valid language',
                                               st.language)
                log_scan and log.debug('Found embedded subtitles %r with enzyme', embedded_subtitle_languages)
            else:
                log_scan and log.debug('MKV has no subtitle track')
        else:
            log_scan and log.debug('Check is only supported for MKV containers, skipping')
    except Exception:
        log_scan and log.error('Parsing video metadata with enzyme failed')

    return [Subtitle(EMBEDDED, text_type(language), path) for language in embedded_subtitle_languages if
            language != Language('und')]
Example #19
0
 def verify_embedded(self, tracks, language):
     track_match = False
     if tracks:
         for track in tracks:
             if track.language:
                 try:
                     current_language = Language.fromalpha3b(track.language)
                     if current_language == str(language):
                         track_match = True
                         break
                 except:
                     continue
             elif track.name:
                 try:
                     current_language = Language.fromname(track.name)
                     if current_language == str(language):
                         track_match = True
                         break
                 except:
                     continue
     return track_match
Example #20
0
    def has_subtitle(self, language):
        """ Returns true if the video has already
        a subtitle for a specific language. """
        has_subtitle = False

        # Look for embedded subtitle in mkv video
        if Video.is_mkv(self.signature):
            with open(self.filename, 'rb') as file_handler:
                mkv_video = enzyme.MKV(file_handler)

            for sub in mkv_video.subtitle_tracks:
                try:
                    if sub.language and \
                            Language.fromalpha3b(sub.language) == language:
                        has_subtitle = True
                        break
                    elif sub.name and \
                            Language.fromname(sub.name) == language:
                        has_subtitle = True
                        break
                except BabelfishError:
                    LOG.error("Embedded subtitle track"
                              "language {} is not a valid language".format(
                                  sub.language))

        # Look for external subtitle
        dir_name = os.path.dirname(self.filename)
        base_name, _ = os.path.splitext(os.path.basename(self.filename))

        search_subtitle = os.path.join(
            dir_name, "{}.{}.*".format(base_name, language.alpha2))
        existing_subtitles = [
            sub_file for sub_file in glob.glob(search_subtitle)
            if os.path.splitext(sub_file)[1] in Subtitle.EXTENSIONS
        ]

        if existing_subtitles:
            has_subtitle = True

        return has_subtitle
Example #21
0
def getAlpha3TCode(code, default=None):
    lang = default or UNDEFINED
    if not code or code == UNDEFINED:
        return lang

    code = code.strip().lower().replace('.', '')

    if len(code) == 3:
        try:
            lang = Language(code).alpha3t
        except:
            try:
                lang = Language.fromalpha3b(code).alpha3t
            except:
                try:
                    lang = Language.fromalpha3t(code).alpha3t
                except:
                    pass
    elif len(code) == 2:
        try:
            lang = Language.fromalpha2(code).alpha3t
        except:
            pass
    return lang
Example #22
0
class BSPlayerProvider(Provider):
    """BSPlayer Provider."""

    languages = {Language.fromalpha3b(l) for l in language_converters["alpha3b"].codes}
    server_url = "https://api.bsplayer.org/xml-rpc"
    user_agent = "subliminal v%s" % __short_version__

    def __init__(self, search_url=None):
        self.server = ServerProxy(self.server_url, TimeoutSafeTransport(10), context=make_context(settings.SSL_VERIFY))
        # None values not allowed for logging in, so replace it by ''
        self.token = None
        self.session = Session()
        self.search_url = search_url or get_sub_domain()

    def _api_request(self, func_name="logIn", params="", tries=5):
        headers = {
            "User-Agent": "BSPlayer/2.x (1022.12360)",
            "Content-Type": "text/xml; charset=utf-8",
            "Connection": "close",
            "SOAPAction": '"http://api.bsplayer-subtitles.com/v1.php#{func_name}"'.format(func_name=func_name),
        }
        data = (
            '<?xml version="1.0" encoding="UTF-8"?>\n'
            '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" '
            'xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" '
            'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
            f'xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="{self.search_url}">'
            '<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">'
            f"<ns1:{func_name}>{params}</ns1:{func_name}></SOAP-ENV:Body></SOAP-ENV:Envelope>"
        )

        for i in range(tries):
            try:
                res = self.session.post(self.search_url, data=data, headers=headers)
                return ElementTree.fromstring(res.content)
            except ElementTree.ParseError:
                logger.warning(f"[BSPlayer]: {res.content}")
            except Exception as ex:
                logger.error("[BSPlayer] ERROR: %s." % ex)
                if func_name == "logIn":
                    self.search_url = get_sub_domain()
                sleep(2)
        logger.error("[BSPlayer] ERROR: Too many tries (%d)..." % tries)

    def initialize(self):
        root = self._api_request(func_name="logIn", params=("<username></username>" "<password></password>" "<AppID>BSPlayer v2.67</AppID>"))
        res = root.find(".//return")
        if res.find("status").text == "OK":
            self.token = res.find("data").text

    def terminate(self):
        root = self._api_request(func_name="logOut", params=f"<handle>{self.token}</handle>")
        res = root.find(".//return")
        if res.find("status").text != "OK":
            logger.error("[BSPlayer] ERROR: Unable to close session.")
        self.token = None

    def query(self, languages, name_hash=None, size=None):
        # fill the search criteria
        root = self._api_request(
            func_name="searchSubtitles",
            params=(
                "<handle>{token}</handle>"
                "<movieHash>{movie_hash}</movieHash>"
                "<movieSize>{movie_size}</movieSize>"
                "<languageId>{language_ids}</languageId>"
                "<imdbId>*</imdbId>"
            ).format(token=self.token, movie_hash=name_hash, movie_size=size, language_ids=",".join([l.alpha3 for l in languages])),
        )
        res = root.find(".//return/result")
        if res.find("status").text != "OK":
            return []

        items = root.findall(".//return/data/item")
        subtitles = []
        if items:
            for item in items:
                subtitle_id = item.find("subID").text
                size = item.find("subSize").text
                download_link = item.find("subDownloadLink").text
                language = Language.fromalpha3b(item.find("subLang").text)
                filename = item.find("subName").text
                subtitle_source = item.find("subFormat").text
                subtitle_hash = item.find("subHash").text
                rating = item.find("subRating").text
                season = item.find("season").text
                episode = item.find("episode").text
                encoding = item.find("encsubtitle").text
                imdb_id = item.find("movieIMBDID").text
                imdb_rating = item.find("movieIMBDRating").text
                movie_year = item.find("movieYear").text
                movie_name = item.find("movieName").text
                movie_hash = item.find("movieHash").text
                movie_size = item.find("movieSize").text
                movie_fps = item.find("movieFPS").text

                subtitle = BSPlayerSubtitle(
                    subtitle_id,
                    size,
                    download_link,
                    language,
                    filename,
                    subtitle_source,
                    subtitle_hash,
                    rating,
                    season,
                    episode,
                    encoding,
                    imdb_id,
                    imdb_rating,
                    movie_year,
                    movie_name,
                    movie_hash,
                    movie_size,
                    movie_fps,
                )
                logger.debug("Found subtitle %s", subtitle)

                subtitles.append(subtitle)

        return subtitles

    def list_subtitles(self, video, languages):
        return self.query(languages, name_hash=self.hash_bsplayer(video.name), size=video.size)

    def download_subtitle(self, subtitle):
        logger.info("Downloading subtitle %r", subtitle)
        headers = {
            "User-Agent": "BSPlayer/2.x (1022.12360)",
            "Content-Length": "0",
        }

        response = self.session.get(subtitle.page_link, headers=headers)

        subtitle.content = fix_line_ending(zlib.decompress(response.content, 47))

    @staticmethod
    def hash_bsplayer(video_path):
        """Compute a hash using BSPlayer's algorithm.
        :param str video_path: path of the video.
        :return: the name_hash.
        :rtype: str
        """
        little_endian_long_long = "<q"  # little-endian long long
        byte_size = struct.calcsize(little_endian_long_long)

        with open(video_path, "rb") as f:
            file_size = os.path.getsize(video_path)
            file_hash = file_size

            if file_size < 65536 * 2:
                return

            for _ in range(65536 // byte_size):
                buff = f.read(byte_size)
                (l_value,) = struct.unpack(little_endian_long_long, buff)
                file_hash += l_value
                file_hash &= 0xFFFFFFFFFFFFFFFF  # to remain as 64bit number

            f.seek(max(0, file_size - 65536), 0)

            for x in range(65536 // byte_size):
                buff = f.read(byte_size)
                (l_value,) = struct.unpack(little_endian_long_long, buff)
                file_hash += l_value
                file_hash &= 0xFFFFFFFFFFFFFFFF

        return "%016x" % file_hash
Example #23
0
class BSPlayerProvider(Provider):
    """BSPlayer Provider.
    """
    languages = {Language.fromalpha3b(l) for l in language_converters['alpha3b'].codes}
    server_url = 'https://api.bsplayer.org/xml-rpc'
    user_agent = 'subliminal v%s' % __short_version__

    def __init__(self, search_url=None):
        self.server = ServerProxy(self.server_url, TimeoutSafeTransport(10))
        # None values not allowed for logging in, so replace it by ''
        self.token = None
        self.session = Session()
        self.search_url = search_url or get_sub_domain()

    def _api_request(self, func_name='logIn', params='', tries=5):
        headers = {
            'User-Agent': 'BSPlayer/2.x (1022.12360)',
            'Content-Type': 'text/xml; charset=utf-8',
            'Connection': 'close',
            'SOAPAction': '"http://api.bsplayer-subtitles.com/v1.php#{func_name}"'.format(func_name=func_name)
        }
        data = (
            '<?xml version="1.0" encoding="UTF-8"?>\n'
            '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" '
            'xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" '
            'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
            'xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="{search_url}">'
            '<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">'
            '<ns1:{func_name}>{params}</ns1:{func_name}></SOAP-ENV:Body></SOAP-ENV:Envelope>'
        ).format(search_url=self.search_url, func_name=func_name, params=params)

        for i in range(tries):
            try:
                res = self.session.post(self.search_url, data=data, headers=headers)
                return ElementTree.fromstring(res.content)
            except Exception as ex:
                logger.error("[BSPlayer] ERROR: %s." % ex)
                if func_name == 'logIn':
                    self.search_url = get_sub_domain()
                sleep(1)
        logger.error('[BSPlayer] ERROR: Too many tries (%d)...' % tries)

    def initialize(self):
        root = self._api_request(
            func_name='logIn',
            params=('<username></username>'
                    '<password></password>'
                    '<AppID>BSPlayer v2.67</AppID>')
        )
        res = root.find('.//return')
        if res.find('status').text == 'OK':
            self.token = res.find('data').text

    def terminate(self):
        root = self._api_request(
            func_name='logOut',
            params='<handle>{token}</handle>'.format(token=self.token)
        )
        res = root.find('.//return')
        if res.find('status').text != 'OK':
            logger.error('[BSPlayer] ERROR: Unable to close session.')
        self.token = None

    def query(self, languages, hash=None, size=None):
        # fill the search criteria
        root = self._api_request(
            func_name='searchSubtitles',
            params=(
                '<handle>{token}</handle>'
                '<movieHash>{movie_hash}</movieHash>'
                '<movieSize>{movie_size}</movieSize>'
                '<languageId>{language_ids}</languageId>'
                '<imdbId>*</imdbId>'
            ).format(token=self.token, movie_hash=hash,
                     movie_size=size, language_ids=','.join(map(lambda l: l.alpha3, languages)))
        )
        res = root.find('.//return/result')
        if res.find('status').text != 'OK':
            return []

        items = root.findall('.//return/data/item')
        subtitles = []
        if items:
            for item in items:
                subtitle_id = item.find('subID').text
                size = item.find('subSize').text
                download_link = item.find('subDownloadLink').text
                language = Language.fromalpha3b(item.find('subLang').text)
                filename = item.find('subName').text
                subtitle_format = item.find('subFormat').text
                subtitle_hash = item.find('subHash').text
                rating = item.find('subRating').text
                season = item.find('season').text
                episode = item.find('episode').text
                encoding = item.find('encsubtitle').text
                imdb_id = item.find('movieIMBDID').text
                imdb_rating = item.find('movieIMBDRating').text
                movie_year = item.find('movieYear').text
                movie_name = item.find('movieName').text
                movie_hash = item.find('movieHash').text
                movie_size = item.find('movieSize').text
                movie_fps = item.find('movieFPS').text

                subtitle = BSPlayerSubtitle(subtitle_id, size, download_link, language, filename, subtitle_format,
                                            subtitle_hash, rating, season, episode, encoding, imdb_id, imdb_rating,
                                            movie_year, movie_name, movie_hash, movie_size, movie_fps)
                logger.debug('Found subtitle %s', subtitle)

                subtitles.append(subtitle)

        return subtitles

    def list_subtitles(self, video, languages):
        return self.query(languages, hash=self.hash_bsplayer(video.name), size=video.size)

    def download_subtitle(self, subtitle):
        logger.info('Downloading subtitle %r', subtitle)
        headers = {
            'User-Agent': 'BSPlayer/2.x (1022.12360)',
            'Content-Length': '0',
        }

        response = self.session.get(subtitle.page_link, headers=headers)

        subtitle.content = fix_line_ending(zlib.decompress(response.content, 47))

    def hash_bsplayer(self, video_path):
        """Compute a hash using BSPlayer's algorithm.
        :param str video_path: path of the video.
        :return: the hash.
        :rtype: str
        """
        little_endian_long_long = '<q'  # little-endian long long
        byte_size = struct.calcsize(little_endian_long_long)

        with open(video_path, 'rb') as f:
            file_size = os.path.getsize(video_path)
            file_hash = file_size

            if file_size < 65536 * 2:
                return

            for _ in range(65536 // byte_size):
                buff = f.read(byte_size)
                (l_value,) = struct.unpack(little_endian_long_long, buff)
                file_hash += l_value
                file_hash &= 0xFFFFFFFFFFFFFFFF  # to remain as 64bit number

            f.seek(max(0, file_size - 65536), 0)

            for x in range(65536 // byte_size):
                buff = f.read(byte_size)
                (l_value,) = struct.unpack(little_endian_long_long, buff)
                file_hash += l_value
                file_hash &= 0xFFFFFFFFFFFFFFFF

        return "%016x" % file_hash
Example #24
0
def scan_video(path, subtitles=True, embedded_subtitles=True, subtitles_dir=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.
    :param str subtitles_dir: directory to search for subtitles.
    :return: the scanned video.
    :rtype: :class:`Video`

    """
    # 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 %r in %r', filename, dirpath)

    # guess
    video = Video.fromguess(path, guessit(path))

    # 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)
        video.hashes['napiprojekt'] = hash_napiprojekt(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(search_external_subtitles(path, directory=subtitles_dir).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:
        logger.exception('Parsing video metadata with enzyme failed')

    return video
Example #25
0
    def fromalpha3b(cls, s):
        if s in repl_map:
            s = repl_map[s]
            return Language(*Language_.fromietf(s).__getstate__())

        return Language(*Language_.fromalpha3b(s).__getstate__())
Example #26
0
def scan_video(path, subtitles=True, embedded_subtitles=True):
    """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`

    """
    # 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 %r in %r', filename, dirpath)

    # guess
    video = Video.fromguess(path, guess_file_info(path))

    # 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(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
Example #27
0
def parse_video(fn,
                video_info,
                hints,
                external_subtitles=False,
                embedded_subtitles=False,
                known_embedded=None,
                forced_only=False,
                no_refining=False,
                dry_run=False,
                ignore_all=False,
                stored_subs=None):

    logger.debug("Parsing video: %s, hints: %s", os.path.basename(fn), hints)
    video = scan_video(fn,
                       hints=hints,
                       dont_use_actual_file=dry_run or no_refining)

    if no_refining:
        logger.debug("Taking parse_video shortcut")
        return video

    # refiners

    refine_kwargs = {
        "episode_refiners": ('tvdb', 'sz_omdb'),
        "movie_refiners": ('sz_omdb', ),
        "embedded_subtitles": False,
    }

    # our own metadata refiner :)
    if "stream" in video_info:
        for key, value in video_info["stream"].iteritems():
            if hasattr(video, key) and not getattr(video, key):
                logger.info(u"Adding stream %s info: %s", key, value)
                setattr(video, key, value)

    plex_title = video_info.get("original_title") or video_info.get("title")
    if hints["type"] == "episode":
        plex_title = video_info.get("original_title") or video_info.get(
            "series")

    year = video_info.get("year")
    if not video.year and year:
        logger.info(u"Adding PMS year info: %s", year)
        video.year = year

    refine(video, **refine_kwargs)

    if hints["type"] == "movie" and not video.imdb_id:
        if plex_title:
            logger.info(u"Adding PMS title/original_title info: %s",
                        plex_title)
            old_title = video.title
            video.title = plex_title.replace(" - ", " ").replace(" -",
                                                                 " ").replace(
                                                                     "- ", " ")

            # re-refine with new info
            logger.info(u"Re-refining with movie title: '%s' instead of '%s'",
                        plex_title, old_title)
            refine(video, **refine_kwargs)

        # still no match? add our own data
        if not video.imdb_id:
            video.imdb_id = video_info.get("imdb_id")
            if video.imdb_id:
                logger.info(u"Adding PMS imdb_id info: %s", video.imdb_id)

    if hints["type"] == "episode":
        if not video.series_tvdb_id and not video.tvdb_id and plex_title:
            # add our title
            logger.info(u"Adding PMS title/original_title info: %s",
                        plex_title)
            old_title = video.series
            video.series = plex_title

            # re-refine with new info
            logger.info(u"Re-refining with series title: '%s' instead of '%s'",
                        plex_title, old_title)
            refine(video, **refine_kwargs)

        # still no match? add our own data
        if not video.series_tvdb_id:
            logger.info(u"Adding PMS series_tvdb_id info: %s",
                        video_info.get("series_tvdb_id"))
            video.series_tvdb_id = video_info.get("series_tvdb_id")

        if not video.tvdb_id:
            logger.info(u"Adding PMS tvdb_id info: %s",
                        video_info.get("tvdb_id"))
            video.tvdb_id = video_info.get("tvdb_id")

    # did it match?
    if (hints["type"] == "episode" and not video.series_tvdb_id
            and not video.tvdb_id
            and not video.series_imdb_id) or (hints["type"] == "movie"
                                              and not video.imdb_id):
        logger.warning(
            "Couldn't find corresponding series/movie in online databases, continuing"
        )

    # scan for external subtitles
    external_langs_found = set(
        search_external_subtitles(video.name, forced_tag=forced_only).values())

    # found external subtitles should be considered?
    if external_subtitles:
        # |= is update, thanks plex
        video.subtitle_languages.update(external_langs_found)

    else:
        # did we already download subtitles for this?
        if not ignore_all and stored_subs and external_langs_found:
            for lang in external_langs_found:
                if has_external_subtitle(video_info["plex_part"].id,
                                         stored_subs, lang):
                    logger.info(
                        "Not re-downloading subtitle for language %s, it already exists on the filesystem",
                        lang)
                    video.subtitle_languages.add(lang)

    # add known embedded subtitles
    if embedded_subtitles and known_embedded:
        embedded_subtitle_languages = set()
        # mp4 and stuff, check burned in
        for language in known_embedded:
            try:
                embedded_subtitle_languages.add(Language.fromalpha3b(language))
            except LanguageError:
                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.update(embedded_subtitle_languages)

    # guess special
    if hints["type"] == "episode":
        if video.season == 0 or video.episode == 0:
            video.is_special = True
        else:
            # check parent folder name
            if os.path.dirname(fn).split(
                    os.path.sep)[-1].lower() in ("specials", "season 00"):
                video.is_special = True

    return video
Example #28
0
    def fromalpha3b(cls, s):
        if s in repl_map:
            s = repl_map[s]
            return Language_.fromietf(s)

        return Language_.fromalpha3b(s)
Example #29
0
def refine(video, embedded_subtitles=True, **kwargs):
    """Refine a video by searching its metadata.

    Several :class:`~subliminal.video.Video` attributes can be found:

      * :attr:`~subliminal.video.Video.resolution`
      * :attr:`~subliminal.video.Video.video_codec`
      * :attr:`~subliminal.video.Video.audio_codec`
      * :attr:`~subliminal.video.Video.subtitle_languages`

    :param bool embedded_subtitles: search for embedded subtitles.

    """
    # skip non existing videos
    if not video.exists:
        return

    # check extensions
    extension = os.path.splitext(video.name)[1]
    if extension == '.mkv':
        with open(video.name, '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', video.resolution)

            # video codec
            if video_track.codec_id == 'V_MPEG4/ISO/AVC':
                video.video_codec = 'H.264'
                logger.debug('Found video_codec %s', video.video_codec)
            elif video_track.codec_id == 'V_MPEG4/ISO/SP':
                video.video_codec = 'DivX'
                logger.debug('Found video_codec %s', video.video_codec)
            elif video_track.codec_id == 'V_MPEG4/ISO/ASP':
                video.video_codec = 'Xvid'
                logger.debug('Found video_codec %s', 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 = 'Dolby Digital'
                logger.debug('Found audio_codec %s', video.audio_codec)
            elif audio_track.codec_id == 'A_DTS':
                video.audio_codec = 'DTS'
                logger.debug('Found audio_codec %s', video.audio_codec)
            elif audio_track.codec_id == 'A_AAC':
                video.audio_codec = 'AAC'
                logger.debug('Found audio_codec %s', 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',
                             embedded_subtitle_languages)
                video.subtitle_languages |= embedded_subtitle_languages
        else:
            logger.debug('MKV has no subtitle track')
    else:
        logger.debug('Unsupported video extension %s', extension)
Example #30
0
def refine(video, embedded_subtitles=True, **kwargs):
    """Refine a video by searching its metadata.

    Several :class:`~subliminal.video.Video` attributes can be found:

      * :attr:`~subliminal.video.Video.resolution`
      * :attr:`~subliminal.video.Video.video_codec`
      * :attr:`~subliminal.video.Video.audio_codec`
      * :attr:`~subliminal.video.Video.subtitle_languages`

    :param bool embedded_subtitles: search for embedded subtitles.

    """
    # skip non existing videos
    if not video.exists:
        return

    # check extensions
    extension = os.path.splitext(video.name)[1]
    if extension == '.mkv':
        with open(video.name, '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', video.resolution)

            # video codec
            if video_track.codec_id == 'V_MPEG4/ISO/AVC':
                video.video_codec = 'H.264'
                logger.debug('Found video_codec %s', video.video_codec)
            elif video_track.codec_id == 'V_MPEG4/ISO/SP':
                video.video_codec = 'DivX'
                logger.debug('Found video_codec %s', video.video_codec)
            elif video_track.codec_id == 'V_MPEG4/ISO/ASP':
                video.video_codec = 'Xvid'
                logger.debug('Found video_codec %s', 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 = 'Dolby Digital'
                logger.debug('Found audio_codec %s', video.audio_codec)
            elif audio_track.codec_id == 'A_DTS':
                video.audio_codec = 'DTS'
                logger.debug('Found audio_codec %s', video.audio_codec)
            elif audio_track.codec_id == 'A_AAC':
                video.audio_codec = 'AAC'
                logger.debug('Found audio_codec %s', 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', embedded_subtitle_languages)
                video.subtitle_languages |= embedded_subtitle_languages
        else:
            logger.debug('MKV has no subtitle track')
    else:
        logger.debug('Unsupported video extension %s', extension)
Example #31
0
    def fromalpha3b(cls, s):
        if s in repl_map:
            s = repl_map[s]
            return Language(*Language_.fromietf(s).__getstate__())

        return Language(*Language_.fromalpha3b(s).__getstate__())
Example #32
0
    def query(self, languages, name_hash=None, size=None):
        # fill the search criteria
        root = self._api_request(
            func_name="searchSubtitles",
            params=(
                "<handle>{token}</handle>"
                "<movieHash>{movie_hash}</movieHash>"
                "<movieSize>{movie_size}</movieSize>"
                "<languageId>{language_ids}</languageId>"
                "<imdbId>*</imdbId>"
            ).format(token=self.token, movie_hash=name_hash, movie_size=size, language_ids=",".join([l.alpha3 for l in languages])),
        )
        res = root.find(".//return/result")
        if res.find("status").text != "OK":
            return []

        items = root.findall(".//return/data/item")
        subtitles = []
        if items:
            for item in items:
                subtitle_id = item.find("subID").text
                size = item.find("subSize").text
                download_link = item.find("subDownloadLink").text
                language = Language.fromalpha3b(item.find("subLang").text)
                filename = item.find("subName").text
                subtitle_source = item.find("subFormat").text
                subtitle_hash = item.find("subHash").text
                rating = item.find("subRating").text
                season = item.find("season").text
                episode = item.find("episode").text
                encoding = item.find("encsubtitle").text
                imdb_id = item.find("movieIMBDID").text
                imdb_rating = item.find("movieIMBDRating").text
                movie_year = item.find("movieYear").text
                movie_name = item.find("movieName").text
                movie_hash = item.find("movieHash").text
                movie_size = item.find("movieSize").text
                movie_fps = item.find("movieFPS").text

                subtitle = BSPlayerSubtitle(
                    subtitle_id,
                    size,
                    download_link,
                    language,
                    filename,
                    subtitle_source,
                    subtitle_hash,
                    rating,
                    season,
                    episode,
                    encoding,
                    imdb_id,
                    imdb_rating,
                    movie_year,
                    movie_name,
                    movie_hash,
                    movie_size,
                    movie_fps,
                )
                logger.debug("Found subtitle %s", subtitle)

                subtitles.append(subtitle)

        return subtitles
Example #33
0
def subtitlesLanguages(video_path):
    """Return a list detected subtitles for the given video file"""
    resultList = []
    embedded_subtitle_languages = set()

    # Serch for embedded subtitles
    if not sickbeard.EMBEDDED_SUBTITLES_ALL:
        if video_path.endswith('mkv'):
            try:
                with open(video_path.encode(sickbeard.SYS_ENCODING),
                          'rb') as f:
                    mkv = MKV(f)
                if mkv.subtitle_tracks:
                    for st in mkv.subtitle_tracks:
                        if st.language:
                            try:
                                embedded_subtitle_languages.add(
                                    Language.fromalpha3b(st.language))
                            except BabelfishError:
                                logger.log(
                                    'Embedded subtitle track is not a valid language',
                                    logger.DEBUG)
                                embedded_subtitle_languages.add(
                                    Language('und'))
                        elif st.name:
                            try:
                                embedded_subtitle_languages.add(
                                    Language.fromname(st.name))
                            except BabelfishError:
                                logger.log(
                                    'Embedded subtitle track is not a valid language',
                                    logger.DEBUG)
                                embedded_subtitle_languages.add(
                                    Language('und'))
                        else:
                            embedded_subtitle_languages.add(Language('und'))
                else:
                    logger.log('MKV has no subtitle track', logger.DEBUG)
            except MalformedMKVError:
                logger.log(
                    'MKV seems to be malformed, ignoring embedded subtitles',
                    logger.WARNING)

    # 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))

    external_subtitle_languages = subliminal.video.scan_subtitle_languages(
        video_path)
    subtitle_languages = external_subtitle_languages.union(
        embedded_subtitle_languages)

    if (len(subtitle_languages) is 1 and len(wantedLanguages()) is 1
        ) and Language('und') in subtitle_languages:
        subtitle_languages.remove(Language('und'))
        subtitle_languages.add(fromietf(wantedLanguages()[0]))

    for language in 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)
Example #34
0
def scan_video(path, subtitles=True, embedded_subtitles=True, subtitles_dir=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.
    :param str subtitles_dir: directory to search for subtitles.
    :return: the scanned video.
    :rtype: :class:`Video`

    """
    # 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 %r in %r", filename, dirpath)

    # guess
    video = Video.fromguess(path, guess_file_info(path))

    # 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)
        video.hashes["napiprojekt"] = hash_napiprojekt(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(search_external_subtitles(path, directory=subtitles_dir).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:
        logger.exception("Parsing video metadata with enzyme failed")

    return video