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.

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