logo

youtube-dl

[mirror] Download/Watch videos from video hostersgit clone https://hacktivis.me/git/mirror/youtube-dl.git

slideslive.py (4230B)


  1. # coding: utf-8
  2. from __future__ import unicode_literals
  3. from .common import InfoExtractor
  4. from ..utils import (
  5. bool_or_none,
  6. smuggle_url,
  7. try_get,
  8. url_or_none,
  9. )
  10. class SlidesLiveIE(InfoExtractor):
  11. _VALID_URL = r'https?://slideslive\.com/(?P<id>[0-9]+)'
  12. _TESTS = [{
  13. # video_service_name = YOUTUBE
  14. 'url': 'https://slideslive.com/38902413/gcc-ia16-backend',
  15. 'md5': 'b29fcd6c6952d0c79c5079b0e7a07e6f',
  16. 'info_dict': {
  17. 'id': 'LMtgR8ba0b0',
  18. 'ext': 'mp4',
  19. 'title': 'GCC IA16 backend',
  20. 'description': 'Watch full version of this video at https://slideslive.com/38902413.',
  21. 'uploader': 'SlidesLive Videos - A',
  22. 'uploader_id': 'UC62SdArr41t_-_fX40QCLRw',
  23. 'timestamp': 1597615266,
  24. 'upload_date': '20170925',
  25. }
  26. }, {
  27. # video_service_name = yoda
  28. 'url': 'https://slideslive.com/38935785',
  29. 'md5': '575cd7a6c0acc6e28422fe76dd4bcb1a',
  30. 'info_dict': {
  31. 'id': 'RMraDYN5ozA_',
  32. 'ext': 'mp4',
  33. 'title': 'Offline Reinforcement Learning: From Algorithms to Practical Challenges',
  34. },
  35. 'params': {
  36. 'format': 'bestvideo',
  37. },
  38. }, {
  39. # video_service_name = youtube
  40. 'url': 'https://slideslive.com/38903721/magic-a-scientific-resurrection-of-an-esoteric-legend',
  41. 'only_matching': True,
  42. }, {
  43. # video_service_name = url
  44. 'url': 'https://slideslive.com/38922070/learning-transferable-skills-1',
  45. 'only_matching': True,
  46. }, {
  47. # video_service_name = vimeo
  48. 'url': 'https://slideslive.com/38921896/retrospectives-a-venue-for-selfreflection-in-ml-research-3',
  49. 'only_matching': True,
  50. }]
  51. def _real_extract(self, url):
  52. video_id = self._match_id(url)
  53. video_data = self._download_json(
  54. 'https://ben.slideslive.com/player/' + video_id, video_id)
  55. service_name = video_data['video_service_name'].lower()
  56. assert service_name in ('url', 'yoda', 'vimeo', 'youtube')
  57. service_id = video_data['video_service_id']
  58. subtitles = {}
  59. for sub in try_get(video_data, lambda x: x['subtitles'], list) or []:
  60. if not isinstance(sub, dict):
  61. continue
  62. webvtt_url = url_or_none(sub.get('webvtt_url'))
  63. if not webvtt_url:
  64. continue
  65. lang = sub.get('language') or 'en'
  66. subtitles.setdefault(lang, []).append({
  67. 'url': webvtt_url,
  68. })
  69. info = {
  70. 'id': video_id,
  71. 'thumbnail': video_data.get('thumbnail'),
  72. 'is_live': bool_or_none(video_data.get('is_live')),
  73. 'subtitles': subtitles,
  74. }
  75. if service_name in ('url', 'yoda'):
  76. info['title'] = video_data['title']
  77. if service_name == 'url':
  78. info['url'] = service_id
  79. else:
  80. formats = []
  81. _MANIFEST_PATTERN = 'https://01.cdn.yoda.slideslive.com/%s/master.%s'
  82. # use `m3u8` entry_protocol until EXT-X-MAP is properly supported by `m3u8_native` entry_protocol
  83. formats.extend(self._extract_m3u8_formats(
  84. _MANIFEST_PATTERN % (service_id, 'm3u8'),
  85. service_id, 'mp4', m3u8_id='hls', fatal=False))
  86. formats.extend(self._extract_mpd_formats(
  87. _MANIFEST_PATTERN % (service_id, 'mpd'), service_id,
  88. mpd_id='dash', fatal=False))
  89. self._sort_formats(formats)
  90. info.update({
  91. 'id': service_id,
  92. 'formats': formats,
  93. })
  94. else:
  95. info.update({
  96. '_type': 'url_transparent',
  97. 'url': service_id,
  98. 'ie_key': service_name.capitalize(),
  99. 'title': video_data.get('title'),
  100. })
  101. if service_name == 'vimeo':
  102. info['url'] = smuggle_url(
  103. 'https://player.vimeo.com/video/' + service_id,
  104. {'http_headers': {'Referer': url}})
  105. return info