youtube-dl

Another place where youtube-dl lives on
git clone git://git.oshgnacknak.de/youtube-dl.git
Log | Files | Refs | README | LICENSE

arkena.py (7525B)


      1 # coding: utf-8
      2 from __future__ import unicode_literals
      3 
      4 import re
      5 
      6 from .common import InfoExtractor
      7 from ..compat import compat_urlparse
      8 from ..utils import (
      9     ExtractorError,
     10     float_or_none,
     11     int_or_none,
     12     parse_iso8601,
     13     try_get,
     14 )
     15 
     16 
     17 class ArkenaIE(InfoExtractor):
     18     _VALID_URL = r'''(?x)
     19                         https?://
     20                             (?:
     21                                 video\.(?:arkena|qbrick)\.com/play2/embed/player\?|
     22                                 play\.arkena\.com/(?:config|embed)/avp/v\d/player/media/(?P<id>[^/]+)/[^/]+/(?P<account_id>\d+)
     23                             )
     24                         '''
     25     _TESTS = [{
     26         'url': 'https://video.qbrick.com/play2/embed/player?accountId=1034090&mediaId=d8ab4607-00090107-aab86310',
     27         'md5': '97f117754e5f3c020f5f26da4a44ebaf',
     28         'info_dict': {
     29             'id': 'd8ab4607-00090107-aab86310',
     30             'ext': 'mp4',
     31             'title': 'EM_HT20_117_roslund_v2.mp4',
     32             'timestamp': 1608285912,
     33             'upload_date': '20201218',
     34             'duration': 1429.162667,
     35             'subtitles': {
     36                 'sv': 'count:3',
     37             },
     38         },
     39     }, {
     40         'url': 'https://play.arkena.com/embed/avp/v2/player/media/b41dda37-d8e7-4d3f-b1b5-9a9db578bdfe/1/129411',
     41         'only_matching': True,
     42     }, {
     43         'url': 'https://play.arkena.com/config/avp/v2/player/media/b41dda37-d8e7-4d3f-b1b5-9a9db578bdfe/1/129411/?callbackMethod=jQuery1111023664739129262213_1469227693893',
     44         'only_matching': True,
     45     }, {
     46         'url': 'http://play.arkena.com/config/avp/v1/player/media/327336/darkmatter/131064/?callbackMethod=jQuery1111002221189684892677_1469227595972',
     47         'only_matching': True,
     48     }, {
     49         'url': 'http://play.arkena.com/embed/avp/v1/player/media/327336/darkmatter/131064/',
     50         'only_matching': True,
     51     }, {
     52         'url': 'http://video.arkena.com/play2/embed/player?accountId=472718&mediaId=35763b3b-00090078-bf604299&pageStyling=styled',
     53         'only_matching': True,
     54     }]
     55 
     56     @staticmethod
     57     def _extract_url(webpage):
     58         # See https://support.arkena.com/display/PLAY/Ways+to+embed+your+video
     59         mobj = re.search(
     60             r'<iframe[^>]+src=(["\'])(?P<url>(?:https?:)?//play\.arkena\.com/embed/avp/.+?)\1',
     61             webpage)
     62         if mobj:
     63             return mobj.group('url')
     64 
     65     def _real_extract(self, url):
     66         mobj = re.match(self._VALID_URL, url)
     67         video_id = mobj.group('id')
     68         account_id = mobj.group('account_id')
     69 
     70         # Handle http://video.arkena.com/play2/embed/player URL
     71         if not video_id:
     72             qs = compat_urlparse.parse_qs(compat_urlparse.urlparse(url).query)
     73             video_id = qs.get('mediaId', [None])[0]
     74             account_id = qs.get('accountId', [None])[0]
     75             if not video_id or not account_id:
     76                 raise ExtractorError('Invalid URL', expected=True)
     77 
     78         media = self._download_json(
     79             'https://video.qbrick.com/api/v1/public/accounts/%s/medias/%s' % (account_id, video_id),
     80             video_id, query={
     81                 # https://video.qbrick.com/docs/api/examples/library-api.html
     82                 'fields': 'asset/resources/*/renditions/*(height,id,language,links/*(href,mimeType),type,size,videos/*(audios/*(codec,sampleRate),bitrate,codec,duration,height,width),width),created,metadata/*(title,description),tags',
     83             })
     84         metadata = media.get('metadata') or {}
     85         title = metadata['title']
     86 
     87         duration = None
     88         formats = []
     89         thumbnails = []
     90         subtitles = {}
     91         for resource in media['asset']['resources']:
     92             for rendition in (resource.get('renditions') or []):
     93                 rendition_type = rendition.get('type')
     94                 for i, link in enumerate(rendition.get('links') or []):
     95                     href = link.get('href')
     96                     if not href:
     97                         continue
     98                     if rendition_type == 'image':
     99                         thumbnails.append({
    100                             'filesize': int_or_none(rendition.get('size')),
    101                             'height': int_or_none(rendition.get('height')),
    102                             'id': rendition.get('id'),
    103                             'url': href,
    104                             'width': int_or_none(rendition.get('width')),
    105                         })
    106                     elif rendition_type == 'subtitle':
    107                         subtitles.setdefault(rendition.get('language') or 'en', []).append({
    108                             'url': href,
    109                         })
    110                     elif rendition_type == 'video':
    111                         f = {
    112                             'filesize': int_or_none(rendition.get('size')),
    113                             'format_id': rendition.get('id'),
    114                             'url': href,
    115                         }
    116                         video = try_get(rendition, lambda x: x['videos'][i], dict)
    117                         if video:
    118                             if not duration:
    119                                 duration = float_or_none(video.get('duration'))
    120                             f.update({
    121                                 'height': int_or_none(video.get('height')),
    122                                 'tbr': int_or_none(video.get('bitrate'), 1000),
    123                                 'vcodec': video.get('codec'),
    124                                 'width': int_or_none(video.get('width')),
    125                             })
    126                             audio = try_get(video, lambda x: x['audios'][0], dict)
    127                             if audio:
    128                                 f.update({
    129                                     'acodec': audio.get('codec'),
    130                                     'asr': int_or_none(audio.get('sampleRate')),
    131                                 })
    132                         formats.append(f)
    133                     elif rendition_type == 'index':
    134                         mime_type = link.get('mimeType')
    135                         if mime_type == 'application/smil+xml':
    136                             formats.extend(self._extract_smil_formats(
    137                                 href, video_id, fatal=False))
    138                         elif mime_type == 'application/x-mpegURL':
    139                             formats.extend(self._extract_m3u8_formats(
    140                                 href, video_id, 'mp4', 'm3u8_native',
    141                                 m3u8_id='hls', fatal=False))
    142                         elif mime_type == 'application/hds+xml':
    143                             formats.extend(self._extract_f4m_formats(
    144                                 href, video_id, f4m_id='hds', fatal=False))
    145                         elif mime_type == 'application/dash+xml':
    146                             formats.extend(self._extract_f4m_formats(
    147                                 href, video_id, f4m_id='hds', fatal=False))
    148                         elif mime_type == 'application/vnd.ms-sstr+xml':
    149                             formats.extend(self._extract_ism_formats(
    150                                 href, video_id, ism_id='mss', fatal=False))
    151         self._sort_formats(formats)
    152 
    153         return {
    154             'id': video_id,
    155             'title': title,
    156             'description': metadata.get('description'),
    157             'timestamp': parse_iso8601(media.get('created')),
    158             'thumbnails': thumbnails,
    159             'subtitles': subtitles,
    160             'duration': duration,
    161             'tags': media.get('tags'),
    162             'formats': formats,
    163         }