1 from __future__ 
import unicode_literals
 
   3 from .common 
import InfoExtractor
 
   7     compat_urllib_parse_urlparse
, 
  17 class FiveMinIE(InfoExtractor
): 
  20         (?:https?://[^/]*?5min\.com/Scripts/PlayerSeed\.js\?(?:.*?&)?playList=| 
  21             https?://(?:(?:massively|www)\.)?joystiq\.com/video/| 
  28             # From http://www.engadget.com/2013/11/15/ipad-mini-retina-display-review/ 
  29             'url': 'http://pshared.5min.com/Scripts/PlayerSeed.js?sid=281&width=560&height=345&playList=518013791', 
  30             'md5': '4f7b0b79bf1a470e5004f7112385941d', 
  34                 'title': 'iPad Mini with Retina Display Review', 
  39             # From http://on.aol.com/video/how-to-make-a-next-level-fruit-salad-518086247 
  40             'url': '5min:518086247', 
  41             'md5': 'e539a9dd682c288ef5a498898009f69e', 
  45                 'title': 'How to Make a Next-Level Fruit Salad', 
  51         'ErrorVideoNotExist': 'We\'re sorry, but the video you are trying to watch does not exist.', 
  52         'ErrorVideoNoLongerAvailable': 'We\'re sorry, but the video you are trying to watch is no longer available.', 
  53         'ErrorVideoRejected': 'We\'re sorry, but the video you are trying to watch has been removed.', 
  54         'ErrorVideoUserNotGeo': 'We\'re sorry, but the video you are trying to watch cannot be viewed from your current location.', 
  55         'ErrorVideoLibraryRestriction': 'We\'re sorry, but the video you are trying to watch is currently unavailable for viewing at this domain.', 
  56         'ErrorExposurePermission': 'We\'re sorry, but the video you are trying to watch is currently unavailable for viewing at this domain.', 
  93     def _real_extract(self
, url
): 
  94         video_id 
= self
._match
_id
(url
) 
  95         embed_url 
= 'https://embed.5min.com/playerseed/?playList=%s' % video_id
 
  96         embed_page 
= self
._download
_webpage
(embed_url
, video_id
, 
  97                                             'Downloading embed page') 
  98         sid 
= self
._search
_regex
(r
'sid=(\d+)', embed_page
, 'sid') 
  99         query 
= compat_urllib_parse
.urlencode({ 
 100             'func': 'GetResults', 
 101             'playlist': video_id
, 
 103             'isPlayerSeed': 'true', 
 106         response 
= self
._download
_json
( 
 107             'https://syn.5min.com/handlers/SenseHandler.ashx?' + query
, 
 109         if not response
['success']: 
 110             raise ExtractorError( 
 113                     self
._ERRORS
.get(response
['errorMessage'], response
['errorMessage'])), 
 115         info 
= response
['binding'][0] 
 118         parsed_video_url 
= compat_urllib_parse_urlparse(compat_parse_qs( 
 119             compat_urllib_parse_urlparse(info
['EmbededURL']).query
)['videoUrl'][0]) 
 120         for rendition 
in info
['Renditions']: 
 121             if rendition
['RenditionType'] == 'm3u8': 
 122                 formats
.extend(self
._extract
_m
3u8_formats
(rendition
['Url'], video_id
, m3u8_id
='hls')) 
 123             elif rendition
['RenditionType'] == 'aac': 
 126                 rendition_url 
= compat_urlparse
.urlunparse(parsed_video_url
._replace
(path
=replace_extension(parsed_video_url
.path
.replace('//', '/%s/' % rendition
['ID']), rendition
['RenditionType']))) 
 127                 quality 
= self
._QUALITIES
.get(rendition
['ID'], {}) 
 129                     'format_id': '%s-%d' % (rendition
['RenditionType'], rendition
['ID']), 
 130                     'url': rendition_url
, 
 131                     'width': quality
.get('width'), 
 132                     'height': quality
.get('height'), 
 134         self
._sort
_formats
(formats
) 
 138             'title': info
['Title'], 
 139             'thumbnail': info
.get('ThumbURL'), 
 140             'duration': parse_duration(info
.get('Duration')),