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.

122 lines
4.3 KiB

  1. # coding: utf-8
  2. from __future__ import unicode_literals
  3. from .common import InfoExtractor
  4. from ..compat import compat_HTTPError
  5. from ..utils import (
  6. float_or_none,
  7. int_or_none,
  8. try_get,
  9. # unified_timestamp,
  10. ExtractorError,
  11. )
  12. class RedBullTVIE(InfoExtractor):
  13. _VALID_URL = r'https?://(?:www\.)?redbull\.tv/(?:video|film)/(?P<id>AP-\w+)'
  14. _TESTS = [{
  15. # film
  16. 'url': 'https://www.redbull.tv/video/AP-1Q756YYX51W11/abc-of-wrc',
  17. 'md5': 'fb0445b98aa4394e504b413d98031d1f',
  18. 'info_dict': {
  19. 'id': 'AP-1Q756YYX51W11',
  20. 'ext': 'mp4',
  21. 'title': 'ABC of...WRC',
  22. 'description': 'md5:5c7ed8f4015c8492ecf64b6ab31e7d31',
  23. 'duration': 1582.04,
  24. # 'timestamp': 1488405786,
  25. # 'upload_date': '20170301',
  26. },
  27. }, {
  28. # episode
  29. 'url': 'https://www.redbull.tv/video/AP-1PMT5JCWH1W11/grime?playlist=shows:shows-playall:web',
  30. 'info_dict': {
  31. 'id': 'AP-1PMT5JCWH1W11',
  32. 'ext': 'mp4',
  33. 'title': 'Grime - Hashtags S2 E4',
  34. 'description': 'md5:334b741c8c1ce65be057eab6773c1cf5',
  35. 'duration': 904.6,
  36. # 'timestamp': 1487290093,
  37. # 'upload_date': '20170217',
  38. 'series': 'Hashtags',
  39. 'season_number': 2,
  40. 'episode_number': 4,
  41. },
  42. }, {
  43. 'url': 'https://www.redbull.tv/film/AP-1MSKKF5T92111/in-motion',
  44. 'only_matching': True,
  45. }]
  46. def _real_extract(self, url):
  47. video_id = self._match_id(url)
  48. session = self._download_json(
  49. 'https://api-v2.redbull.tv/session', video_id,
  50. note='Downloading access token', query={
  51. 'build': '4.370.0',
  52. 'category': 'personal_computer',
  53. 'os_version': '1.0',
  54. 'os_family': 'http',
  55. })
  56. if session.get('code') == 'error':
  57. raise ExtractorError('%s said: %s' % (
  58. self.IE_NAME, session['message']))
  59. auth = '%s %s' % (session.get('token_type', 'Bearer'), session['access_token'])
  60. try:
  61. info = self._download_json(
  62. 'https://api-v2.redbull.tv/content/%s' % video_id,
  63. video_id, note='Downloading video information',
  64. headers={'Authorization': auth}
  65. )
  66. except ExtractorError as e:
  67. if isinstance(e.cause, compat_HTTPError) and e.cause.code == 404:
  68. error_message = self._parse_json(
  69. e.cause.read().decode(), video_id)['message']
  70. raise ExtractorError('%s said: %s' % (
  71. self.IE_NAME, error_message), expected=True)
  72. raise
  73. video = info['video_product']
  74. title = info['title'].strip()
  75. formats = self._extract_m3u8_formats(
  76. video['url'], video_id, 'mp4', 'm3u8_native')
  77. self._sort_formats(formats)
  78. subtitles = {}
  79. for _, captions in (try_get(
  80. video, lambda x: x['attachments']['captions'],
  81. dict) or {}).items():
  82. if not captions or not isinstance(captions, list):
  83. continue
  84. for caption in captions:
  85. caption_url = caption.get('url')
  86. if not caption_url:
  87. continue
  88. ext = caption.get('format')
  89. if ext == 'xml':
  90. ext = 'ttml'
  91. subtitles.setdefault(caption.get('lang') or 'en', []).append({
  92. 'url': caption_url,
  93. 'ext': ext,
  94. })
  95. subheading = info.get('subheading')
  96. if subheading:
  97. title += ' - %s' % subheading
  98. return {
  99. 'id': video_id,
  100. 'title': title,
  101. 'description': info.get('long_description') or info.get(
  102. 'short_description'),
  103. 'duration': float_or_none(video.get('duration'), scale=1000),
  104. # 'timestamp': unified_timestamp(info.get('published')),
  105. 'series': info.get('show_title'),
  106. 'season_number': int_or_none(info.get('season_number')),
  107. 'episode_number': int_or_none(info.get('episode_number')),
  108. 'formats': formats,
  109. 'subtitles': subtitles,
  110. }