diff --git a/docs/supportedsites.md b/docs/supportedsites.md index 35275278b..935e9894b 100644 --- a/docs/supportedsites.md +++ b/docs/supportedsites.md @@ -272,6 +272,7 @@ - **Expressen** - **ExtremeTube** - **EyedoTV** + - **F1TV** - **facebook** - **FacebookPluginsVideo** - **faz.net** diff --git a/youtube_dl/extractor/extractors.py b/youtube_dl/extractor/extractors.py index 44120cae2..4841454b4 100644 --- a/youtube_dl/extractor/extractors.py +++ b/youtube_dl/extractor/extractors.py @@ -361,7 +361,10 @@ from .flickr import FlickrIE from .flipagram import FlipagramIE from .folketinget import FolketingetIE from .footyroom import FootyRoomIE -from .formula1 import Formula1IE +from .formula1 import ( + Formula1IE, + F1TVIE, +) from .fourtube import ( FourTubeIE, PornTubeIE, diff --git a/youtube_dl/extractor/formula1.py b/youtube_dl/extractor/formula1.py index fecfc28ae..3df8f17b3 100644 --- a/youtube_dl/extractor/formula1.py +++ b/youtube_dl/extractor/formula1.py @@ -31,3 +31,59 @@ class Formula1IE(InfoExtractor): r'data-videoid="([^"]+)"', webpage, 'ooyala embed code') return self.url_result( 'ooyala:%s' % ooyala_embed_code, 'Ooyala', ooyala_embed_code) + + +class F1TVIE(InfoExtractor): + _VALID_URL = r'https?://f1tv\.formula1\.com/en/(?:[^/]+)/(?:[^/]+)/(?P.+)' + + _TESTS = [{ + 'url': 'https://f1tv.formula1.com/en/current-season/singapore-grand-prix/2019-singapore-grand-prix-race', + 'info_dict': { + 'id': '2019-singapore-grand-prix-race', + 'ext': 'mp4', + 'title': '2019 Singapore Grand Prix Formula 1 Race', + }, + 'params': { + 'format': 'bestvideo', + # m3u8 download + 'skip_download': True, + }, + }, { + 'url': 'https://f1tv.formula1.com/en/current-season/singapore-grand-prix/2019-singapore-grand-prix-race', + 'only_matching': True, + }] + + _API_BASE = 'https://f1tv.formula1.com/api' + + def _real_extract(self, url): + slug = self._match_id(url) + + metadata = self._download_json( + self._API_BASE + '/session-occurrence/?slug=' + slug + '&fields=session_name,channel_urls&fields_to_expand=channel_urls', + slug + ) + metadata = metadata['objects'][0] + + # Select world feed perspective + for channel in metadata['channel_urls']: + if channel.get('name') == 'WIF': + channelUrl = channel['self'] + break + + channel = self._download_json( + self._API_BASE + '/viewings/', slug, + headers={'Content-Type': 'application/json'}, + data='{"channel_url": "' + channelUrl + '"}', + note='Downloading JSON channel info' + ) + + formats = self._extract_m3u8_formats( + channel['tokenised_url'], slug, + 'mp4', 'm3u8_native', m3u8_id='hls' + ) + + return { + 'id': slug, + 'title': metadata['session_name'], + 'formats': formats, + }