streams.py
get(vid, force=False, callback=None, threeD=False)
¶
Get all streams as a dict. callback function passed to get_pafy.
Source code in mps_youtube/streams.py
def get(vid, force=False, callback=None, threeD=False):
""" Get all streams as a dict. callback function passed to get_pafy. """
now = time.time()
ytid = vid.ytid
have_stream = g.streams.get(ytid) and (g.streams[ytid]['expiry'] > now if g.streams[ytid]['expiry'] is not None else False)
prfx = "preload: " if not callback else ""
if not force and have_stream:
ss = str(int(g.streams[ytid]['expiry'] - now) // 60)
util.dbg("%s%sGot streams from cache (%s mins left)%s",
c.g, prfx, ss, c.w)
return g.streams.get(ytid)['meta']
#p = None#util.get_pafy(vid, force=force, callback=callback)
#ps = p.allstreams if threeD else [x for x in p.allstreams if not x.threed]
ps = pafy.get_video_streams(ytid)
try:
# test urls are valid
[x['url'] for x in ps]
except TypeError:
# refetch if problem
util.dbg("%s****Type Error in get_streams. Retrying%s", c.r, c.w)
p = util.get_pafy(vid, force=True, callback=callback)
ps = p.allstreams if threeD else [x for x in p.allstreams
if not x.threed]
streams = [{"url": s['url'],
"ext": s['ext'],
"quality": s['resolution'],
"rawbitrate": s.get('bitrate',-1),
"mtype": 'audio' if 'audio' in s['resolution'] else ('video' if s['acodec'] != 'none' else '?'),
"size": int(s.get('filesize') if s.get('filesize') is not None else s.get('filesize_approx', -1))} for s in ps]
if 'manifest' in streams[0]['url']:
expiry = float(streams[0]['url'].split('/expire/')[1].split('/')[0])
else:
temp = streams[0]['url'].split('expire=')[1]
expiry = float(temp[:temp.find('&')])
g.streams[ytid] = dict(expiry=expiry, meta=streams)
prune()
return streams
get_size(ytid, url, preloading=False)
¶
Get size of stream, try stream cache first.
Source code in mps_youtube/streams.py
def get_size(ytid, url, preloading=False):
""" Get size of stream, try stream cache first. """
# try cached value
stream = [x for x in g.streams[ytid]['meta'] if x['url'] == url][0]
size = stream['size']
prefix = "preload: " if preloading else ""
if not size == -1:
util.dbg("%s%susing cached size: %s%s", c.g, prefix, size, c.w)
else:
screen.writestatus("Getting content length", mute=preloading)
stream['size'] = _get_content_length(url, preloading=preloading)
util.dbg("%s%s - content-length: %s%s", c.y, prefix, stream['size'], c.w)
return stream['size']
preload(song, delay=2, override=False)
¶
Get streams.
Source code in mps_youtube/streams.py
def preload(song, delay=2, override=False):
""" Get streams. """
args = (song, delay, override)
t = threading.Thread(target=_preload, args=args)
t.daemon = True
t.start()
prune()
¶
Keep cache size in check.
Source code in mps_youtube/streams.py
def prune():
""" Keep cache size in check. """
while len(g.pafs) > g.max_cached_streams:
g.pafs.popitem(last=False)
while len(g.streams) > g.max_cached_streams:
g.streams.popitem(last=False)
# prune time expired items
now = time.time()
oldpafs = [k for k in g.pafs if g.pafs[k] is not None and g.pafs[k].expiry < now]
if len(oldpafs):
util.dbg(c.r + "%s old pafy items pruned%s", len(oldpafs), c.w)
for oldpaf in oldpafs:
g.pafs.pop(oldpaf, 0)
oldstreams = [k for k in g.streams if g.streams[k]['expiry'] is None or g.streams[k]['expiry'] < now]
if len(oldstreams):
util.dbg(c.r + "%s old stream items pruned%s", len(oldstreams), c.w)
for oldstream in oldstreams:
g.streams.pop(oldstream, 0)
util.dbg(c.b + "paf: %s, streams: %s%s", len(g.pafs), len(g.streams), c.w)
select(slist, q=0, audio=False, m4a_ok=True, maxres=None)
¶
Select a stream from stream list.
Source code in mps_youtube/streams.py
def select(slist, q=0, audio=False, m4a_ok=True, maxres=None):
""" Select a stream from stream list. """
maxres = maxres or config.MAX_RES.get
slist = slist['meta'] if isinstance(slist, dict) else slist
def okres(x):
""" Return True if resolution is within user specified maxres. """
return int(x['quality'].split("x")[1]) <= maxres
def getq(x):
""" Return height aspect of resolution, eg 640x480 => 480. """
return int(x['quality'].split("x")[1])
def getbitrate(x):
"""Return the bitrate of a stream."""
return x['rawbitrate']
if audio:
streams = [x for x in slist if x['mtype'] == "audio"]
if not m4a_ok:
streams = [x for x in streams if not x['ext'] == "m4a"]
if not config.AUDIO_FORMAT.get == "auto":
if m4a_ok and config.AUDIO_FORMAT.get == "m4a":
streams = [x for x in streams if x['ext'] == "m4a"]
if config.AUDIO_FORMAT.get == "webm":
streams = [x for x in streams if x['ext'] == "webm"]
if not streams:
streams = [x for x in slist if x['mtype'] == "audio"]
streams = sorted(streams, key=getbitrate, reverse=True)
else:
streams = [x for x in slist if x['mtype'] == "video" and okres(x)]
if not config.VIDEO_FORMAT.get == "auto":
if config.VIDEO_FORMAT.get == "mp4":
streams = [x for x in streams if x['ext'] == "mp4"]
if config.VIDEO_FORMAT.get == "webm":
streams = [x for x in streams if x['ext'] == "webm"]
if config.VIDEO_FORMAT.get == "3gp":
streams = [x for x in streams if x['ext'] == "3gp"]
if not streams:
streams = [x for x in slist if x['mtype'] == "video" and okres(x)]
streams = sorted(streams, key=getq, reverse=True)
util.dbg("select stream, q: %s, audio: %s, len: %s", q, audio, len(streams))
try:
ret = streams[q]
except IndexError:
ret = streams[0] if q and len(streams) else None
return ret