From 4cc768576f1eb4603898347e9ef4de8bb70ac5f0 Mon Sep 17 00:00:00 2001 From: CasperMcFadden95 <145611964+CasperMcFadden95@users.noreply.github.com> Date: Sun, 22 Jun 2025 14:13:58 +0000 Subject: [PATCH 1/7] [ie/EasyBroadcastLiveIE] Add extractor --- yt_dlp/extractor/_extractors.py | 1 + yt_dlp/extractor/easybroadcast.py | 67 +++++++++++++++++++++++++++++++ yt_dlp/extractor/generic.py | 18 +++++++++ 3 files changed, 86 insertions(+) create mode 100644 yt_dlp/extractor/easybroadcast.py diff --git a/yt_dlp/extractor/_extractors.py b/yt_dlp/extractor/_extractors.py index 34c98b537..69d709215 100644 --- a/yt_dlp/extractor/_extractors.py +++ b/yt_dlp/extractor/_extractors.py @@ -574,6 +574,7 @@ ClipYouEmbedIE, EaglePlatformIE, ) +from .easybroadcast import EasyBroadcastLiveIE from .ebaumsworld import EbaumsWorldIE from .ebay import EbayIE from .egghead import ( diff --git a/yt_dlp/extractor/easybroadcast.py b/yt_dlp/extractor/easybroadcast.py new file mode 100644 index 000000000..0a4af90dd --- /dev/null +++ b/yt_dlp/extractor/easybroadcast.py @@ -0,0 +1,67 @@ + +from yt_dlp.extractor.common import InfoExtractor +from yt_dlp.utils import ( + ExtractorError, +) + + +class EasyBroadcastLiveIE(InfoExtractor): + _VALID_URL = r'https?://(?:\w+\.)?player\.easybroadcast\.io/events/(?P[0-9a-zA-Z_]+)' + _TESTS = [ + { + 'url': 'https://al24.player.easybroadcast.io/events/66_al24_u4yga6h', + 'info_dict': { + 'id': '66_al24_u4yga6h', + 'title': 'Al24', + 'ext': 'mp4', + 'live_status': 'is_live', + }, + }, + { + 'url': 'https://snrt.player.easybroadcast.io/events/73_aloula_w1dqfwm', + 'info_dict': { + 'id': '73_aloula_w1dqfwm', + 'title': 'Aloula', + 'ext': 'mp4', + 'live_status': 'is_live', + }, + }, + { + 'url': 'https://captaprod.player.easybroadcast.io/events/54_tvr_vtucuxt', + 'info_dict': { + 'id': '54_tvr_vtucuxt', + 'title': 'TVR', + 'ext': 'mp4', + 'live_status': 'is_live', + }, + }, + ] + + def _real_extract(self, url): + event_id = self._match_id(url) + + base_url = url.split('/events/')[0] + api_url = f'{base_url}/api/events/{event_id}' + metadata = self._download_json(api_url, event_id, note='Downloading EasyBroadcast event metadata') + + m3u8_url = metadata.get('stream') + token = None + if metadata.get('token_authentication', False): + token_api_url = f'https://token.easybroadcast.io/all?url={m3u8_url}' + token = self._download_webpage(token_api_url, event_id, note='Fetching stream token').strip() + m3u8_url = m3u8_url + '?' + token + if not token: + raise ExtractorError('Empty token returned from token server.') + + formats = self._extract_m3u8_formats(m3u8_url, video_id=event_id, ext='mp4', m3u8_id='hls', live=True) + + if token: + for fmt in formats: + fmt['url'] = fmt['url'] + '?' + token + + return { + 'id': event_id, + 'title': metadata.get('name', event_id), + 'formats': formats, + 'is_live': True, + } diff --git a/yt_dlp/extractor/generic.py b/yt_dlp/extractor/generic.py index 721d04e31..368d5ab21 100644 --- a/yt_dlp/extractor/generic.py +++ b/yt_dlp/extractor/generic.py @@ -6,6 +6,7 @@ from .common import InfoExtractor from .commonprotocols import RtmpIE +from .easybroadcast import EasyBroadcastLiveIE from .youtube import YoutubeIE from ..compat import compat_etree_fromstring from ..cookies import LenientSimpleCookie @@ -804,6 +805,16 @@ class GenericIE(InfoExtractor): }, 'skip': 'All The Daily Show URLs now redirect to http://www.cc.com/shows/', }, + # EasyBroadcast embed + { + 'url': 'https://al24news.dz/en/live', + 'info_dict': { + 'id': '66_al24_u4yga6h', + 'title': 'Al24', + 'ext': 'mp4', + 'live_status': 'is_live', + }, + }, # jwplayer YouTube { 'url': 'http://media.nationalarchives.gov.uk/index.php/webinar-using-discovery-national-archives-online-catalogue/', @@ -2612,6 +2623,13 @@ def _extract_embeds(self, url, webpage, *, urlh=None, info_dict={}): if embeds: return embeds + # EasyBroadcast embed + mobj = re.search( + EasyBroadcastLiveIE._VALID_URL, + webpage) + if mobj is not None: + return [self.url_result(mobj.group(0), ie=EasyBroadcastLiveIE)] + jwplayer_data = self._find_jwplayer_data( webpage, video_id, transform_source=js_to_json) if jwplayer_data: From ce19f1b4861cdb58820180c5ff9bce8ab8641fd8 Mon Sep 17 00:00:00 2001 From: CasperMcFadden95 <145611964+CasperMcFadden95@users.noreply.github.com> Date: Sun, 22 Jun 2025 17:07:11 +0000 Subject: [PATCH 2/7] Use _EMBED_REGEX --- yt_dlp/extractor/generic.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/yt_dlp/extractor/generic.py b/yt_dlp/extractor/generic.py index 368d5ab21..721d04e31 100644 --- a/yt_dlp/extractor/generic.py +++ b/yt_dlp/extractor/generic.py @@ -6,7 +6,6 @@ from .common import InfoExtractor from .commonprotocols import RtmpIE -from .easybroadcast import EasyBroadcastLiveIE from .youtube import YoutubeIE from ..compat import compat_etree_fromstring from ..cookies import LenientSimpleCookie @@ -805,16 +804,6 @@ class GenericIE(InfoExtractor): }, 'skip': 'All The Daily Show URLs now redirect to http://www.cc.com/shows/', }, - # EasyBroadcast embed - { - 'url': 'https://al24news.dz/en/live', - 'info_dict': { - 'id': '66_al24_u4yga6h', - 'title': 'Al24', - 'ext': 'mp4', - 'live_status': 'is_live', - }, - }, # jwplayer YouTube { 'url': 'http://media.nationalarchives.gov.uk/index.php/webinar-using-discovery-national-archives-online-catalogue/', @@ -2623,13 +2612,6 @@ def _extract_embeds(self, url, webpage, *, urlh=None, info_dict={}): if embeds: return embeds - # EasyBroadcast embed - mobj = re.search( - EasyBroadcastLiveIE._VALID_URL, - webpage) - if mobj is not None: - return [self.url_result(mobj.group(0), ie=EasyBroadcastLiveIE)] - jwplayer_data = self._find_jwplayer_data( webpage, video_id, transform_source=js_to_json) if jwplayer_data: From 9f716e23fdb2c0486ee4d9e9d045aab936a2dc99 Mon Sep 17 00:00:00 2001 From: CasperMcFadden95 <145611964+CasperMcFadden95@users.noreply.github.com> Date: Sun, 22 Jun 2025 18:31:23 +0000 Subject: [PATCH 3/7] Use _EMBED_REGEX --- yt_dlp/extractor/easybroadcast.py | 34 ++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/yt_dlp/extractor/easybroadcast.py b/yt_dlp/extractor/easybroadcast.py index 0a4af90dd..ef3a375f1 100644 --- a/yt_dlp/extractor/easybroadcast.py +++ b/yt_dlp/extractor/easybroadcast.py @@ -7,33 +7,57 @@ class EasyBroadcastLiveIE(InfoExtractor): _VALID_URL = r'https?://(?:\w+\.)?player\.easybroadcast\.io/events/(?P[0-9a-zA-Z_]+)' + _EMBED_REGEX = [rf'