def __init__(self, stream: Dict, player_config_args: Dict, monostate: Monostate): """Construct a :class:`Stream <Stream>`. :param dict stream: The unscrambled data extracted from YouTube. :param dict player_config_args: The data object containing video media data like title and keywords. :param dict monostate: Dictionary of data shared across all instances of :class:`Stream <Stream>`. """ # A dictionary shared between all instances of :class:`Stream <Stream>` # (Borg pattern). self._monostate = monostate self.url = stream["url"] # signed download url self.itag = int(stream["itag"]) # stream format id (youtube nomenclature) self.type = stream[ "type" ] # the part of the mime before the slash, overwritten later self.abr = None # average bitrate (audio streams only) self.fps = None # frames per second (video streams only) self.res = None # resolution (e.g.: 480p, 720p, 1080p) self._filesize: Optional[int] = None # filesize in bytes self.mime_type = None # content identifier (e.g.: video/mp4) self.subtype = None # the part of the mime after the slash self.codecs: List[str] = [] # audio/video encoders (e.g.: vp8, mp4a) self.audio_codec = None # audio codec of the stream (e.g.: vorbis) self.video_codec = None # video codec of the stream (e.g.: vp8) # Iterates over the key/values of stream and sets them as class # attributes. This is an anti-pattern and should be removed. self.set_attributes_from_dict(stream) # Additional information about the stream format, such as resolution, # frame rate, and whether the stream is live (HLS) or 3D. self.fmt_profile: Dict = get_format_profile(self.itag) # Same as above, except for the format profile attributes. self.set_attributes_from_dict(self.fmt_profile) # The player configuration which contains information like the video # title. # TODO(nficano): this should be moved to the monostate. self.player_config_args = player_config_args # 'video/webm; codecs="vp8, vorbis"' -> 'video/webm', ['vp8', 'vorbis'] self.mime_type, self.codecs = extract.mime_type_codec(self.type) # 'video/webm' -> 'video', 'webm' self.type, self.subtype = self.mime_type.split("/") # ['vp8', 'vorbis'] -> video_codec: vp8, audio_codec: vorbis. DASH # streams return NoneType for audio/video depending. self.video_codec, self.audio_codec = self.parse_codecs()
def __init__( self, stream: Dict, player_config_args: Dict, monostate: Monostate ): """Construct a :class:`Stream <Stream>`. :param dict stream: The unscrambled data extracted from YouTube. :param dict player_config_args: The data object containing video media data like title and keywords. :param dict monostate: Dictionary of data shared across all instances of :class:`Stream <Stream>`. """ # A dictionary shared between all instances of :class:`Stream <Stream>` # (Borg pattern). self._monostate = monostate self.url = stream["url"] # signed download url self.itag = int( stream["itag"] ) # stream format id (youtube nomenclature) # set type and codec info # 'video/webm; codecs="vp8, vorbis"' -> 'video/webm', ['vp8', 'vorbis'] self.mime_type, self.codecs = extract.mime_type_codec(stream["type"]) # 'video/webm' -> 'video', 'webm' self.type, self.subtype = self.mime_type.split("/") # ['vp8', 'vorbis'] -> video_codec: vp8, audio_codec: vorbis. DASH # streams return NoneType for audio/video depending. self.video_codec, self.audio_codec = self.parse_codecs() self.is_otf: bool = stream["is_otf"] self.bitrate: Optional[int] = stream["bitrate"] self._filesize: Optional[int] = None # filesize in bytes # Additional information about the stream format, such as resolution, # frame rate, and whether the stream is live (HLS) or 3D. itag_profile = get_format_profile(self.itag) self.is_dash = itag_profile["is_dash"] self.abr = itag_profile["abr"] # average bitrate (audio streams only) self.fps = stream[ "fps" ] # frames per second (video streams only) self.resolution = itag_profile[ "resolution" ] # resolution (e.g.: "480p") self.is_3d = itag_profile["is_3d"] self.is_hdr = itag_profile["is_hdr"] self.is_live = itag_profile["is_live"] # The player configuration, contains info like the video title. self.player_config_args = player_config_args
def __init__(self, stream, player_config_args, monostate): """Construct a :class:`Stream <Stream>`. :param dict stream: The unscrambled data extracted from YouTube. :param dict player_config_args: The data object containing video media data like title and keywords. :param dict monostate: Dictionary of data shared across all instances of :class:`Stream <Stream>`. """ # A dictionary shared between all instances of :class:`Stream <Stream>` # (Borg pattern). self._monostate = monostate self.abr = None # average bitrate (audio streams only) self.fps = None # frames per second (video streams only) self.itag = None # stream format id (youtube nomenclature) self.res = None # resolution (e.g.: 480p, 720p, 1080p) self.url = None # signed download url self.mime_type = None # content identifier (e.g.: video/mp4) self.type = None # the part of the mime before the slash self.subtype = None # the part of the mime after the slash self.codecs = [] # audio/video encoders (e.g.: vp8, mp4a) self.audio_codec = None # audio codec of the stream (e.g.: vorbis) self.video_codec = None # video codec of the stream (e.g.: vp8) # Iterates over the key/values of stream and sets them as class # attributes. This is an anti-pattern and should be removed. self.set_attributes_from_dict(stream) # Additional information about the stream format, such as resolution, # frame rate, and whether the stream is live (HLS) or 3D. self.fmt_profile = get_format_profile(self.itag) # Same as above, except for the format profile attributes. self.set_attributes_from_dict(self.fmt_profile) # The player configuration which contains information like the video # title. # TODO(nficano): this should be moved to the monostate. self.player_config_args = player_config_args # 'video/webm; codecs="vp8, vorbis"' -> 'video/webm', ['vp8', 'vorbis'] self.mime_type, self.codecs = extract.mime_type_codec(self.type) # 'video/webm' -> 'video', 'webm' self.type, self.subtype = self.mime_type.split('/') # ['vp8', 'vorbis'] -> video_codec: vp8, audio_codec: vorbis. DASH # streams return NoneType for audio/video depending. self.video_codec, self.audio_codec = self.parse_codecs()
def test_mime_type_codec_with_no_match_should_error(): with pytest.raises(RegexMatchError): extract.mime_type_codec("audio/webm")
def test_mime_type_codec(): mime_type, mime_subtype = extract.mime_type_codec( 'audio/webm; codecs="opus"') assert mime_type == "audio/webm" assert mime_subtype == ["opus"]