Resolve final url upon playing video.

So i am working on porting my iTBN XBMC add-on over to PLEX. All is going well, the two are very similar so most of the code works just like before. I have however run in to one problem. My script needs to resolve a couple url's before it can find the source video url, and if tell it to resolve the url's when it lists the video links the load time is 

way too high. Here is an example of the code that is too slow.

	for url,name,thumbnail,description in mylist:
		url=GETSOURCE(url)
		oc.add(VideoClipObject(
		key = url,
		title = name+' - '+description,
		thumb = thumbnail,
		items = [
			MediaObject(
			container = Container.MP4,
			video_codec = VideoCodec.H264,
			audio_codec = AudioCodec.AAC,
			audio_channels = 2,
			parts = [PartObject(key = url)]
			)
		]
		))
def GETSOURCE(url):
	link=HTTP.Request(url).content
	somemagiccode
		return url

Like i said this works, but since it is running the GETSOURCE() function while it lists all the items it takes forever to load. In XBMC the resolution is.

        for url in match:
                xbmc.Player().play(url)

Does PLEX have a similar function? Also if nothing else i can have PLEX create directories and then upon clicking on the directory it will resolve the link and list the video, but that is one extra step for the user which i would like to avoid. If you need more specific details let me know. The main question here is does PLEX have a function similar to xbmc.Player().play . If so i think i can handle the rest. Thank you.

You're flirting with a common error in developing channels for the latest Plex plugin framework. If you choose to work without a URL Service, then you will need to provide both the 'key' and 'rating_key' arguments when creating the VideoClipObject. The 'key' is intended to be a callback, whereas the 'rating_key' should be a unique identifier (I usually use the url, although I've been told that's not correct)(Actually, I've been told it is correct  :)). Here's a link to a thread with some further discussion. Here's a little more background reading, and here.

In answer to your question, the most common practice is to use a callback as the key to the PartObject. In the callback function you can manipulate the data however necessary before returning the final media URL. For example:

items = [
    MediaObject(
        container = Container.MP4,
        video_codec = VideoCodec.H264,
        audio_codec = AudioCodec.AAC,
        audio_channels = 2,
        parts = [PartObject(key = Callback(PlayVideo, url=url))]
    )
]

def PlayVideo(url):
‘’’ take the given url and perform necessary work to find and return the final media url’’’
return Redirect(media_url)

Just to add in case it's not clear, the advantage to this is that the supplemental url loads only happen when the user actually "hits play" so to speak, so they are loaded on demand only and no more slowdowns.

First of all thanks for the quick reply. It sounds like you know exactly what I am talking about and what I want to do which is good. I am still having troubles though, I'm sure it is some stupid little thing that i am overlooking.

Here is an example of some test code that i feel like should work but doesn't.

items = [
	MediaObject(
	container = Container.MP4,
	video_codec = VideoCodec.H264,
	audio_codec = AudioCodec.AAC,
	audio_channels = 2,
	parts = [PartObject(key = Callback(PlayVideo, url=url))]
	)
]
...

def PlayVideo(url):
url = “http://cdn.jerryseinfeld.com/assets/20081001_pmyqfa.mp4
return url

But this works.

items = [
	MediaObject(
	container = Container.MP4,
	video_codec = VideoCodec.H264,
	audio_codec = AudioCodec.AAC,
	audio_channels = 2,
	parts = [PartObject(key = "http://cdn.jerryseinfeld.com/assets/20081001_pmyqfa.mp4")]
	)
]

In this case shouldn't both of these sections of code give me the same results. Or am I missing something?

The issue is that when you return the url from the Callback, the client expects it to be media not a link to media. That's why I included the Redirect() in my example.  It basically uses a HTTP 302 redirect to tell the client, "follow this link to get the media". I've since been informed that the preferred method to return the media is using the @indirect decorator. In essence what this does is forces the callback method to return one more layer of XML data with the media url included. This method works much better across the range of available Plex clients. You would implement it like this:

@indirect
def PlayVideo(url):
    ''' take url and convert it to media_url '''
    return IndirectResponse(VideoClipObject, key = media_url)

Thank you so much Mikedm139. Resolves like a charm and it's as fast as could be.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.