You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
8.0 KiB

  1. # coding: utf-8
  2. from __future__ import unicode_literals
  3. from .common import InfoExtractor
  4. from ..utils import (
  5. ExtractorError,
  6. int_or_none,
  7. float_or_none,
  8. mimetype2ext,
  9. parse_iso8601,
  10. remove_end,
  11. update_url_query,
  12. )
  13. class DRTVIE(InfoExtractor):
  14. _VALID_URL = r'https?://(?:www\.)?dr\.dk/(?:tv/se|nyheder|radio/ondemand)/(?:[^/]+/)*(?P<id>[\da-z-]+)(?:[/#?]|$)'
  15. IE_NAME = 'drtv'
  16. _TESTS = [{
  17. 'url': 'https://www.dr.dk/tv/se/boern/ultra/klassen-ultra/klassen-darlig-taber-10',
  18. 'md5': '25e659cccc9a2ed956110a299fdf5983',
  19. 'info_dict': {
  20. 'id': 'klassen-darlig-taber-10',
  21. 'ext': 'mp4',
  22. 'title': 'Klassen - Dårlig taber (10)',
  23. 'description': 'md5:815fe1b7fa656ed80580f31e8b3c79aa',
  24. 'timestamp': 1471991907,
  25. 'upload_date': '20160823',
  26. 'duration': 606.84,
  27. },
  28. 'params': {
  29. 'skip_download': True,
  30. },
  31. }, {
  32. 'url': 'https://www.dr.dk/nyheder/indland/live-christianias-rydning-af-pusher-street-er-i-gang',
  33. 'md5': '2c37175c718155930f939ef59952474a',
  34. 'info_dict': {
  35. 'id': 'christiania-pusher-street-ryddes-drdkrjpo',
  36. 'ext': 'mp4',
  37. 'title': 'LIVE Christianias rydning af Pusher Street er i gang',
  38. 'description': '- Det er det fedeste, der er sket i 20 år, fortæller christianit til DR Nyheder.',
  39. 'timestamp': 1472800279,
  40. 'upload_date': '20160902',
  41. 'duration': 131.4,
  42. },
  43. }]
  44. def _real_extract(self, url):
  45. video_id = self._match_id(url)
  46. webpage = self._download_webpage(url, video_id)
  47. if '>Programmet er ikke længere tilgængeligt' in webpage:
  48. raise ExtractorError(
  49. 'Video %s is not available' % video_id, expected=True)
  50. video_id = self._search_regex(
  51. (r'data-(?:material-identifier|episode-slug)="([^"]+)"',
  52. r'data-resource="[^>"]+mu/programcard/expanded/([^"]+)"'),
  53. webpage, 'video id')
  54. programcard = self._download_json(
  55. 'http://www.dr.dk/mu/programcard/expanded/%s' % video_id,
  56. video_id, 'Downloading video JSON')
  57. data = programcard['Data'][0]
  58. title = remove_end(self._og_search_title(
  59. webpage, default=None), ' | TV | DR') or data['Title']
  60. description = self._og_search_description(
  61. webpage, default=None) or data.get('Description')
  62. timestamp = parse_iso8601(data.get('CreatedTime'))
  63. thumbnail = None
  64. duration = None
  65. restricted_to_denmark = False
  66. formats = []
  67. subtitles = {}
  68. for asset in data['Assets']:
  69. kind = asset.get('Kind')
  70. if kind == 'Image':
  71. thumbnail = asset.get('Uri')
  72. elif kind in ('VideoResource', 'AudioResource'):
  73. duration = float_or_none(asset.get('DurationInMilliseconds'), 1000)
  74. restricted_to_denmark = asset.get('RestrictedToDenmark')
  75. spoken_subtitles = asset.get('Target') == 'SpokenSubtitles'
  76. for link in asset.get('Links', []):
  77. uri = link.get('Uri')
  78. if not uri:
  79. continue
  80. target = link.get('Target')
  81. format_id = target or ''
  82. preference = None
  83. if spoken_subtitles:
  84. preference = -1
  85. format_id += '-spoken-subtitles'
  86. if target == 'HDS':
  87. f4m_formats = self._extract_f4m_formats(
  88. uri + '?hdcore=3.3.0&plugin=aasp-3.3.0.99.43',
  89. video_id, preference, f4m_id=format_id)
  90. if kind == 'AudioResource':
  91. for f in f4m_formats:
  92. f['vcodec'] = 'none'
  93. formats.extend(f4m_formats)
  94. elif target == 'HLS':
  95. formats.extend(self._extract_m3u8_formats(
  96. uri, video_id, 'mp4', entry_protocol='m3u8_native',
  97. preference=preference, m3u8_id=format_id))
  98. else:
  99. bitrate = link.get('Bitrate')
  100. if bitrate:
  101. format_id += '-%s' % bitrate
  102. formats.append({
  103. 'url': uri,
  104. 'format_id': format_id,
  105. 'tbr': int_or_none(bitrate),
  106. 'ext': link.get('FileFormat'),
  107. 'vcodec': 'none' if kind == 'AudioResource' else None,
  108. })
  109. subtitles_list = asset.get('SubtitlesList')
  110. if isinstance(subtitles_list, list):
  111. LANGS = {
  112. 'Danish': 'da',
  113. }
  114. for subs in subtitles_list:
  115. if not subs.get('Uri'):
  116. continue
  117. lang = subs.get('Language') or 'da'
  118. subtitles.setdefault(LANGS.get(lang, lang), []).append({
  119. 'url': subs['Uri'],
  120. 'ext': mimetype2ext(subs.get('MimeType')) or 'vtt'
  121. })
  122. if not formats and restricted_to_denmark:
  123. self.raise_geo_restricted(
  124. 'Unfortunately, DR is not allowed to show this program outside Denmark.',
  125. expected=True)
  126. self._sort_formats(formats)
  127. return {
  128. 'id': video_id,
  129. 'title': title,
  130. 'description': description,
  131. 'thumbnail': thumbnail,
  132. 'timestamp': timestamp,
  133. 'duration': duration,
  134. 'formats': formats,
  135. 'subtitles': subtitles,
  136. }
  137. class DRTVLiveIE(InfoExtractor):
  138. IE_NAME = 'drtv:live'
  139. _VALID_URL = r'https?://(?:www\.)?dr\.dk/(?:tv|TV)/live/(?P<id>[\da-z-]+)'
  140. _TEST = {
  141. 'url': 'https://www.dr.dk/tv/live/dr1',
  142. 'info_dict': {
  143. 'id': 'dr1',
  144. 'ext': 'mp4',
  145. 'title': 're:^DR1 [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
  146. },
  147. 'params': {
  148. # m3u8 download
  149. 'skip_download': True,
  150. },
  151. }
  152. def _real_extract(self, url):
  153. channel_id = self._match_id(url)
  154. channel_data = self._download_json(
  155. 'https://www.dr.dk/mu-online/api/1.0/channel/' + channel_id,
  156. channel_id)
  157. title = self._live_title(channel_data['Title'])
  158. formats = []
  159. for streaming_server in channel_data.get('StreamingServers', []):
  160. server = streaming_server.get('Server')
  161. if not server:
  162. continue
  163. link_type = streaming_server.get('LinkType')
  164. for quality in streaming_server.get('Qualities', []):
  165. for stream in quality.get('Streams', []):
  166. stream_path = stream.get('Stream')
  167. if not stream_path:
  168. continue
  169. stream_url = update_url_query(
  170. '%s/%s' % (server, stream_path), {'b': ''})
  171. if link_type == 'HLS':
  172. formats.extend(self._extract_m3u8_formats(
  173. stream_url, channel_id, 'mp4',
  174. m3u8_id=link_type, fatal=False, live=True))
  175. elif link_type == 'HDS':
  176. formats.extend(self._extract_f4m_formats(update_url_query(
  177. '%s/%s' % (server, stream_path), {'hdcore': '3.7.0'}),
  178. channel_id, f4m_id=link_type, fatal=False))
  179. self._sort_formats(formats)
  180. return {
  181. 'id': channel_id,
  182. 'title': title,
  183. 'thumbnail': channel_data.get('PrimaryImageUri'),
  184. 'formats': formats,
  185. 'is_live': True,
  186. }