Guest User

Untitled

a guest
Oct 9th, 2013
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.90 KB | None | 0 0
  1. # IMPORTANT NOTE: AS WITH ALL PYTHON CODING, PROPER INDENTATION IS NECESSARY TO PREVENT ERRORS.
  2. # PROGRAMS LIKE NOTEPAD++ DO NOT ALWAYS LINE UP PROPERLY OR CATCH THESE INDENTION ERRORS. TO
  3. # PREVENT THESE AND OTHER PYTHON ERRORS, BEFORE RUNNING THE PROGRAM IN PLEX OR AFTER MAKING CHANGES
  4. # TO THE FILE, I OPEN IT FIRST IN A LOCAL VERSION OF PYTHON I HAVE LOADED AND CHOOSE
  5. # RUN > CHECK MODULE TO FIND ANY POSSIBLE PROBLEMS.
  6.  
  7.  
  8. # These are python variables you set up for use later in this file
  9. # The naming and values are based on the where and how you choose to use them in your code
  10. # For the most part, you are defining variables you will use in the PlayVideo function
  11. # Often video files are stored in a video directory on the site, but the base file could just be htpp://www.anywebsite.com/
  12. BASE_URL = 'http://video.anywebsite.com/'
  13.  
  14. # It is best practice to use regex when possible and avoid importing any Python modules, so below is a regex statement I use
  15. # later in my PlayVideo function to find the video info xml address within the page that allows me to easily pull the
  16. # web pages corresponding video file location
  17. RE_XML_URL = Regex("/xml/video(.+?)',")
  18.  
  19. # The variable below is basic regex to pull a video from an html page. I show its use in a optional version of the PlayVideo function
  20. # RE_VIDEO_URL = Regex('videofile:"(?P<video_url>[^"]+)"')
  21.  
  22. # IMPORTANT NOTE: THE VALUE OF 'URL' THAT IS PASSED TO THE DIFFERENT FUNCTIONS IN THIS PROGRAM IS DETERMINED EITHER
  23. # WITHIN THE PROGRAMMING OF THE INDIVIDUAL CHANNEL PLUGIN THAT USES THIS URL SERVICE OR BY THE END USER CHOOSING THE PLEXIT BUTTON
  24.  
  25. ########################################################################################################
  26. # BELOW IS AN OPTIONAL CODE FOR CONVERTING HTML VIDEO PAGES TO THEIR CORRESPONDING VIDEO INFO XML PAGES.
  27. # IF YOU CAN FIND REFERENCE TO THESE XML VIDEO INFO FILES ON THE VIDEO WEBPAGES, THESE XML PAGES CAN BE
  28. # USED FOR EASY RETRIEVAL OF METADATA AND VIDEO FILES USING XML.ElementFromURL.
  29. # We use string.replace() to create a new url that adds /xml/video-folder/ to middle and changes the extension to .xml.
  30. ########################################################################################################
  31.  
  32. XML_URL = url.replace('http://www.anywebsite.com/','http://www.anywebsite.com/xml/videos-page/').replace('.html','.xml')
  33.  
  34. ####################################################################################################
  35. # This pulls the metadata that is used for Plexit, suggested videos (to friends), the pre-play screen on iOS, Roku, Android and Plex/Web,
  36. # as well as if you get the "info" or "details" within the OSX/Windows/Linux desktop client.
  37. # Afer you pull the data you should save it to preset variables. These basic variables are title, summary, and thumb.
  38. # but some also include duration, and originally_available_at, content_rating, show, tags and index
  39.  
  40. def MetadataObjectForURL(url):
  41.  
  42. # Here you are using the ElementFromURL() API to parse or pull up all the data from the webpage.
  43. # See the Framework documentation API reference for all the choices for parsing data
  44. page = HTML.ElementFromURL(url)
  45.  
  46. # Extract the data available on the page using xpath commands.
  47. # Think about what will access the metadata from this URL service to determine what info you want to extract here
  48. # Below is a basic example that pulls the the title, description and thumb from the head of a html document that makes a request of this URL Service
  49. title = page.xpath("//head//meta[@property='og:title']")[0].get('content')
  50. description = page.xpath("//head//meta[@property='og:description']")[0].get('content')
  51. thumb = page.xpath("//head//meta[@property='og:image']")[0].get('url')
  52.  
  53. # This command returns the metadata values you extracted as a video clip object.
  54. # See the Framework documentation API reference for all the choices of objects to return metadata
  55. return VideoClipObject(
  56. title = title,
  57. summary = description,
  58. thumb = thumb,
  59. )
  60.  
  61. ####################################################################################################
  62. # Here you will define the different types of videos available on this website and the values for their quality
  63. # You will need to search the source of the web pages that play a video to determine the type and location of videos offered thru the site
  64. # You can see if the name and location is available through an embed link, but you may have to look into the subpages for a web page
  65. # like javascript or style sheets to find this information. You will also need this information later when
  66. # writing the code for the PlayVideo function that pulls these specific video files from the webpage
  67.  
  68. def MediaObjectsForURL(url):
  69. return [
  70.  
  71. # First you are calling a MediaObject() for each type of video the website offers using the MediaObject API command
  72. # Most separate these types of videos by the resolution, for example a site may offer a high and low quality option for each video on its site
  73. # or they may offer an .flv format and an .mp4 format version of the video file. You can choose to only offer one type of video file
  74. # or give the user the option of choosing the type of video file they want to use if there are several different types and qualities.
  75. MediaObject(
  76.  
  77. # Then within each MediaObject you define the values for that particular type of video
  78. # The options most used are video_codec, audio_codec, parts, container, video_resolution, audio_channels, and bitrate
  79. # See the Framework documentation API reference for a lists all possible attributes for MediaObject()
  80. # Audio Codecs are AAC and .MP3; Video Codecs are .H264; Container File Types are .MP4, .MKV, .MOV, and .AVI¶
  81. # And for audio channels stereo equals 2
  82.  
  83. # I have found the best way to determine these attributes is to use VLC player and open the network stream URL of a few of the
  84. # videos available on the site. And then use the tools to view the media information esp. codec info
  85.  
  86. video_codec = VideoCodec.H264,
  87. audio_codec = AudioCodec.MP3,
  88. video_resolution = '720',
  89. audio_channels = 2,
  90. container = 'f4v',
  91.  
  92. # This section of the code allows you to peice together videos that come in 2 or more parts it also uses a callback function
  93. # that calls the PlayVideo function below. This done to separate the playing of the video from the call for the media object
  94. # that way it will only play the video if the user selects that particular video.
  95. # The code below is the basic format that all URL Serivces use and then they define PlayVideo if the video only has one part, it only needs one PartObject
  96. # Note that we are also sending a fmt variable to tell the PlayVideo function whether this is a high or low quality video. This is only
  97. # necessary when you have more than one choice for the video files available.
  98. parts = [PartObject(key=Callback(PlayVideo, url = url, fmt='hi')]
  99. )
  100. # Below we are doing the same as above, and defining a second MediaObject that is a low quality version of the video file that is available.
  101. # The fmt variable is sent to the PlayVideo function to help you determine which of the available video types to send back to the Media Object.
  102. MediaObject(
  103. video_codec = VideoCodec.H264,
  104. audio_codec = AudioCodec.MP3,
  105. video_resolution = '420',
  106. audio_channels = 2,
  107. container = 'f4v',
  108. parts = [PartObject(key=Callback(PlayVideo, url = url, fmt='lo')]
  109.  
  110.  
  111. )
  112. ]
  113.  
  114. ####################################################################################################
  115. # Here we are defining the PlayVideo function we called in the callback function above. This function defines the pattern for
  116. # the location and naming scheme of the video so we can play the video file directly. You use HTML request, regular expressions,
  117. # and predefined variables to create the path or http address of the video associated with the html or xml page that was sent
  118. # to this service through the "URL" value. The programming here will vary greatly based on the location of the
  119. # video file related to your video pages. This is where you will be doing the majority to the programming.
  120. # It is best to refer to other services already created for examples of how to pull the video file.
  121.  
  122. # First we define the function taking the the variables for the url entered into the service and the
  123. # fmt variable we established above in MediaObjects
  124.  
  125. def PlayVideo(url, fmt):
  126.  
  127. # Below I have included a basic example of how to program the PlayVideo function for pulling the video location on the web page
  128. # whose URL was sent to the service and only has ONE video on the page. The code pulls the raw data from the web page
  129. # using the URL and then uses a simple page search that returns an f4v video file url that is located in each html video page.
  130. # It uses both of the variables we established at the top of the service.
  131. # EXAMPLE:
  132. # page = HTTP.Request(url).content
  133. # video = RE_VIDEO_URL.search(page).group('video_url') + ".f4v"
  134. # video = BASE_URL + video
  135.  
  136.  
  137. # The example I chose to use for this function uses the optional xml video information file to pull the high and low
  138. # quality version of a video from the url sent to this URL service.
  139. # It basically pulls the content from the URL, looks through the page to find a mention of the regex value I defined as a
  140. # global variable at the beginning of this document. Because the line of data I was using contained a parenthesis right before
  141. # the address, I had to get a little creative in pulling it and then replacing the ending single quote to properly pull
  142. # the xml address out of the page. The function then opens that xml video info page and uses xpath commands to extract the
  143. # video URL and returns those values in the form of a high and low quality video. Then it uses the fmt variable to determine
  144. # which of these videoss should be the value of video.
  145.  
  146. content = HTTP.Request(url).content
  147. xmlurl = RE_XML_URL.search(content).group(0)
  148. xmlurl = xmlurl.replace("'", '')
  149. xmlurl = base_url + xmlurl
  150.  
  151. xml = XML.ElementFromURL(xmlurl)
  152. if xml:
  153. # Here we are extracting the video file addresses from the xml video file metadata
  154. videoHi = xml.xpath('//video/videoHi//text()')[0]
  155. videoLo = xml.xpath('//video/videoLo')[0].text
  156.  
  157. videoHi = videoHi.replace('.f4v', '.mp4')
  158. videoLo = videoLo.replace('.f4v', '.mp4')
  159.  
  160. if fmt == 'hi':
  161. video = videoHi
  162. else:
  163. video = videoLo
  164.  
  165.  
  166. # We then return the address or value of the video. This video URL is then sent back to the MediObject above with return Redirect(video)
  167. # The Redirect() is a Plex Framework function that essentially tells the Client to look at this new URL for the actual media file.
  168.  
  169. return Redirect(video)
  170.  
  171. ####################################################################################################
  172. def TestURLs():
  173.  
  174. # This is for testing the URL, so you are making sure the URL service is working.
  175. # YOU DO NOT NEED THIS IF YOU PUT A TEST URL IN YOUR SERVICEINFO.PLIST FILE. THIS IS AN ALTERNATIVE WAY IF YOU THINK THE VIDEO PAGES WILL CHANGE
  176. # ALOT AND YOU DO NOT THINK YOU CAN DETERMINE A SPECIFIC URL THAT WILL NOT CHANGE
  177. # This coding below is a basic example that allows you to make the test url more dynamic so the service will not fail just because the
  178. # test url no longer exists. Enter the main domain for urls that will be sent to this service in place of anydomain.com
  179.  
  180. test_urls = []
  181. page = HTML.ElementFromURL('http://www.anydomain.com/')
  182.  
  183. # here in this link command you need to edit this xpath to reflect the id or class is used to represent
  184. # a video player container on pages for this url service and enter the correct domain name
  185. for link in page.xpath("//a/span[@class='vid']/.."):
  186. if len(test_urls) < 3:
  187. url = link.get('href')
  188. url = "http://www.anydomain.com" + url
  189.  
  190. if url not in test_urls:
  191. test_urls.append(url)
  192. else:
  193. break
  194.  
  195. return test_urls
  196.  
  197. ####################################################################
  198. # TESTING YOUR URL SERVICE #
  199. ####################################################################
  200. # To test your url service, the best way is to use 'http://localhost:32400/system/services/url/lookup?url=' followed by an html page that contains
  201. # a video. You must first use a URL encoder like 'http://meyerweb.com/eric/tools/dencoder/' to give the page name the proper format. Paste this
  202. # into the address bar of your browser. This will result in a page that shows you the metadata and a key with video info. If this info does not
  203. # come up, check the system log (come.plexapp.system.log) for errors.
  204. # To see the actual video file url and any errors with playing the video, you will then cut the key from the resulting metadata page you pulled
  205. # up above and add 'http://localhost:32400' to the beginning of it and paste it into the address bar of your browser. The resulting page will show you
  206. # the video file location and any errors in locating it.
Advertisement
Add Comment
Please, Sign In to add comment