Merge branch 'master' of github.com:rg3/youtube-dl
This commit is contained in:
		@@ -24,7 +24,7 @@ class BellMediaIE(InfoExtractor):
 | 
			
		||||
                space
 | 
			
		||||
            )\.ca|
 | 
			
		||||
            much\.com
 | 
			
		||||
        )/.*?(?:\bvid=|-vid|~|%7E|/(?:episode)?)(?P<id>[0-9]{6})'''
 | 
			
		||||
        )/.*?(?:\bvid=|-vid|~|%7E|/(?:episode)?)(?P<id>[0-9]{6,})'''
 | 
			
		||||
    _TESTS = [{
 | 
			
		||||
        'url': 'http://www.ctv.ca/video/player?vid=706966',
 | 
			
		||||
        'md5': 'ff2ebbeae0aa2dcc32a830c3fd69b7b0',
 | 
			
		||||
@@ -55,6 +55,9 @@ class BellMediaIE(InfoExtractor):
 | 
			
		||||
    }, {
 | 
			
		||||
        'url': 'http://www.much.com/shows/the-almost-impossible-gameshow/928979/episode-6',
 | 
			
		||||
        'only_matching': True,
 | 
			
		||||
    }, {
 | 
			
		||||
        'url': 'http://www.ctv.ca/DCs-Legends-of-Tomorrow/Video/S2E11-Turncoat-vid1051430',
 | 
			
		||||
        'only_matching': True,
 | 
			
		||||
    }]
 | 
			
		||||
    _DOMAINS = {
 | 
			
		||||
        'thecomedynetwork': 'comedy',
 | 
			
		||||
 
 | 
			
		||||
@@ -9,13 +9,15 @@ from ..utils import (
 | 
			
		||||
    unified_strdate,
 | 
			
		||||
    compat_str,
 | 
			
		||||
    determine_ext,
 | 
			
		||||
    ExtractorError,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DisneyIE(InfoExtractor):
 | 
			
		||||
    _VALID_URL = r'''(?x)
 | 
			
		||||
        https?://(?P<domain>(?:[^/]+\.)?(?:disney\.[a-z]{2,3}(?:\.[a-z]{2})?|disney(?:(?:me|latino)\.com|turkiye\.com\.tr)|starwars\.com))/(?:embed/|(?:[^/]+/)+[\w-]+-)(?P<id>[a-z0-9]{24})'''
 | 
			
		||||
        https?://(?P<domain>(?:[^/]+\.)?(?:disney\.[a-z]{2,3}(?:\.[a-z]{2})?|disney(?:(?:me|latino)\.com|turkiye\.com\.tr)|(?:starwars|marvelkids)\.com))/(?:(?:embed/|(?:[^/]+/)+[\w-]+-)(?P<id>[a-z0-9]{24})|(?:[^/]+/)?(?P<display_id>[^/?#]+))'''
 | 
			
		||||
    _TESTS = [{
 | 
			
		||||
        # Disney.EmbedVideo
 | 
			
		||||
        'url': 'http://video.disney.com/watch/moana-trailer-545ed1857afee5a0ec239977',
 | 
			
		||||
        'info_dict': {
 | 
			
		||||
            'id': '545ed1857afee5a0ec239977',
 | 
			
		||||
@@ -28,6 +30,20 @@ class DisneyIE(InfoExtractor):
 | 
			
		||||
            # m3u8 download
 | 
			
		||||
            'skip_download': True,
 | 
			
		||||
        }
 | 
			
		||||
    }, {
 | 
			
		||||
        # Grill.burger
 | 
			
		||||
        'url': 'http://www.starwars.com/video/rogue-one-a-star-wars-story-intro-featurette',
 | 
			
		||||
        'info_dict': {
 | 
			
		||||
            'id': '5454e9f4e9804a552e3524c8',
 | 
			
		||||
            'ext': 'mp4',
 | 
			
		||||
            'title': '"Intro" Featurette: Rogue One: A Star Wars Story',
 | 
			
		||||
            'upload_date': '20170104',
 | 
			
		||||
            'description': 'Go behind-the-scenes of Rogue One: A Star Wars Story in this featurette with Director Gareth Edwards and the cast of the film.',
 | 
			
		||||
        },
 | 
			
		||||
        'params': {
 | 
			
		||||
            # m3u8 download
 | 
			
		||||
            'skip_download': True,
 | 
			
		||||
        }
 | 
			
		||||
    }, {
 | 
			
		||||
        'url': 'http://videos.disneylatino.com/ver/spider-man-de-regreso-a-casa-primer-adelanto-543a33a1850bdcfcca13bae2',
 | 
			
		||||
        'only_matching': True,
 | 
			
		||||
@@ -43,31 +59,55 @@ class DisneyIE(InfoExtractor):
 | 
			
		||||
    }, {
 | 
			
		||||
        'url': 'http://www.starwars.com/embed/54690d1e6c42e5f09a0fb097',
 | 
			
		||||
        'only_matching': True,
 | 
			
		||||
    }, {
 | 
			
		||||
        'url': 'http://spiderman.marvelkids.com/embed/522900d2ced3c565e4cc0677',
 | 
			
		||||
        'only_matching': True,
 | 
			
		||||
    }, {
 | 
			
		||||
        'url': 'http://spiderman.marvelkids.com/videos/contest-of-champions-part-four-clip-1',
 | 
			
		||||
        'only_matching': True,
 | 
			
		||||
    }, {
 | 
			
		||||
        'url': 'http://disneyjunior.en.disneyme.com/dj/watch-my-friends-tigger-and-pooh-promo',
 | 
			
		||||
        'only_matching': True,
 | 
			
		||||
    }, {
 | 
			
		||||
        'url': 'http://disneyjunior.disney.com/galactech-the-galactech-grab-galactech-an-admiral-rescue',
 | 
			
		||||
        'only_matching': True,
 | 
			
		||||
    }]
 | 
			
		||||
 | 
			
		||||
    def _real_extract(self, url):
 | 
			
		||||
        domain, video_id = re.match(self._VALID_URL, url).groups()
 | 
			
		||||
        webpage = self._download_webpage(
 | 
			
		||||
            'http://%s/embed/%s' % (domain, video_id), video_id)
 | 
			
		||||
        video_data = self._parse_json(self._search_regex(
 | 
			
		||||
            r'Disney\.EmbedVideo=({.+});', webpage, 'embed data'), video_id)['video']
 | 
			
		||||
        domain, video_id, display_id = re.match(self._VALID_URL, url).groups()
 | 
			
		||||
        if not video_id:
 | 
			
		||||
            webpage = self._download_webpage(url, display_id)
 | 
			
		||||
            grill = re.sub(r'"\s*\+\s*"', '', self._search_regex(
 | 
			
		||||
                r'Grill\.burger\s*=\s*({.+})\s*:',
 | 
			
		||||
                webpage, 'grill data'))
 | 
			
		||||
            page_data = next(s for s in self._parse_json(grill, display_id)['stack'] if s.get('type') == 'video')
 | 
			
		||||
            video_data = page_data['data'][0]
 | 
			
		||||
        else:
 | 
			
		||||
            webpage = self._download_webpage(
 | 
			
		||||
                'http://%s/embed/%s' % (domain, video_id), video_id)
 | 
			
		||||
            page_data = self._parse_json(self._search_regex(
 | 
			
		||||
                r'Disney\.EmbedVideo\s*=\s*({.+});',
 | 
			
		||||
                webpage, 'embed data'), video_id)
 | 
			
		||||
            video_data = page_data['video']
 | 
			
		||||
 | 
			
		||||
        for external in video_data.get('externals', []):
 | 
			
		||||
            if external.get('source') == 'vevo':
 | 
			
		||||
                return self.url_result('vevo:' + external['data_id'], 'Vevo')
 | 
			
		||||
 | 
			
		||||
        video_id = video_data['id']
 | 
			
		||||
        title = video_data['title']
 | 
			
		||||
 | 
			
		||||
        formats = []
 | 
			
		||||
        for flavor in video_data.get('flavors', []):
 | 
			
		||||
            flavor_format = flavor.get('format')
 | 
			
		||||
            flavor_url = flavor.get('url')
 | 
			
		||||
            if not flavor_url or not re.match(r'https?://', flavor_url):
 | 
			
		||||
            if not flavor_url or not re.match(r'https?://', flavor_url) or flavor_format == 'mp4_access':
 | 
			
		||||
                continue
 | 
			
		||||
            tbr = int_or_none(flavor.get('bitrate'))
 | 
			
		||||
            if tbr == 99999:
 | 
			
		||||
                formats.extend(self._extract_m3u8_formats(
 | 
			
		||||
                    flavor_url, video_id, 'mp4', m3u8_id=flavor_format, fatal=False))
 | 
			
		||||
                    flavor_url, video_id, 'mp4',
 | 
			
		||||
                    m3u8_id=flavor_format, fatal=False))
 | 
			
		||||
                continue
 | 
			
		||||
            format_id = []
 | 
			
		||||
            if flavor_format:
 | 
			
		||||
@@ -88,6 +128,10 @@ class DisneyIE(InfoExtractor):
 | 
			
		||||
                'ext': ext,
 | 
			
		||||
                'vcodec': 'none' if (width == 0 and height == 0) else None,
 | 
			
		||||
            })
 | 
			
		||||
        if not formats and video_data.get('expired'):
 | 
			
		||||
            raise ExtractorError(
 | 
			
		||||
                '%s said: %s' % (self.IE_NAME, page_data['translations']['video_expired']),
 | 
			
		||||
                expected=True)
 | 
			
		||||
        self._sort_formats(formats)
 | 
			
		||||
 | 
			
		||||
        subtitles = {}
 | 
			
		||||
 
 | 
			
		||||
@@ -991,19 +991,6 @@ class GenericIE(InfoExtractor):
 | 
			
		||||
                'title': 'Os Guinness // Is It Fools Talk? // Unbelievable? Conference 2014',
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
        # Kaltura embed protected with referrer
 | 
			
		||||
        {
 | 
			
		||||
            'url': 'http://www.disney.nl/disney-channel/filmpjes/achter-de-schermen#/videoId/violetta-achter-de-schermen-ruggero',
 | 
			
		||||
            'info_dict': {
 | 
			
		||||
                'id': '1_g4fbemnq',
 | 
			
		||||
                'ext': 'mp4',
 | 
			
		||||
                'title': 'Violetta - Achter De Schermen - Ruggero',
 | 
			
		||||
                'description': 'Achter de schermen met Ruggero',
 | 
			
		||||
                'timestamp': 1435133761,
 | 
			
		||||
                'upload_date': '20150624',
 | 
			
		||||
                'uploader_id': 'echojecka',
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
        # Kaltura embed with single quotes
 | 
			
		||||
        {
 | 
			
		||||
            'url': 'http://fod.infobase.com/p_ViewPlaylist.aspx?AssignmentID=NUN8ZY',
 | 
			
		||||
@@ -2350,8 +2337,9 @@ class GenericIE(InfoExtractor):
 | 
			
		||||
                'Channel': 'channel',
 | 
			
		||||
                'ChannelList': 'channel_list',
 | 
			
		||||
            }
 | 
			
		||||
            return self.url_result('limelight:%s:%s' % (
 | 
			
		||||
                lm[mobj.group(1)], mobj.group(2)), 'Limelight%s' % mobj.group(1), mobj.group(2))
 | 
			
		||||
            return self.url_result(smuggle_url('limelight:%s:%s' % (
 | 
			
		||||
                lm[mobj.group(1)], mobj.group(2)), {'source_url': url}),
 | 
			
		||||
                'Limelight%s' % mobj.group(1), mobj.group(2))
 | 
			
		||||
 | 
			
		||||
        mobj = re.search(
 | 
			
		||||
            r'''(?sx)
 | 
			
		||||
@@ -2361,7 +2349,9 @@ class GenericIE(InfoExtractor):
 | 
			
		||||
                        value=(["\'])(?:(?!\3).)*mediaId=(?P<id>[a-z0-9]{32})
 | 
			
		||||
            ''', webpage)
 | 
			
		||||
        if mobj:
 | 
			
		||||
            return self.url_result('limelight:media:%s' % mobj.group('id'))
 | 
			
		||||
            return self.url_result(smuggle_url(
 | 
			
		||||
                'limelight:media:%s' % mobj.group('id'),
 | 
			
		||||
                {'source_url': url}), 'LimelightMedia', mobj.group('id'))
 | 
			
		||||
 | 
			
		||||
        # Look for AdobeTVVideo embeds
 | 
			
		||||
        mobj = re.search(
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ from ..utils import (
 | 
			
		||||
    determine_ext,
 | 
			
		||||
    float_or_none,
 | 
			
		||||
    int_or_none,
 | 
			
		||||
    unsmuggle_url,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -15,20 +16,23 @@ class LimelightBaseIE(InfoExtractor):
 | 
			
		||||
    _PLAYLIST_SERVICE_URL = 'http://production-ps.lvp.llnw.net/r/PlaylistService/%s/%s/%s'
 | 
			
		||||
    _API_URL = 'http://api.video.limelight.com/rest/organizations/%s/%s/%s/%s.json'
 | 
			
		||||
 | 
			
		||||
    def _call_playlist_service(self, item_id, method, fatal=True):
 | 
			
		||||
    def _call_playlist_service(self, item_id, method, fatal=True, referer=None):
 | 
			
		||||
        headers = {}
 | 
			
		||||
        if referer:
 | 
			
		||||
            headers['Referer'] = referer
 | 
			
		||||
        return self._download_json(
 | 
			
		||||
            self._PLAYLIST_SERVICE_URL % (self._PLAYLIST_SERVICE_PATH, item_id, method),
 | 
			
		||||
            item_id, 'Downloading PlaylistService %s JSON' % method, fatal=fatal)
 | 
			
		||||
            item_id, 'Downloading PlaylistService %s JSON' % method, fatal=fatal, headers=headers)
 | 
			
		||||
 | 
			
		||||
    def _call_api(self, organization_id, item_id, method):
 | 
			
		||||
        return self._download_json(
 | 
			
		||||
            self._API_URL % (organization_id, self._API_PATH, item_id, method),
 | 
			
		||||
            item_id, 'Downloading API %s JSON' % method)
 | 
			
		||||
 | 
			
		||||
    def _extract(self, item_id, pc_method, mobile_method, meta_method):
 | 
			
		||||
        pc = self._call_playlist_service(item_id, pc_method)
 | 
			
		||||
    def _extract(self, item_id, pc_method, mobile_method, meta_method, referer=None):
 | 
			
		||||
        pc = self._call_playlist_service(item_id, pc_method, referer=referer)
 | 
			
		||||
        metadata = self._call_api(pc['orgId'], item_id, meta_method)
 | 
			
		||||
        mobile = self._call_playlist_service(item_id, mobile_method, fatal=False)
 | 
			
		||||
        mobile = self._call_playlist_service(item_id, mobile_method, fatal=False, referer=referer)
 | 
			
		||||
        return pc, mobile, metadata
 | 
			
		||||
 | 
			
		||||
    def _extract_info(self, streams, mobile_urls, properties):
 | 
			
		||||
@@ -207,10 +211,13 @@ class LimelightMediaIE(LimelightBaseIE):
 | 
			
		||||
    _API_PATH = 'media'
 | 
			
		||||
 | 
			
		||||
    def _real_extract(self, url):
 | 
			
		||||
        url, smuggled_data = unsmuggle_url(url, {})
 | 
			
		||||
        video_id = self._match_id(url)
 | 
			
		||||
 | 
			
		||||
        pc, mobile, metadata = self._extract(
 | 
			
		||||
            video_id, 'getPlaylistByMediaId', 'getMobilePlaylistByMediaId', 'properties')
 | 
			
		||||
            video_id, 'getPlaylistByMediaId',
 | 
			
		||||
            'getMobilePlaylistByMediaId', 'properties',
 | 
			
		||||
            smuggled_data.get('source_url'))
 | 
			
		||||
 | 
			
		||||
        return self._extract_info(
 | 
			
		||||
            pc['playlistItems'][0].get('streams', []),
 | 
			
		||||
@@ -247,11 +254,13 @@ class LimelightChannelIE(LimelightBaseIE):
 | 
			
		||||
    _API_PATH = 'channels'
 | 
			
		||||
 | 
			
		||||
    def _real_extract(self, url):
 | 
			
		||||
        url, smuggled_data = unsmuggle_url(url, {})
 | 
			
		||||
        channel_id = self._match_id(url)
 | 
			
		||||
 | 
			
		||||
        pc, mobile, medias = self._extract(
 | 
			
		||||
            channel_id, 'getPlaylistByChannelId',
 | 
			
		||||
            'getMobilePlaylistWithNItemsByChannelId?begin=0&count=-1', 'media')
 | 
			
		||||
            'getMobilePlaylistWithNItemsByChannelId?begin=0&count=-1',
 | 
			
		||||
            'media', smuggled_data.get('source_url'))
 | 
			
		||||
 | 
			
		||||
        entries = [
 | 
			
		||||
            self._extract_info(
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user