Move getStreamURL to PlexPartialObject; Remove duplicated code; Add getStreamURL tests (doesnt actualy test the stream works tho)

This commit is contained in:
Michael Shepanski 2016-03-22 23:38:06 -04:00
parent a0cfaafb68
commit bcf01fdcdf
5 changed files with 41 additions and 41 deletions

View file

@ -3,8 +3,6 @@
PlexAPI Audio
"""
from plexapi import media, utils
from plexapi.compat import urlencode
from plexapi.exceptions import Unsupported
NA = utils.NA
@ -25,23 +23,6 @@ class Audio(utils.PlexPartialObject):
self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt', NA))
self.viewCount = utils.cast(int, data.attrib.get('viewCount', 0))
def getStreamUrl(self, offset=0, **kwargs):
""" Fetch URL to stream audio directly.
offset: Start time (in seconds) audio will initiate from (ex: 300).
params: Dict of additional parameters to include in URL.
"""
if self.TYPE not in [Track.TYPE, Album.TYPE]:
raise Unsupported('Cannot get stream URL for %s.' % self.TYPE)
params = {}
params['path'] = self.key
params['offset'] = offset
params['copyts'] = kwargs.get('copyts', 1)
params['mediaIndex'] = kwargs.get('mediaIndex', 0)
params['X-Plex-Platform'] = kwargs.get('platform', 'Chrome')
if 'protocol' in kwargs:
params['protocol'] = kwargs['protocol']
return self.server.url('/audio/:/transcode/universal/start.m3u8?%s' % urlencode(params))
@utils.register_libtype
class Artist(Audio):
@ -173,3 +154,6 @@ class Track(Audio):
def artist(self):
return utils.listItems(self.server, self.grandparentKey)[0]
def getStreamURL(self, **params):
return self._getStreamURL(**params)

View file

@ -3,8 +3,6 @@
PlexPlaylist
"""
from plexapi import utils
from plexapi.compat import urlencode
from plexapi.exceptions import Unsupported
from plexapi.utils import cast, toDatetime
NA = utils.NA
@ -29,24 +27,6 @@ class Playlist(utils.PlexPartialObject):
self.type = data.attrib.get('type', NA)
self.updatedAt = toDatetime(data.attrib.get('updatedAt', NA))
# TODO: FIXME (Let's move getStreamURL to utils and make it more generic)
def getStreamUrl(self, offset=0, **kwargs):
""" Fetch URL to stream audio directly.
offset: Start time (in seconds) audio will initiate from (ex: 300).
params: Dict of additional parameters to include in URL.
"""
if self.TYPE not in [Track.TYPE, Album.TYPE]:
raise Unsupported('Cannot get stream URL for %s.' % self.TYPE)
params = {}
params['path'] = self.key
params['offset'] = offset
params['copyts'] = kwargs.get('copyts', 1)
params['mediaIndex'] = kwargs.get('mediaIndex', 0)
params['X-Plex-Platform'] = kwargs.get('platform', 'Chrome')
if 'protocol' in kwargs:
params['protocol'] = kwargs['protocol']
return self.server.url('/audio/:/transcode/universal/start.m3u8?%s' % urlencode(params))
def items(self):
path = '%s/items' % self.key
return utils.listItems(self.server, path)

View file

@ -2,10 +2,11 @@
"""
PlexAPI Utils
"""
import re
from requests import put
from datetime import datetime
from plexapi.compat import quote
from plexapi.exceptions import NotFound, UnknownType
from plexapi.compat import quote, urlencode
from plexapi.exceptions import NotFound, UnknownType, Unsupported
# Registry of library types we may come across when parsing XML. This allows us to
@ -58,6 +59,25 @@ class PlexPartialObject(object):
@property
def thumbUrl(self):
return self.server.url(self.thumb)
def _getStreamURL(self, **params):
if self.TYPE not in ('movie', 'episode', 'track'):
raise Unsupported('Fetching stream URL for %s is unsupported.' % self.TYPE)
mvb = params.get('maxVideoBitrate')
vr = params.get('videoResolution', '')
params = {
'path': self.key,
'offset': params.get('offset', 0),
'copyts': params.get('copyts', 1),
'protocol': params.get('protocol'),
'mediaIndex': params.get('mediaIndex', 0),
'X-Plex-Platform': params.get('platform', 'Chrome'),
'maxVideoBitrate': max(mvb,64) if mvb else None,
'videoResolution': vr if re.match('^\d+x\d+$', vr) else None
}
params = {k:v for k,v in params.items() if v is not None} # remove None values
streamtype = 'audio' if self.TYPE in ('track', 'album') else 'video'
return self.server.url('/%s/:/transcode/universal/start.m3u8?%s' % (streamtype, urlencode(params)))
def _findLocation(self, data):
elem = data.find('Location')

View file

@ -118,6 +118,9 @@ class Movie(Video):
@property
def isWatched(self):
return bool(self.viewCount > 0)
def getStreamURL(self, **params):
return self._getStreamURL(**params)
@utils.register_libtype
@ -259,6 +262,9 @@ class Episode(Video):
@property
def thumbUrl(self):
return self.server.url(self.grandparentThumb)
def getStreamURL(self, **params):
return self._getStreamURL(videoResolution='800x600', **params)
def season(self):
return utils.listItems(self.server, self.parentKey)[0]

View file

@ -302,6 +302,16 @@ def test_fetch_details_not_in_search_result(plex, user=None):
log(2, '%s actors found.' % len(actors))
@register('movie,audio')
def test_stream_url(plex, user=None):
movie = plex.library.section(MOVIE_SECTION).get(MOVIE_TITLE)
episode = plex.library.section(SHOW_SECTION).get(SHOW_TITLE).episodes()[-1]
track = plex.library.section(AUDIO_SECTION).get(AUDIO_ARTIST).get(AUDIO_TRACK)
log(2, 'Movie: vlc "%s"' % movie.getStreamURL())
log(2, 'Episode: vlc "%s"' % episode.getStreamURL())
log(2, 'Track: cvlc "%s"' % track.getStreamURL())
#-----------------------
# Play Queue
#-----------------------