def _create_adaptive_streams(self, adaptive_formats): streams = {} adaptive_streams = {} best_audio_itag = None # Extract audio streams from the adaptive format list for url, label, itag, mimeType in adaptive_formats: if url is None: continue # extract any high quality streams only available in adaptive formats adaptive_streams[itag] = url stream_type, stream_codecs = mimeType if stream_type == "audio": streams[f"audio_{stream_codecs}"] = HTTPStream(self.session, url) # find the best quality audio stream m4a, opus or vorbis if best_audio_itag is None or self.adp_audio[itag] > self.adp_audio[best_audio_itag]: best_audio_itag = itag if best_audio_itag and adaptive_streams and MuxedStream.is_usable(self.session): aurl = adaptive_streams[best_audio_itag] for itag, name in self.adp_video.items(): if itag not in adaptive_streams: continue vurl = adaptive_streams[itag] log.debug(f"MuxedStream: v {itag} a {best_audio_itag} = {name}") streams[name] = MuxedStream( self.session, HTTPStream(self.session, vurl), HTTPStream(self.session, aurl) ) return streams
def _create_adaptive_streams(self, info, streams): adaptive_streams = {} best_audio_itag = None # Extract audio streams from the adaptive format list streaming_data = info.get("player_response", {}).get("streamingData", {}) for stream_info in streaming_data.get("adaptiveFormats", []): if "url" not in stream_info: continue stream_params = dict(parse_qsl(stream_info["url"])) if "itag" not in stream_params: continue itag = int(stream_params["itag"]) # extract any high quality streams only available in adaptive formats adaptive_streams[itag] = stream_info["url"] stream_type, stream_format = stream_info["mimeType"] if stream_type == "audio": stream = HTTPStream(self.session, stream_info["url"]) name = "audio_{0}".format(stream_format) streams[name] = stream # find the best quality audio stream m4a, opus or vorbis if best_audio_itag is None or self.adp_audio[ itag] > self.adp_audio[best_audio_itag]: best_audio_itag = itag if best_audio_itag and adaptive_streams and MuxedStream.is_usable( self.session): aurl = adaptive_streams[best_audio_itag] for itag, name in self.adp_video.items(): if itag in adaptive_streams: vurl = adaptive_streams[itag] log.debug( "MuxedStream: v {video} a {audio} = {name}".format( audio=best_audio_itag, name=name, video=itag, )) streams[name] = MuxedStream(self.session, HTTPStream(self.session, vurl), HTTPStream(self.session, aurl)) return streams
def _get_streams(self): if not MuxedStream.is_usable(self.session): return media_id, application = self._get_media_app() if not media_id: return wsclient = UStreamTVWsClient( self.session, media_id, application, referrer=self.url, cluster="live", password=self.get_option("password") ) log.debug( f"Connecting to UStream API:" f" media_id={media_id}," f" application={application}," f" referrer={self.url}," f" cluster=live" ) wsclient.start() log.debug(f"Waiting for stream data (for at most {self.STREAM_READY_TIMEOUT} seconds)...") if ( not wsclient.ready.wait(self.STREAM_READY_TIMEOUT) or not wsclient.is_alive() or wsclient.stream_error ): log.error(wsclient.stream_error or "Waiting for stream data timed out.") wsclient.close() return if not wsclient.stream_formats_audio: for video in wsclient.stream_formats_video: yield f"{video.height}p", UStreamTVStream(self.session, "video", wsclient, video) else: for video in wsclient.stream_formats_video: for audio in wsclient.stream_formats_audio: yield f"{video.height}p+a{audio.bitrate}k", MuxedStream( self.session, UStreamTVStream(self.session, "video", wsclient, video), UStreamTVStream(self.session, "audio", wsclient, audio) )
def _create_adaptive_streams(self, info, streams, protected): adaptive_streams = {} best_audio_itag = None # Extract audio streams from the DASH format list for stream_info in info.get("adaptive_fmts", []): if stream_info.get("s"): protected = True continue stream_params = dict(parse_qsl(stream_info["url"])) if "itag" not in stream_params: continue itag = int(stream_params["itag"]) # extract any high quality streams only available in adaptive formats adaptive_streams[itag] = stream_info["url"] stream_type, stream_format = stream_info["type"] if stream_type == "audio": stream = HTTPStream(self.session, stream_info["url"]) name = "audio_{0}".format(stream_format) streams[name] = stream # find the best quality audio stream m4a, opus or vorbis if best_audio_itag is None or self.adp_audio[itag] > self.adp_audio[best_audio_itag]: best_audio_itag = itag if best_audio_itag and adaptive_streams and MuxedStream.is_usable(self.session): aurl = adaptive_streams[best_audio_itag] for itag, name in self.adp_video.items(): if itag in adaptive_streams: vurl = adaptive_streams[itag] log.debug("MuxedStream: v {video} a {audio} = {name}".format( audio=best_audio_itag, name=name, video=itag, )) streams[name] = MuxedStream(self.session, HTTPStream(self.session, vurl), HTTPStream(self.session, aurl)) return streams, protected
def ytdl_fallback(self): '''Basic support for m3u8 URLs with youtube-dl''' log.debug(f'Fallback {youtube_dl.__name__} {youtube_dl.version.__version__}') class YTDL_Logger(object): def debug(self, msg): log.debug(msg) def warning(self, msg): log.warning(msg) def error(self, msg): log.trace(msg) ydl_opts = { 'call_home': False, 'forcejson': True, 'logger': YTDL_Logger(), 'no_color': True, 'noplaylist': True, 'no_warnings': True, 'verbose': False, 'quiet': True, } with youtube_dl.YoutubeDL(ydl_opts) as ydl: try: info = ydl.extract_info(self.url, download=False) except Exception: return if not info or not info.get('formats'): return self.title = info['title'] streams = [] for stream in info['formats']: if stream['protocol'] in ['m3u8', 'm3u8_native'] and stream['ext'] == 'mp4': log.trace('{0!r}'.format(stream)) name = stream.get('height') or stream.get('width') if name: name = '{0}p'.format(name) streams.append((name, HLSStream(self.session, stream['url'], headers=stream['http_headers']))) if not streams: if ('youtube.com' in self.url and info.get('requested_formats') and len(info.get('requested_formats')) == 2 and MuxedStream.is_usable(self.session)): audio_url = audio_format = video_url = video_format = video_name = None for stream in info.get('requested_formats'): if stream.get('format_id') == '135': url = stream.get('manifest_url') if not url: return return DASHStream.parse_manifest(self.session, url).items() if not stream.get('height'): audio_url = stream.get('url') audio_format = stream.get('format_id') if stream.get('height'): video_url = stream.get('url') video_format = stream.get('format_id') video_name = '{0}p'.format(stream.get('height')) log.debug('MuxedStream: v {video} a {audio} = {name}'.format( audio=audio_format, name=video_name, video=video_format, )) streams.append((video_name, MuxedStream(self.session, HTTPStream(self.session, video_url, headers=stream['http_headers']), HTTPStream(self.session, audio_url, headers=stream['http_headers'])) )) return streams
def _get_streams(self): info = self._get_stream_info(self.url) if not info: return formats = info.get("fmt_list") streams = {} protected = False for stream_info in info.get("url_encoded_fmt_stream_map", []): if stream_info.get("s"): protected = True continue stream = HTTPStream(self.session, stream_info["url"]) name = formats.get(stream_info["itag"]) or stream_info["quality"] if stream_info.get("stereo3d"): name += "_3d" streams[name] = stream adaptive_streams = {} best_audio_itag = None # Extract audio streams from the DASH format list for stream_info in info.get("adaptive_fmts", []): if stream_info.get("s"): protected = True continue stream_params = dict(parse_qsl(stream_info["url"])) if "itag" not in stream_params: continue itag = int(stream_params["itag"]) # extract any high quality streams only available in adaptive formats adaptive_streams[itag] = stream_info["url"] stream_type, stream_format = stream_info["type"] if stream_type == "audio": stream = HTTPStream(self.session, stream_info["url"]) name = "audio_{0}".format(stream_format) streams[name] = stream # find the best quality audio stream m4a, opus or vorbis if best_audio_itag is None or self.adp_audio[ itag] > self.adp_audio[best_audio_itag]: best_audio_itag = itag if best_audio_itag and adaptive_streams and MuxedStream.is_usable( self.session): aurl = adaptive_streams[best_audio_itag] for itag, name in self.adp_video.items(): if itag in adaptive_streams: vurl = adaptive_streams[itag] streams[name] = MuxedStream(self.session, HTTPStream(self.session, vurl), HTTPStream(self.session, aurl)) hls_playlist = info.get("hlsvp") if hls_playlist: try: hls_streams = HLSStream.parse_variant_playlist( self.session, hls_playlist, headers=HLS_HEADERS, namekey="pixels") streams.update(hls_streams) except IOError as err: self.logger.warning("Failed to extract HLS streams: {0}", err) if not streams and protected: raise PluginError("This plugin does not support protected videos, " "try youtube-dl instead") return streams
def _get_streams(self): info = self._get_stream_info(self.url) if not info: return formats = info.get("fmt_list") streams = {} protected = False for stream_info in info.get("url_encoded_fmt_stream_map", []): if stream_info.get("s"): protected = True continue stream = HTTPStream(self.session, stream_info["url"]) name = formats.get(stream_info["itag"]) or stream_info["quality"] if stream_info.get("stereo3d"): name += "_3d" streams[name] = stream adaptive_streams = {} best_audio_itag = None # Extract audio streams from the DASH format list for stream_info in info.get("adaptive_fmts", []): if stream_info.get("s"): protected = True continue stream_params = dict(parse_qsl(stream_info["url"])) if "itag" not in stream_params: continue itag = int(stream_params["itag"]) # extract any high quality streams only available in adaptive formats adaptive_streams[itag] = stream_info["url"] stream_type, stream_format = stream_info["type"] if stream_type == "audio": stream = HTTPStream(self.session, stream_info["url"]) name = "audio_{0}".format(stream_format) streams[name] = stream # find the best quality audio stream m4a, opus or vorbis if best_audio_itag is None or self.adp_audio[itag] > self.adp_audio[best_audio_itag]: best_audio_itag = itag if best_audio_itag and adaptive_streams and MuxedStream.is_usable(self.session): aurl = adaptive_streams[best_audio_itag] for itag, name in self.adp_video.items(): if itag in adaptive_streams: vurl = adaptive_streams[itag] streams[name] = MuxedStream(self.session, HTTPStream(self.session, vurl), HTTPStream(self.session, aurl)) hls_playlist = info.get("hlsvp") if hls_playlist: try: hls_streams = HLSStream.parse_variant_playlist( self.session, hls_playlist, headers=HLS_HEADERS, namekey="pixels" ) streams.update(hls_streams) except IOError as err: self.logger.warning("Failed to extract HLS streams: {0}", err) if not streams and protected: raise PluginError("This plugin does not support protected videos, " "try youtube-dl instead") return streams
def _create_adaptive_streams(self, info, streams): if not MuxedStream.is_usable(self.session): log.info("Cannot use FFMPEG") return streams adaptive_streams = {} best_audio_itag = None adp_video = self.adp_video_h264.copy() vp9 = "vp9" if hostname() in self.stb_vp9_1 or hostname( ) in self.stb_vp9_2 else "" if not vp9: log.debug("STB w/o vp9 4K support detected") if self.get_option("yes-vp9-codecs"): vp9 = "vp9" elif self.get_option("no-vp9-codecs"): vp9 = "" log.info("VP9 Codecs are skipped") if vp9: adp_video.update(self.adp_video_vp9) if self.get_option( "yes-vp9-hdr-codecs") or hostname() in self.stb_vp9_2: adp_video.update(self.adp_video_vp9_hdr) # Extract streams from the DASH format list for stream_info in info.get("formats", []): itag = int(stream_info["format_id"]) if itag not in self.adp_audio and itag not in adp_video: log.debug( "Skipped format:{}, Codec:{}", stream_info["format"], stream_info["acodec"] if stream_info["acodec"] != "none" else stream_info["vcodec"], ) continue # extract any high quality streams only available in adaptive formats and not skipped adaptive_streams[itag] = stream_info["url"] stream_format = stream_info["ext"] if itag in self.adp_audio: if self.get_option( "no-opus-codec") and stream_info["acodec"] == "opus": log.debug("Skipped format:{}, Codec:{}", stream_info["format"], stream_info["acodec"]) continue stream = HTTPStream(self.session, stream_info["url"]) name = "audio_{0}".format(stream_format) streams[name] = stream # find the best quality audio stream m4a, opus or vorbis if best_audio_itag is None or self.adp_audio[ itag] > self.adp_audio[best_audio_itag]: best_audio_itag = itag if best_audio_itag and adaptive_streams and MuxedStream.is_usable( self.session): aurl = adaptive_streams[best_audio_itag] for itag, name in adp_video.items(): if itag in adaptive_streams: vurl = adaptive_streams[itag] log.debug( "MuxedStream: v {video} a {audio} = {name}".format( audio=best_audio_itag, name=name, video=itag, )) streams[name] = MuxedStream(self.session, HTTPStream(self.session, vurl), HTTPStream(self.session, aurl)) return streams