from __future__ import unicode_literals
-from .subtitles import SubtitlesInfoExtractor
+from .common import InfoExtractor
from ..utils import (
fix_xml_ampersands,
parse_duration,
)
-class NPOBaseIE(SubtitlesInfoExtractor):
+class NPOBaseIE(InfoExtractor):
def _get_token(self, video_id):
token_page = self._download_webpage(
'http://ida.omroep.nl/npoplayer/i.js',
video_id, note='Downloading token')
- return self._search_regex(
+ token = self._search_regex(
r'npoplayer\.token = "(.+?)"', token_page, 'token')
+ # Decryption algorithm extracted from http://npoplayer.omroep.nl/csjs/npoplayer-min.js
+ token_l = list(token)
+ first = second = None
+ for i in range(5, len(token_l) - 4):
+ if token_l[i].isdigit():
+ if first is None:
+ first = i
+ elif second is None:
+ second = i
+ if first is None or second is None:
+ first = 12
+ second = 13
+
+ token_l[first], token_l[second] = token_l[second], token_l[first]
+
+ return ''.join(token_l)
class NPOIE(NPOBaseIE):
IE_NAME = 'npo.nl'
- _VALID_URL = r'https?://www\.npo\.nl/[^/]+/[^/]+/(?P<id>[^/?]+)'
+ _VALID_URL = r'https?://(?:www\.)?npo\.nl/(?!live|radio)[^/]+/[^/]+/(?P<id>[^/?]+)'
_TESTS = [
{
def _get_info(self, video_id):
metadata = self._download_json(
- 'http://e.omroep.nl/metadata/aflevering/%s' % video_id,
+ 'http://e.omroep.nl/metadata/%s' % video_id,
video_id,
# We have to remove the javascript callback
transform_source=strip_jsonp,
'quality': stream.get('kwaliteit'),
})
- subtitles = {}
-
- tt888 = metadata.get('tt888')
- if self._have_to_download_any_subtitles and tt888 == 'ja':
- subtitles['nl'] = 'http://e.omroep.nl/tt888/%s' % video_id
- subtitles = self.extract_subtitles(video_id, subtitles)
-
self._sort_formats(formats)
+ subtitles = {}
+ if metadata.get('tt888') == 'ja':
+ subtitles['nl'] = [{
+ 'ext': 'vtt',
+ 'url': 'http://e.omroep.nl/tt888/%s' % video_id,
+ }]
+
return {
'id': video_id,
'title': metadata['titel'],
class NPOLiveIE(NPOBaseIE):
IE_NAME = 'npo.nl:live'
- _VALID_URL = r'https?://www\.npo\.nl/live/(?P<id>.+)'
+ _VALID_URL = r'https?://(?:www\.)?npo\.nl/live/(?P<id>.+)'
_TEST = {
'url': 'http://www.npo.nl/live/npo-1',
if streams:
for stream in streams:
stream_type = stream.get('type').lower()
- if stream_type == 'ss':
+ # smooth streaming is not supported
+ if stream_type in ['ss', 'ms']:
continue
stream_info = self._download_json(
'http://ida.omroep.nl/aapi/?stream=%s&token=%s&type=jsonp'
stream_url = self._download_json(
stream_info['stream'], display_id,
'Downloading %s URL' % stream_type,
- transform_source=strip_jsonp)
+ 'Unable to download %s URL' % stream_type,
+ transform_source=strip_jsonp, fatal=False)
+ if not stream_url:
+ continue
if stream_type == 'hds':
f4m_formats = self._extract_f4m_formats(stream_url, display_id)
# f4m downloader downloads only piece of live stream
else:
formats.append({
'url': stream_url,
+ 'preference': -10,
})
self._sort_formats(formats)
}
+class NPORadioIE(InfoExtractor):
+ IE_NAME = 'npo.nl:radio'
+ _VALID_URL = r'https?://(?:www\.)?npo\.nl/radio/(?P<id>[^/]+)/?$'
+
+ _TEST = {
+ 'url': 'http://www.npo.nl/radio/radio-1',
+ 'info_dict': {
+ 'id': 'radio-1',
+ 'ext': 'mp3',
+ 'title': 're:^NPO Radio 1 [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
+ 'is_live': True,
+ },
+ 'params': {
+ 'skip_download': True,
+ }
+ }
+
+ @staticmethod
+ def _html_get_attribute_regex(attribute):
+ return r'{0}\s*=\s*\'([^\']+)\''.format(attribute)
+
+ def _real_extract(self, url):
+ video_id = self._match_id(url)
+
+ webpage = self._download_webpage(url, video_id)
+
+ title = self._html_search_regex(
+ self._html_get_attribute_regex('data-channel'), webpage, 'title')
+
+ stream = self._parse_json(
+ self._html_search_regex(self._html_get_attribute_regex('data-streams'), webpage, 'data-streams'),
+ video_id)
+
+ codec = stream.get('codec')
+
+ return {
+ 'id': video_id,
+ 'url': stream['url'],
+ 'title': self._live_title(title),
+ 'acodec': codec,
+ 'ext': codec,
+ 'is_live': True,
+ }
+
+
+class NPORadioFragmentIE(InfoExtractor):
+ IE_NAME = 'npo.nl:radio:fragment'
+ _VALID_URL = r'https?://(?:www\.)?npo\.nl/radio/[^/]+/fragment/(?P<id>\d+)'
+
+ _TEST = {
+ 'url': 'http://www.npo.nl/radio/radio-5/fragment/174356',
+ 'md5': 'dd8cc470dad764d0fdc70a9a1e2d18c2',
+ 'info_dict': {
+ 'id': '174356',
+ 'ext': 'mp3',
+ 'title': 'Jubileumconcert Willeke Alberti',
+ },
+ }
+
+ def _real_extract(self, url):
+ audio_id = self._match_id(url)
+
+ webpage = self._download_webpage(url, audio_id)
+
+ title = self._html_search_regex(
+ r'href="/radio/[^/]+/fragment/%s" title="([^"]+)"' % audio_id,
+ webpage, 'title')
+
+ audio_url = self._search_regex(
+ r"data-streams='([^']+)'", webpage, 'audio url')
+
+ return {
+ 'id': audio_id,
+ 'url': audio_url,
+ 'title': title,
+ }
+
+
class TegenlichtVproIE(NPOIE):
IE_NAME = 'tegenlicht.vpro.nl'
_VALID_URL = r'https?://tegenlicht\.vpro\.nl/afleveringen/.*?'