aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfries1234 <fries12420@gmail.com>2025-04-18 16:35:47 -0700
committerGitHub <noreply@github.com>2025-04-19 01:35:47 +0200
commited8ad1b4d6b9d7a1426ff5192ff924f3371e4721 (patch)
tree09e86dea93b7ec12292b2837f9c52ed47de362a6
parent839d64325356310e6de6cd9cad28fb546619ca63 (diff)
[ie/tvw:tvchannels] Add extractor (#12721)
Authored by: fries1234
-rw-r--r--yt_dlp/extractor/_extractors.py5
-rw-r--r--yt_dlp/extractor/tvw.py54
2 files changed, 55 insertions, 4 deletions
diff --git a/yt_dlp/extractor/_extractors.py b/yt_dlp/extractor/_extractors.py
index f7e3f25c3..9ae1bb36b 100644
--- a/yt_dlp/extractor/_extractors.py
+++ b/yt_dlp/extractor/_extractors.py
@@ -2237,7 +2237,10 @@ from .tvplay import (
TVPlayIE,
)
from .tvplayer import TVPlayerIE
-from .tvw import TvwIE
+from .tvw import (
+ TvwIE,
+ TvwTvChannelsIE,
+)
from .tweakers import TweakersIE
from .twentymin import TwentyMinutenIE
from .twentythreevideo import TwentyThreeVideoIE
diff --git a/yt_dlp/extractor/tvw.py b/yt_dlp/extractor/tvw.py
index 1c060cd7a..0ab926dbd 100644
--- a/yt_dlp/extractor/tvw.py
+++ b/yt_dlp/extractor/tvw.py
@@ -1,13 +1,21 @@
import json
from .common import InfoExtractor
-from ..utils import clean_html, remove_end, unified_timestamp, url_or_none
-from ..utils.traversal import traverse_obj
+from ..utils import (
+ clean_html,
+ extract_attributes,
+ parse_qs,
+ remove_end,
+ require,
+ unified_timestamp,
+ url_or_none,
+)
+from ..utils.traversal import find_element, traverse_obj
class TvwIE(InfoExtractor):
+ IE_NAME = 'tvw'
_VALID_URL = r'https?://(?:www\.)?tvw\.org/video/(?P<id>[^/?#]+)'
-
_TESTS = [{
'url': 'https://tvw.org/video/billy-frank-jr-statue-maquette-unveiling-ceremony-2024011211/',
'md5': '9ceb94fe2bb7fd726f74f16356825703',
@@ -115,3 +123,43 @@ class TvwIE(InfoExtractor):
'is_live': ('eventStatus', {lambda x: x == 'live'}),
}),
}
+
+
+class TvwTvChannelsIE(InfoExtractor):
+ IE_NAME = 'tvw:tvchannels'
+ _VALID_URL = r'https?://(?:www\.)?tvw\.org/tvchannels/(?P<id>[^/?#]+)'
+ _TESTS = [{
+ 'url': 'https://tvw.org/tvchannels/air/',
+ 'info_dict': {
+ 'id': 'air',
+ 'ext': 'mp4',
+ 'title': r're:TVW Cable Channel Live Stream',
+ 'thumbnail': r're:https?://.+/.+\.(?:jpe?g|png)$',
+ 'live_status': 'is_live',
+ },
+ }, {
+ 'url': 'https://tvw.org/tvchannels/tvw2/',
+ 'info_dict': {
+ 'id': 'tvw2',
+ 'ext': 'mp4',
+ 'title': r're:TVW-2 Broadcast Channel',
+ 'thumbnail': r're:https?://.+/.+\.(?:jpe?g|png)$',
+ 'live_status': 'is_live',
+ },
+ }]
+
+ def _real_extract(self, url):
+ video_id = self._match_id(url)
+ webpage = self._download_webpage(url, video_id)
+
+ m3u8_url = traverse_obj(webpage, (
+ {find_element(id='invintus-persistent-stream-frame', html=True)}, {extract_attributes},
+ 'src', {parse_qs}, 'encoder', 0, {json.loads}, 'live247URI', {url_or_none}, {require('stream url')}))
+
+ return {
+ 'id': video_id,
+ 'formats': self._extract_m3u8_formats(m3u8_url, video_id, 'mp4', m3u8_id='hls', live=True),
+ 'title': remove_end(self._og_search_title(webpage, default=None), ' - TVW'),
+ 'thumbnail': self._og_search_thumbnail(webpage, default=None),
+ 'is_live': True,
+ }