2 from __future__ 
import unicode_literals
 
   6 from .common 
import InfoExtractor
 
   7 from ..compat 
import compat_urllib_parse_unquote
 
  16 class NRKBaseIE(InfoExtractor
): 
  17     def _extract_formats(self
, manifest_url
, video_id
, fatal
=True): 
  19         formats
.extend(self
._extract
_f
4m
_formats
( 
  20             manifest_url 
+ '?hdcore=3.5.0&plugin=aasp-3.5.0.151.81', 
  21             video_id
, f4m_id
='hds', fatal
=fatal
)) 
  22         formats
.extend(self
._extract
_m
3u8_formats
(manifest_url
.replace( 
  23             'akamaihd.net/z/', 'akamaihd.net/i/').replace('/manifest.f4m', '/master.m3u8'), 
  24             video_id
, 'mp4', 'm3u8_native', m3u8_id
='hls', fatal
=fatal
)) 
  27     def _real_extract(self
, url
): 
  28         video_id 
= self
._match
_id
(url
) 
  30         data 
= self
._download
_json
( 
  31             'http://%s/mediaelement/%s' % (self
._API
_HOST
, video_id
), 
  32             video_id
, 'Downloading mediaelement JSON') 
  34         title 
= data
.get('fullTitle') or data
.get('mainTitle') or data
['title'] 
  35         video_id 
= data
.get('id') or video_id
 
  39         media_assets 
= data
.get('mediaAssets') 
  40         if media_assets 
and isinstance(media_assets
, list): 
  41             def video_id_and_title(idx
): 
  42                 return ((video_id
, title
) if len(media_assets
) == 1 
  43                         else ('%s-%d' % (video_id
, idx
), '%s (Part %d)' % (title
, idx
))) 
  44             for num
, asset 
in enumerate(media_assets
, 1): 
  45                 asset_url 
= asset
.get('url') 
  48                 formats 
= self
._extract
_formats
(asset_url
, video_id
, fatal
=False) 
  51                 self
._sort
_formats
(formats
) 
  52                 entry_id
, entry_title 
= video_id_and_title(num
) 
  53                 duration 
= parse_duration(asset
.get('duration')) 
  55                 for subtitle 
in ('webVtt', 'timedText'): 
  56                     subtitle_url 
= asset
.get('%sSubtitlesUrl' % subtitle
) 
  58                         subtitles
.setdefault('no', []).append({ 
  59                             'url': compat_urllib_parse_unquote(subtitle_url
) 
  62                     'id': asset
.get('carrierId') or entry_id
, 
  65                     'subtitles': subtitles
, 
  70             media_url 
= data
.get('mediaUrl') 
  72                 formats 
= self
._extract
_formats
(media_url
, video_id
) 
  73                 self
._sort
_formats
(formats
) 
  74                 duration 
= parse_duration(data
.get('duration')) 
  83             if data
.get('usageRights', {}).get('isGeoBlocked'): 
  85                     'NRK har ikke rettigheter til å vise dette programmet utenfor Norge', 
  88         conviva 
= data
.get('convivaStatistics') or {} 
  89         series 
= conviva
.get('seriesName') or data
.get('seriesTitle') 
  90         episode 
= conviva
.get('episodeName') or data
.get('episodeNumberOrDate') 
  93         images 
= data
.get('images') 
  94         if images 
and isinstance(images
, dict): 
  95             web_images 
= images
.get('webImages') 
  96             if isinstance(web_images
, list): 
  98                     'url': image
['imageUrl'], 
  99                     'width': int_or_none(image
.get('width')), 
 100                     'height': int_or_none(image
.get('height')), 
 101                 } for image 
in web_images 
if image
.get('imageUrl')] 
 103         description 
= data
.get('description') 
 106             'description': description
, 
 109             'age_limit': parse_age_limit(data
.get('legalAge')), 
 110             'thumbnails': thumbnails
, 
 113         vcodec 
= 'none' if data
.get('mediaType') == 'Audio' else None 
 115         # TODO: extract chapters when https://github.com/rg3/youtube-dl/pull/9409 is merged 
 117         for entry 
in entries
: 
 118             entry
.update(common_info
) 
 119             for f 
in entry
['formats']: 
 122         return self
.playlist_result(entries
, video_id
, title
, description
) 
 125 class NRKIE(NRKBaseIE
): 
 126     _VALID_URL 
= r
'(?:nrk:|https?://(?:www\.)?nrk\.no/video/PS\*)(?P<id>\d+)' 
 127     _API_HOST 
= 'v8.psapi.nrk.no' 
 130         'url': 'http://www.nrk.no/video/PS*150533', 
 131         'md5': '2f7f6eeb2aacdd99885f355428715cfa', 
 135             'title': 'Dompap og andre fugler i Piip-Show', 
 136             'description': 'md5:d9261ba34c43b61c812cb6b0269a5c8f', 
 141         'url': 'http://www.nrk.no/video/PS*154915', 
 146             'title': 'Slik høres internett ut når du er blind', 
 147             'description': 'md5:a621f5cc1bd75c8d5104cb048c6b8568', 
 153 class NRKTVIE(NRKBaseIE
): 
 154     IE_DESC 
= 'NRK TV and NRK Radio' 
 155     _VALID_URL 
= r
'https?://(?:tv|radio)\.nrk(?:super)?\.no/(?:serie/[^/]+|program)/(?P<id>[a-zA-Z]{4}\d{8})(?:/\d{2}-\d{2}-\d{4})?(?:#del=(?P<part_id>\d+))?' 
 156     _API_HOST 
= 'psapi-we.nrk.no' 
 159         'url': 'https://tv.nrk.no/serie/20-spoersmaal-tv/MUHH48000314/23-05-2014', 
 160         'md5': '4e9ca6629f09e588ed240fb11619922a', 
 162             'id': 'MUHH48000314AA', 
 164             'title': '20 spørsmål 23.05.2014', 
 165             'description': 'md5:bdea103bc35494c143c6a9acdd84887a', 
 169         'url': 'https://tv.nrk.no/program/mdfp15000514', 
 170         'md5': '43d0be26663d380603a9cf0c24366531', 
 172             'id': 'MDFP15000514CA', 
 174             'title': 'Grunnlovsjubiléet - Stor ståhei for ingenting 24.05.2014', 
 175             'description': 'md5:89290c5ccde1b3a24bb8050ab67fe1db', 
 179         # single playlist video 
 180         'url': 'https://tv.nrk.no/serie/tour-de-ski/MSPO40010515/06-01-2015#del=2', 
 181         'md5': 'adbd1dbd813edaf532b0a253780719c2', 
 183             'id': 'MSPO40010515-part2', 
 185             'title': 'Tour de Ski: Sprint fri teknikk, kvinner og menn 06.01.2015 (del 2:2)', 
 186             'description': 'md5:238b67b97a4ac7d7b4bf0edf8cc57d26', 
 188         'skip': 'Only works from Norway', 
 190         'url': 'https://tv.nrk.no/serie/tour-de-ski/MSPO40010515/06-01-2015', 
 192             'md5': '9480285eff92d64f06e02a5367970a7a', 
 194                 'id': 'MSPO40010515-part1', 
 196                 'title': 'Tour de Ski: Sprint fri teknikk, kvinner og menn 06.01.2015 (del 1:2)', 
 197                 'description': 'md5:238b67b97a4ac7d7b4bf0edf8cc57d26', 
 200             'md5': 'adbd1dbd813edaf532b0a253780719c2', 
 202                 'id': 'MSPO40010515-part2', 
 204                 'title': 'Tour de Ski: Sprint fri teknikk, kvinner og menn 06.01.2015 (del 2:2)', 
 205                 'description': 'md5:238b67b97a4ac7d7b4bf0edf8cc57d26', 
 209             'id': 'MSPO40010515', 
 210             'title': 'Tour de Ski: Sprint fri teknikk, kvinner og menn', 
 211             'description': 'md5:238b67b97a4ac7d7b4bf0edf8cc57d26', 
 214         'skip': 'Only works from Norway', 
 216         'url': 'https://radio.nrk.no/serie/dagsnytt/NPUB21019315/12-07-2015#', 
 217         'only_matching': True, 
 221 class NRKPlaylistIE(InfoExtractor
): 
 222     _VALID_URL 
= r
'https?://(?:www\.)?nrk\.no/(?!video|skole)(?:[^/]+/)+(?P<id>[^/]+)' 
 225         'url': 'http://www.nrk.no/troms/gjenopplev-den-historiske-solformorkelsen-1.12270763', 
 227             'id': 'gjenopplev-den-historiske-solformorkelsen-1.12270763', 
 228             'title': 'Gjenopplev den historiske solformørkelsen', 
 229             'description': 'md5:c2df8ea3bac5654a26fc2834a542feed', 
 233         'url': 'http://www.nrk.no/kultur/bok/rivertonprisen-til-karin-fossum-1.12266449', 
 235             'id': 'rivertonprisen-til-karin-fossum-1.12266449', 
 236             'title': 'Rivertonprisen til Karin Fossum', 
 237             'description': 'Første kvinne på 15 år til å vinne krimlitteraturprisen.', 
 242     def _real_extract(self
, url
): 
 243         playlist_id 
= self
._match
_id
(url
) 
 245         webpage 
= self
._download
_webpage
(url
, playlist_id
) 
 248             self
.url_result('nrk:%s' % video_id
, 'NRK') 
 249             for video_id 
in re
.findall( 
 250                 r
'class="[^"]*\brich\b[^"]*"[^>]+data-video-id="([^"]+)"', 
 254         playlist_title 
= self
._og
_search
_title
(webpage
) 
 255         playlist_description 
= self
._og
_search
_description
(webpage
) 
 257         return self
.playlist_result( 
 258             entries
, playlist_id
, playlist_title
, playlist_description
) 
 261 class NRKSkoleIE(InfoExtractor
): 
 262     IE_DESC 
= 'NRK Skole' 
 263     _VALID_URL 
= r
'https?://(?:www\.)?nrk\.no/skole/?\?.*\bmediaId=(?P<id>\d+)' 
 266         'url': 'https://www.nrk.no/skole/?page=search&q=&mediaId=14099', 
 267         'md5': '6bc936b01f9dd8ed45bc58b252b2d9b6', 
 271             'title': 'Genetikk og eneggede tvillinger', 
 272             'description': 'md5:3aca25dcf38ec30f0363428d2b265f8d', 
 276         'url': 'https://www.nrk.no/skole/?page=objectives&subject=naturfag&objective=K15114&mediaId=19355', 
 277         'only_matching': True, 
 280     def _real_extract(self
, url
): 
 281         video_id 
= self
._match
_id
(url
) 
 283         webpage 
= self
._download
_webpage
( 
 284             'https://mimir.nrk.no/plugin/1.0/static?mediaId=%s' % video_id
, 
 287         nrk_id 
= self
._parse
_json
( 
 289                 r
'<script[^>]+type=["\']application
/json
["\'][^>]*>({.+?})</script>', 
 290                 webpage, 'application json'), 
 291             video_id)['activeMedia']['psId'] 
 293         return self.url_result('nrk:%s' % nrk_id)