예제 #1
0
 def get_video_codec(self):
     return Text(self.__json__["video_codec"])
예제 #2
0
 def get_video_codec_description(self):
     return Text(self.__json__["video_codec_description"])
예제 #3
0
 def get_device_name(self):
     return Text(self.__json__["device_name"])
예제 #4
0
 def get_meta_title(self):
     return Text(html_to_title(self.__json__["meta_title"]))
예제 #5
0
 def get_container_format(self):
     return Text(self.__json__["container_format"])
예제 #6
0
 def get_audio_codec_description(self):
     return Text(self.__json__["audio_codec_description"])
예제 #7
0
 def get_audio_codec(self):
     return Text(self.__json__["audio_codec"])
예제 #8
0
class Video(VideoState):
    unreadable: "U" = False
    # Video optional arguments
    audio_bit_rate: "r" = 0
    audio_codec: "a" = ""
    audio_codec_description: "A" = ""
    bit_depth: "D" = 0
    channels: "C" = 2
    container_format: "c" = ""
    device_name: "b" = ""
    duration: "d" = 0.0
    duration_time_base: "t" = 0
    frame_rate_den: "y" = 0
    frame_rate_num: "x" = 0
    height: "h" = 0
    meta_title: "n" = ""
    properties: "p" = {}
    sample_rate: "u" = 0
    similarity_id: ("S", int) = None
    video_codec: "v" = ""
    video_codec_description: "V" = ""
    width: "w" = 0
    audio_languages: "l" = []
    subtitle_languages: "L" = []

    __slots__ = ("database", )

    def __init__(self, database, **kwargs):
        super().__init__(**kwargs)
        self.__json__["duration"] = abs(self.__json__["duration"])
        self.__json__[
            "duration_time_base"] = self.__json__["duration_time_base"] or 1
        self.__json__["frame_rate_den"] = self.__json__["frame_rate_den"] or 1
        # Runtime
        self.database = database
        # Additional initialization.
        self.update_properties(self.__json__["properties"])

    def get_audio_codec(self):
        return Text(self.__json__["audio_codec"])

    def get_audio_codec_description(self):
        return Text(self.__json__["audio_codec_description"])

    def get_container_format(self):
        return Text(self.__json__["container_format"])

    def get_device_name(self):
        return Text(self.__json__["device_name"])

    def get_meta_title(self):
        return Text(html_to_title(self.__json__["meta_title"]))

    def get_video_codec(self):
        return Text(self.__json__["video_codec"])

    def get_video_codec_description(self):
        return Text(self.__json__["video_codec_description"])

    def get_thumb_name(self):
        thumb_name = self.__json__["thumb_name"]
        if not thumb_name:
            thumb_name = db_utils.generate_thumb_name(self.filename)
            self.__json__["thumb_name"] = thumb_name
        return thumb_name

    def set_properties(self, properties: dict):
        self.__json__["properties"] = {
            key: self.database.get_prop_type(key)(value)
            for key, value in properties.items()
        }

    def extract_attributes(self, keys: Iterable[str]) -> Dict[str, Any]:
        output = {}
        for key in keys:
            if key.startswith(":"):
                prop_name = key[1:]
                output.setdefault("properties",
                                  {})[prop_name] = self.properties[prop_name]
            else:
                output[key] = getattr(self, key)
        return output

    frame_rate = property(
        lambda self: self.frame_rate_num / self.frame_rate_den)
    length = property(lambda self: Duration(
        round(self.duration * 1000000 / self.duration_time_base)))
    title = property(lambda self: self.meta_title
                     if self.meta_title else Text(self.filename.file_title))
    title_numeric = property(lambda self: self.meta_title_numeric
                             if self.meta_title else self.file_title_numeric)
    filename_numeric = property(lambda self: SemanticText(self.filename.path))
    meta_title_numeric = property(
        lambda self: SemanticText(self.meta_title.value))
    raw_seconds = property(
        lambda self: self.duration / self.duration_time_base)
    raw_microseconds = property(
        lambda self: self.duration * 1000000 / self.duration_time_base)
    thumbnail_path = property(lambda self: db_utils.generate_thumb_path(
        self.database.thumbnail_folder, self.thumb_name))
    quality = property(lambda self: self.database.quality_attribute(self))
    move_id = property(lambda self: self.database.moves_attribute(self)[0])

    @property
    def quality_compression(self):
        basic_file_size = (
            self.width * self.height * self.frame_rate * 3 +
            self.sample_rate * self.channels * 2) * self.raw_seconds
        return self.file_size / basic_file_size

    @property
    def moves(self):
        return [{
            "video_id": video.video_id,
            "filename": video.filename
        } for video in self.database.moves_attribute(self)[1]]

    def terms(self, as_set=False):
        term_sources = [self.filename.path, str(self.meta_title)]
        for prop in self.database.get_prop_types():
            if prop.type is str and prop.name in self.properties:
                val = self.properties[prop.name]
                if prop.multiple:
                    term_sources.extend(val)
                else:
                    term_sources.append(val)
        return string_to_pieces(" ".join(term_sources), as_set=as_set)

    @staticmethod
    def has_terms_exact(self, terms):
        # type: (Video, Sequence[str]) -> bool
        return " ".join(terms) in " ".join(self.terms())

    @staticmethod
    def has_terms_and(self, terms):
        # type: (Video, Sequence[str]) -> bool
        video_terms = self.terms(as_set=True)
        return all(term in video_terms for term in terms)

    @staticmethod
    def has_terms_or(self, terms):
        # type: (Video, Sequence[str]) -> bool
        video_terms = self.terms(as_set=True)
        return any(term in video_terms for term in terms)

    @staticmethod
    def has_terms_id(self, terms):
        # type: (Video, Sequence[str]) -> bool
        (term, ) = terms
        return self.video_id == int(term)

    def update_properties(self, properties: dict) -> Set[str]:
        modified = set()
        for name, value in properties.items():
            if self.update_property(name, value):
                modified.add(name)
        return modified

    def update_property(self, name, value):
        value = self.database.get_prop_type(name)(value)
        modified = name not in self.properties or self.properties[name] != value
        self.properties[name] = value
        return modified
예제 #9
0
class VideoState(Jsonable):
    filename: ("f", str) = None
    file_size: "s" = 0
    errors: "e" = set()
    video_id: ("j", int) = None
    runtime: ("R", VideoRuntimeInfo) = {}
    unreadable: "U" = True
    thumb_name: "i" = ""
    __slots__ = ("discarded", )
    __protected__ = ("database", "runtime", "discarded")

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.discarded = False

    def __str__(self):
        cls = type(self)
        with StringPrinter() as printer:
            printer.write(f"{cls.__name__} {self.video_id}:")
            for field in class_get_public_attributes(cls):
                printer.write(f"\t{field}: {getattr(self, field)}")
            return str(printer)

    def __hash__(self):
        return hash(self.filename)

    def __eq__(self, other):
        return self.filename == other.filename

    def __lt__(self, other):
        return self.filename < other.filename

    def get_filename(self):
        return AbsolutePath(self.__json__["filename"])

    def set_filename(self, data):
        assert isinstance(data, (str, AbsolutePath))
        self.__json__["filename"] = str(data)

    def get_thumb_name(self):
        from pysaurus.database.db_utils import generate_thumb_name

        return generate_thumb_name(self.filename)

    def to_dict_errors(self, errors):
        return list(errors)

    @classmethod
    def from_dict_errors(cls, errors):
        return set(errors)

    extension = property(lambda self: self.filename.extension)
    file_title = property(lambda self: Text(self.filename.file_title))
    file_title_numeric = property(
        lambda self: SemanticText(self.filename.file_title))
    size = property(lambda self: FileSize(self.file_size))
    day = property(lambda self: self.date.day)
    # runtime attributes
    disk = property(
        lambda self: self.filename.get_drive_name() or self.runtime.driver_id)
    date = property(lambda self: DateModified(self.runtime.mtime))
    has_thumbnail = property(lambda self: not self.unreadable_thumbnail and
                             self.runtime.has_thumbnail)

    readable = property(lambda self: not self.unreadable)
    found = property(lambda self: self.runtime.is_file)
    not_found = property(lambda self: not self.runtime.is_file)
    with_thumbnails = property(lambda self: self.has_thumbnail)
    without_thumbnails = property(lambda self: not self.has_thumbnail)

    @property
    def unreadable_thumbnail(self):
        return PYTHON_ERROR_THUMBNAIL in self.errors

    @unreadable_thumbnail.setter
    def unreadable_thumbnail(self, has_error):
        if has_error:
            self.errors.add(PYTHON_ERROR_THUMBNAIL)
        elif PYTHON_ERROR_THUMBNAIL in self.errors:
            self.errors.remove(PYTHON_ERROR_THUMBNAIL)

    def terms(self, as_set=False):
        return string_to_pieces(self.filename.path, as_set=as_set)

    def to_comparable(self, sorting: VideoSorting) -> list:
        return [
            to_comparable(getattr(self, field), reverse)
            for field, reverse in sorting
        ]

    @classmethod
    def is_flag(cls, name):
        return name in {
            "readable",
            "unreadable",
            "found",
            "not_found",
            "with_thumbnails",
            "without_thumbnails",
        }