2 from __future__ 
import unicode_literals
 
   6 from .common 
import InfoExtractor
 
   7 from ..compat 
import compat_urlparse
 
  17 class JWPlatformBaseIE(InfoExtractor
): 
  19     def _find_jwplayer_data(webpage
): 
  20         # TODO: Merge this with JWPlayer-related codes in generic.py 
  23             r
'jwplayer\((?P<quote>[\'"])[^\'" ]+(?P
=quote
)\
)\
.setup\s
*\
((?P
<options
>[^
)]+)\
)', 
  26             return mobj.group('options
') 
  28     def _extract_jwplayer_data(self, webpage, video_id, *args, **kwargs): 
  29         jwplayer_data = self._parse_json( 
  30             self._find_jwplayer_data(webpage), video_id, 
  31             transform_source=js_to_json) 
  32         return self._parse_jwplayer_data( 
  33             jwplayer_data, video_id, *args, **kwargs) 
  35     def _parse_jwplayer_data(self, jwplayer_data, video_id=None, require_title=True, 
  36                              m3u8_id=None, mpd_id=None, rtmp_params=None, base_url=None): 
  37         # JWPlayer backward compatibility: flattened playlists 
  38         # https://github.com/jwplayer/jwplayer/blob/v7.4.3/src/js/api/config.js#L81-L96 
  39         if 'playlist
' not in jwplayer_data: 
  40             jwplayer_data = {'playlist
': [jwplayer_data]} 
  44         # JWPlayer backward compatibility: single playlist item 
  45         # https://github.com/jwplayer/jwplayer/blob/v7.7.0/src/js/playlist/playlist.js#L10 
  46         if not isinstance(jwplayer_data['playlist
'], list): 
  47             jwplayer_data['playlist
'] = [jwplayer_data['playlist
']] 
  49         for video_data in jwplayer_data['playlist
']: 
  50             # JWPlayer backward compatibility: flattened sources 
  51             # https://github.com/jwplayer/jwplayer/blob/v7.4.3/src/js/playlist/item.js#L29-L35 
  52             if 'sources
' not in video_data: 
  53                 video_data['sources
'] = [video_data] 
  55             this_video_id = video_id or video_data['mediaid
'] 
  58             for source in video_data['sources
']: 
  59                 source_url = self._proto_relative_url(source['file']) 
  61                     source_url = compat_urlparse.urljoin(base_url, source_url) 
  62                 source_type = source.get('type') or '' 
  63                 ext = mimetype2ext(source_type) or determine_ext(source_url) 
  64                 if source_type == 'hls
' or ext == 'm3u8
': 
  65                     formats.extend(self._extract_m3u8_formats( 
  66                         source_url, this_video_id, 'mp4
', 'm3u8_native
', m3u8_id=m3u8_id, fatal=False)) 
  68                     formats.extend(self._extract_mpd_formats( 
  69                         source_url, this_video_id, mpd_id=mpd_id, fatal=False)) 
  70                 # https://github.com/jwplayer/jwplayer/blob/master/src/js/providers/default.js#L67 
  71                 elif source_type.startswith('audio
') or ext in ('oga
', 'aac
', 'mp3
', 'mpeg
', 'vorbis
'): 
  78                     height = int_or_none(source.get('height
')) 
  80                         # Often no height is provided but there is a label in 
  82                         height = int_or_none(self._search_regex( 
  83                             r'^
(\d
{3,})[pP
]$
', source.get('label
') or '', 
  84                             'height
', default=None)) 
  87                         'width
': int_or_none(source.get('width
')), 
  91                     if source_url.startswith('rtmp
'): 
  92                         a_format['ext
'] = 'flv
' 
  94                         # See com/longtailvideo/jwplayer/media/RTMPMediaProvider.as 
  95                         # of jwplayer.flash.swf 
  96                         rtmp_url_parts = re.split( 
  97                             r'((?
:mp4|mp3|flv
):)', source_url, 1) 
  98                         if len(rtmp_url_parts) == 3: 
  99                             rtmp_url, prefix, play_path = rtmp_url_parts 
 102                                 'play_path
': prefix + play_path, 
 105                             a_format.update(rtmp_params) 
 106                     formats.append(a_format) 
 107             self._sort_formats(formats) 
 110             tracks = video_data.get('tracks
') 
 111             if tracks and isinstance(tracks, list): 
 113                     if track.get('file') and track.get('kind
') == 'captions
': 
 114                         subtitles.setdefault(track.get('label
') or 'en
', []).append({ 
 115                             'url
': self._proto_relative_url(track['file']) 
 120                 'title
': video_data['title
'] if require_title else video_data.get('title
'), 
 121                 'description
': video_data.get('description
'), 
 122                 'thumbnail
': self._proto_relative_url(video_data.get('image
')), 
 123                 'timestamp
': int_or_none(video_data.get('pubdate
')), 
 124                 'duration
': float_or_none(jwplayer_data.get('duration
')), 
 125                 'subtitles
': subtitles, 
 128         if len(entries) == 1: 
 131             return self.playlist_result(entries) 
 134 class JWPlatformIE(JWPlatformBaseIE): 
 135     _VALID_URL = r'(?
:https?
://content\
.jwplatform\
.com
/(?
:feeds|players|jw6
)/|jwplatform
:)(?P
<id>[a
-zA
-Z0
-9]{8}
)' 
 137         'url
': 'http
://content
.jwplatform
.com
/players
/nPripu9l
-ALJ3XQCI
.js
', 
 138         'md5
': 'fa8899fa601eb7c83a64e9d568bdf325
', 
 142             'title
': 'Big Buck Bunny Trailer
', 
 143             'description
': 'Big Buck Bunny 
is a short animated film by the Blender Institute
. It 
is made using free 
and open source software
.', 
 144             'upload_date
': '20081127', 
 145             'timestamp
': 1227796140, 
 150     def _extract_url(webpage): 
 152             r'<script
[^
>]+?src
=["\'](?P<url>(?:https?:)?//content.jwplatform.com/players/[a-zA-Z0-9]{8})', 
 155             return mobj.group('url') 
 157     def _real_extract(self, url): 
 158         video_id = self._match_id(url) 
 159         json_data = self._download_json('http://content.jwplatform.com/feeds/%s.json' % video_id, video_id) 
 160         return self._parse_jwplayer_data(json_data, video_id)