| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  | # coding: utf-8 | 
					
						
							|  |  |  | from __future__ import unicode_literals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from .common import InfoExtractor | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  | from ..compat import ( | 
					
						
							|  |  |  |     compat_str, | 
					
						
							|  |  |  |     compat_HTTPError, | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | from ..utils import ( | 
					
						
							|  |  |  |     qualities, | 
					
						
							|  |  |  |     strip_or_none, | 
					
						
							|  |  |  |     int_or_none, | 
					
						
							|  |  |  |     ExtractorError, | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FilmOnIE(InfoExtractor): | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |     IE_NAME = 'filmon' | 
					
						
							|  |  |  |     _VALID_URL = r'(?:https?://(?:www\.)?filmon\.com/vod/view/|filmon:)(?P<id>\d+)' | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |     _TESTS = [{ | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         'url': 'https://www.filmon.com/vod/view/24869-0-plan-9-from-outer-space', | 
					
						
							|  |  |  |         'info_dict': { | 
					
						
							|  |  |  |             'id': '24869', | 
					
						
							|  |  |  |             'ext': 'mp4', | 
					
						
							|  |  |  |             'title': 'Plan 9 From Outer Space', | 
					
						
							|  |  |  |             'description': 'Dead human, zombies and vampires', | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |     }, { | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         'url': 'https://www.filmon.com/vod/view/2825-1-popeye-series-1', | 
					
						
							|  |  |  |         'info_dict': { | 
					
						
							|  |  |  |             'id': '2825', | 
					
						
							|  |  |  |             'title': 'Popeye Series 1', | 
					
						
							|  |  |  |             'description': 'The original series of Popeye.', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         'playlist_mincount': 8, | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |     }] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _real_extract(self, url): | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         video_id = self._match_id(url) | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         try: | 
					
						
							|  |  |  |             response = self._download_json( | 
					
						
							|  |  |  |                 'https://www.filmon.com/api/vod/movie?id=%s' % video_id, | 
					
						
							|  |  |  |                 video_id)['response'] | 
					
						
							|  |  |  |         except ExtractorError as e: | 
					
						
							|  |  |  |             if isinstance(e.cause, compat_HTTPError): | 
					
						
							|  |  |  |                 errmsg = self._parse_json(e.cause.read().decode(), video_id)['reason'] | 
					
						
							|  |  |  |                 raise ExtractorError('%s said: %s' % (self.IE_NAME, errmsg), expected=True) | 
					
						
							|  |  |  |             raise | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         title = response['title'] | 
					
						
							|  |  |  |         description = strip_or_none(response.get('description')) | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         if response.get('type_id') == 1: | 
					
						
							|  |  |  |             entries = [self.url_result('filmon:' + episode_id) for episode_id in response.get('episodes', [])] | 
					
						
							|  |  |  |             return self.playlist_result(entries, video_id, title, description) | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         QUALITY = qualities(('low', 'high')) | 
					
						
							|  |  |  |         formats = [] | 
					
						
							|  |  |  |         for format_id, stream in response.get('streams', {}).items(): | 
					
						
							|  |  |  |             stream_url = stream.get('url') | 
					
						
							|  |  |  |             if not stream_url: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |             formats.append({ | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |                 'format_id': format_id, | 
					
						
							|  |  |  |                 'url': stream_url, | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |                 'ext': 'mp4', | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |                 'quality': QUALITY(stream.get('quality')), | 
					
						
							|  |  |  |                 'protocol': 'm3u8_native', | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |             }) | 
					
						
							|  |  |  |         self._sort_formats(formats) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         thumbnails = [] | 
					
						
							|  |  |  |         poster = response.get('poster', {}) | 
					
						
							|  |  |  |         thumbs = poster.get('thumbs', {}) | 
					
						
							|  |  |  |         thumbs['poster'] = poster | 
					
						
							|  |  |  |         for thumb_id, thumb in thumbs.items(): | 
					
						
							|  |  |  |             thumb_url = thumb.get('url') | 
					
						
							|  |  |  |             if not thumb_url: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             thumbnails.append({ | 
					
						
							|  |  |  |                 'id': thumb_id, | 
					
						
							|  |  |  |                 'url': thumb_url, | 
					
						
							|  |  |  |                 'width': int_or_none(thumb.get('width')), | 
					
						
							|  |  |  |                 'height': int_or_none(thumb.get('height')), | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |         return { | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |             'id': video_id, | 
					
						
							|  |  |  |             'title': title, | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |             'formats': formats, | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |             'description': description, | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |             'thumbnails': thumbnails, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  | class FilmOnChannelIE(InfoExtractor): | 
					
						
							|  |  |  |     IE_NAME = 'filmon:channel' | 
					
						
							|  |  |  |     _VALID_URL = r'https?://(?:www\.)?filmon\.com/(?:tv|channel)/(?P<id>[a-z0-9-]+)' | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |     _TESTS = [{ | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         # VOD | 
					
						
							|  |  |  |         'url': 'http://www.filmon.com/tv/sports-haters', | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |         'info_dict': { | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |             'id': '4190', | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |             'ext': 'mp4', | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |             'title': 'Sports Haters', | 
					
						
							|  |  |  |             'description': 'md5:dabcb4c1d9cfc77085612f1a85f8275d', | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |         }, | 
					
						
							|  |  |  |     }, { | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         # LIVE | 
					
						
							|  |  |  |         'url': 'https://www.filmon.com/channel/filmon-sports', | 
					
						
							|  |  |  |         'only_matching': True, | 
					
						
							|  |  |  |     }, { | 
					
						
							|  |  |  |         'url': 'https://www.filmon.com/tv/2894', | 
					
						
							|  |  |  |         'only_matching': True, | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |     }] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |     _THUMBNAIL_RES = [ | 
					
						
							|  |  |  |         ('logo', 56, 28), | 
					
						
							|  |  |  |         ('big_logo', 106, 106), | 
					
						
							|  |  |  |         ('extra_big_logo', 300, 300), | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |     def _real_extract(self, url): | 
					
						
							|  |  |  |         channel_id = self._match_id(url) | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         try: | 
					
						
							|  |  |  |             channel_data = self._download_json( | 
					
						
							|  |  |  |                 'http://www.filmon.com/api-v2/channel/' + channel_id, channel_id)['data'] | 
					
						
							|  |  |  |         except ExtractorError as e: | 
					
						
							|  |  |  |             if isinstance(e.cause, compat_HTTPError): | 
					
						
							|  |  |  |                 errmsg = self._parse_json(e.cause.read().decode(), channel_id)['message'] | 
					
						
							|  |  |  |                 raise ExtractorError('%s said: %s' % (self.IE_NAME, errmsg), expected=True) | 
					
						
							|  |  |  |             raise | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         channel_id = compat_str(channel_data['id']) | 
					
						
							|  |  |  |         is_live = not channel_data.get('is_vod') and not channel_data.get('is_vox') | 
					
						
							|  |  |  |         title = channel_data['title'] | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         QUALITY = qualities(('low', 'high')) | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |         formats = [] | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         for stream in channel_data.get('streams', []): | 
					
						
							|  |  |  |             stream_url = stream.get('url') | 
					
						
							|  |  |  |             if not stream_url: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             if not is_live: | 
					
						
							|  |  |  |                 formats.extend(self._extract_wowza_formats( | 
					
						
							|  |  |  |                     stream_url, channel_id, skip_protocols=['dash', 'rtmp', 'rtsp'])) | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             quality = stream.get('quality') | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |             formats.append({ | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |                 'format_id': quality, | 
					
						
							|  |  |  |                 # this is an m3u8 stream, but we are deliberately not using _extract_m3u8_formats | 
					
						
							|  |  |  |                 # because it doesn't have bitrate variants anyway | 
					
						
							|  |  |  |                 'url': stream_url, | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |                 'ext': 'mp4', | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |                 'quality': QUALITY(quality), | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |             }) | 
					
						
							|  |  |  |         self._sort_formats(formats) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |         thumbnails = [] | 
					
						
							|  |  |  |         for name, width, height in self._THUMBNAIL_RES: | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |             thumbnails.append({ | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |                 'id': name, | 
					
						
							|  |  |  |                 'url': 'http://static.filmon.com/assets/channels/%s/%s.png' % (channel_id, name), | 
					
						
							|  |  |  |                 'width': width, | 
					
						
							|  |  |  |                 'height': height, | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |             }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return { | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |             'id': channel_id, | 
					
						
							|  |  |  |             'display_id': channel_data.get('alias'), | 
					
						
							|  |  |  |             'title': self._live_title(title) if is_live else title, | 
					
						
							|  |  |  |             'description': channel_data.get('description'), | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |             'thumbnails': thumbnails, | 
					
						
							| 
									
										
										
										
											2017-02-03 10:15:03 +01:00
										 |  |  |             'formats': formats, | 
					
						
							|  |  |  |             'is_live': is_live, | 
					
						
							| 
									
										
										
										
											2015-08-05 22:40:46 +02:00
										 |  |  |         } |