summaryrefslogtreecommitdiffstats
path: root/yt_dlp/extractor
diff options
context:
space:
mode:
Diffstat (limited to 'yt_dlp/extractor')
-rw-r--r--yt_dlp/extractor/common.py2
-rw-r--r--yt_dlp/extractor/peertube.py8
-rw-r--r--yt_dlp/extractor/piksel.py19
-rw-r--r--yt_dlp/extractor/tiktok.py8
4 files changed, 25 insertions, 12 deletions
diff --git a/yt_dlp/extractor/common.py b/yt_dlp/extractor/common.py
index b99b7e5..1d2c443 100644
--- a/yt_dlp/extractor/common.py
+++ b/yt_dlp/extractor/common.py
@@ -2451,7 +2451,7 @@ class InfoExtractor:
})
continue
- src_url = src if src.startswith('http') else urllib.parse.urljoin(base, src)
+ src_url = src if src.startswith('http') else urllib.parse.urljoin(f'{base}/', src)
src_url = src_url.strip()
if proto == 'm3u8' or src_ext == 'm3u8':
diff --git a/yt_dlp/extractor/peertube.py b/yt_dlp/extractor/peertube.py
index b7919c0..fb4d025 100644
--- a/yt_dlp/extractor/peertube.py
+++ b/yt_dlp/extractor/peertube.py
@@ -1470,11 +1470,15 @@ class PeerTubeIE(InfoExtractor):
title = video['name']
- formats = []
+ formats, is_live = [], False
files = video.get('files') or []
for playlist in (video.get('streamingPlaylists') or []):
if not isinstance(playlist, dict):
continue
+ if playlist_url := url_or_none(playlist.get('playlistUrl')):
+ is_live = True
+ formats.extend(self._extract_m3u8_formats(
+ playlist_url, video_id, fatal=False, live=True))
playlist_files = playlist.get('files')
if not (playlist_files and isinstance(playlist_files, list)):
continue
@@ -1498,6 +1502,7 @@ class PeerTubeIE(InfoExtractor):
f['vcodec'] = 'none'
else:
f['fps'] = int_or_none(file_.get('fps'))
+ is_live = False
formats.append(f)
description = video.get('description')
@@ -1555,6 +1560,7 @@ class PeerTubeIE(InfoExtractor):
'categories': categories,
'formats': formats,
'subtitles': subtitles,
+ 'is_live': is_live,
'webpage_url': webpage_url,
}
diff --git a/yt_dlp/extractor/piksel.py b/yt_dlp/extractor/piksel.py
index 8870d7b..02ae2fe 100644
--- a/yt_dlp/extractor/piksel.py
+++ b/yt_dlp/extractor/piksel.py
@@ -25,29 +25,31 @@ class PikselIE(InfoExtractor):
)|
(?:api|player)\.multicastmedia|
(?:api-ovp|player)\.piksel
- )\.com|
+ )\.(?:com|tech)|
(?:
mz-edge\.stream\.co|
movie-s\.nhk\.or
)\.jp|
vidego\.baltimorecity\.gov
)/v/(?:refid/(?P<refid>[^/]+)/prefid/)?(?P<id>[\w-]+)'''
- _EMBED_REGEX = [r'<iframe[^>]+src=["\'](?P<url>(?:https?:)?//player\.piksel\.com/v/[a-z0-9]+)']
+ _EMBED_REGEX = [r'<iframe[^>]+src=["\'](?P<url>(?:https?:)?//player\.piksel\.(?:com|tech)/v/[a-z0-9]+)']
_TESTS = [
{
- 'url': 'http://player.piksel.com/v/ums2867l',
+ 'url': 'http://player.piksel.tech/v/ums2867l',
'md5': '34e34c8d89dc2559976a6079db531e85',
'info_dict': {
'id': 'ums2867l',
'ext': 'mp4',
'title': 'GX-005 with Caption',
'timestamp': 1481335659,
- 'upload_date': '20161210'
+ 'upload_date': '20161210',
+ 'description': '',
+ 'thumbnail': 'https://thumbs.piksel.tech/thumbs/aid/t1488331553/3238987.jpg?w=640&h=480',
}
},
{
# Original source: http://www.uscourts.gov/cameras-courts/state-washington-vs-donald-j-trump-et-al
- 'url': 'https://player.piksel.com/v/v80kqp41',
+ 'url': 'https://player.piksel.tech/v/v80kqp41',
'md5': '753ddcd8cc8e4fa2dda4b7be0e77744d',
'info_dict': {
'id': 'v80kqp41',
@@ -55,7 +57,8 @@ class PikselIE(InfoExtractor):
'title': 'WAW- State of Washington vs. Donald J. Trump, et al',
'description': 'State of Washington vs. Donald J. Trump, et al, Case Number 17-CV-00141-JLR, TRO Hearing, Civil Rights Case, 02/3/2017, 1:00 PM (PST), Seattle Federal Courthouse, Seattle, WA, Judge James L. Robart presiding.',
'timestamp': 1486171129,
- 'upload_date': '20170204'
+ 'upload_date': '20170204',
+ 'thumbnail': 'https://thumbs.piksel.tech/thumbs/aid/t1495569155/3279887.jpg?w=640&h=360',
}
},
{
@@ -65,7 +68,7 @@ class PikselIE(InfoExtractor):
}
]
- def _call_api(self, app_token, resource, display_id, query, host='https://player.piksel.com', fatal=True):
+ def _call_api(self, app_token, resource, display_id, query, host='https://player.piksel.tech', fatal=True):
url = urljoin(host, f'/ws/ws_{resource}/api/{app_token}/mode/json/apiv/5')
response = traverse_obj(
self._download_json(url, display_id, query=query, fatal=fatal), ('response', {dict})) or {}
@@ -146,7 +149,7 @@ class PikselIE(InfoExtractor):
smil_url = dict_get(video_data, ['httpSmil', 'hdSmil', 'rtmpSmil'])
if smil_url:
- transform_source = None
+ transform_source = lambda x: x.replace('src="/', 'src="')
if ref_id == 'nhkworld':
# TODO: figure out if this is something to be fixed in urljoin,
# _parse_smil_formats or keep it here
diff --git a/yt_dlp/extractor/tiktok.py b/yt_dlp/extractor/tiktok.py
index ab8efc1..7bcfded 100644
--- a/yt_dlp/extractor/tiktok.py
+++ b/yt_dlp/extractor/tiktok.py
@@ -940,6 +940,7 @@ class TikTokUserIE(TikTokBaseIE):
def _entries(self, sec_uid, user_name):
display_id = user_name or sec_uid
+ seen_ids = set()
cursor = int(time.time() * 1E3)
for page in itertools.count(1):
@@ -949,6 +950,9 @@ class TikTokUserIE(TikTokBaseIE):
for video in traverse_obj(response, ('itemList', lambda _, v: v['id'])):
video_id = video['id']
+ if video_id in seen_ids:
+ continue
+ seen_ids.add(video_id)
webpage_url = self._create_url(display_id, video_id)
yield self.url_result(
webpage_url, TikTokIE,
@@ -956,8 +960,8 @@ class TikTokUserIE(TikTokBaseIE):
old_cursor = cursor
cursor = traverse_obj(
- response, ('itemList', -1, 'createTime', {functools.partial(int_or_none, invscale=1E3)}))
- if not cursor:
+ response, ('itemList', -1, 'createTime', {lambda x: int(x * 1E3)}))
+ if not cursor or old_cursor == cursor:
# User may not have posted within this ~1 week lookback, so manually adjust cursor
cursor = old_cursor - 7 * 86_400_000
# In case 'hasMorePrevious' is wrong, break if we have gone back before TikTok existed