Immutable value object representing a video such as MP4.
| 12 | |
| 13 | |
| 14 | class Video(object): |
| 15 | """Immutable value object representing a video such as MP4.""" |
| 16 | |
| 17 | def __init__(self, blob: bytes, mime_type: str | None, filename: str | None): |
| 18 | super(Video, self).__init__() |
| 19 | self._blob = blob |
| 20 | self._mime_type = mime_type |
| 21 | self._filename = filename |
| 22 | |
| 23 | @classmethod |
| 24 | def from_blob(cls, blob: bytes, mime_type: str | None, filename: str | None = None): |
| 25 | """Return a new |Video| object loaded from image binary in *blob*.""" |
| 26 | return cls(blob, mime_type, filename) |
| 27 | |
| 28 | @classmethod |
| 29 | def from_path_or_file_like(cls, movie_file: str | IO[bytes], mime_type: str | None) -> Video: |
| 30 | """Return a new |Video| object containing video in *movie_file*. |
| 31 | |
| 32 | *movie_file* can be either a path (string) or a file-like |
| 33 | (e.g. StringIO) object. |
| 34 | """ |
| 35 | if isinstance(movie_file, str): |
| 36 | # treat movie_file as a path |
| 37 | with open(movie_file, "rb") as f: |
| 38 | blob = f.read() |
| 39 | filename = os.path.basename(movie_file) |
| 40 | else: |
| 41 | # assume movie_file is a file-like object |
| 42 | blob = movie_file.read() |
| 43 | filename = None |
| 44 | |
| 45 | return cls.from_blob(blob, mime_type, filename) |
| 46 | |
| 47 | @property |
| 48 | def blob(self): |
| 49 | """The bytestream of the media "file".""" |
| 50 | return self._blob |
| 51 | |
| 52 | @property |
| 53 | def content_type(self): |
| 54 | """MIME-type of this media, e.g. `'video/mp4'`.""" |
| 55 | return self._mime_type |
| 56 | |
| 57 | @property |
| 58 | def ext(self): |
| 59 | """Return the file extension for this video, e.g. 'mp4'. |
| 60 | |
| 61 | The extension is that from the actual filename if known. Otherwise |
| 62 | it is the lowercase canonical extension for the video's MIME type. |
| 63 | 'vid' is used if the MIME type is 'video/unknown'. |
| 64 | """ |
| 65 | if self._filename: |
| 66 | return os.path.splitext(self._filename)[1].lstrip(".") |
| 67 | return { |
| 68 | CT.ASF: "asf", |
| 69 | CT.AVI: "avi", |
| 70 | CT.MOV: "mov", |
| 71 | CT.MP4: "mp4", |
no outgoing calls
searching dependent graphs…