From f1f27eb2abfe5cb2a7dd5521d25d9b4aa3375f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Wed, 12 Feb 2025 18:49:02 +0100 Subject: [PATCH] [vsco] support '/video/' URLs (#4295 #6973) requires yt-dlp/youtube-dl to handle m3u8 manifests --- docs/supportedsites.md | 2 +- gallery_dl/extractor/vsco.py | 38 ++++++++++++++++++++++++++++++------ test/results/vsco.py | 20 +++++++++++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/docs/supportedsites.md b/docs/supportedsites.md index 170e8483..2b98722f 100644 --- a/docs/supportedsites.md +++ b/docs/supportedsites.md @@ -1018,7 +1018,7 @@ Consider all listed sites to potentially be NSFW. VSCO https://vsco.co/ - Avatars, Collections, Galleries, individual Images, Spaces, User Profiles + Avatars, Collections, Galleries, individual Images, Spaces, User Profiles, Videos diff --git a/gallery_dl/extractor/vsco.py b/gallery_dl/extractor/vsco.py index 1c0c1720..b3ce99db 100644 --- a/gallery_dl/extractor/vsco.py +++ b/gallery_dl/extractor/vsco.py @@ -38,7 +38,9 @@ class VscoExtractor(Extractor): if img["is_video"]: if not videos: continue - url = "https://" + img["video_url"] + url = img["video_url"] + if not url.startswith("ytdl:"): + url = "https://" + url else: base = img["responsive_url"].partition("/")[2] cdn, _, path = base.partition("/") @@ -63,6 +65,9 @@ class VscoExtractor(Extractor): "height": img["height"], "description": img.get("description") or "", }) + if data["extension"] == "m3u8": + data["_ytdl_manifest"] = "hls" + data["extension"] = "mp4" yield Message.Url, url, data def images(self): @@ -294,12 +299,33 @@ class VscoImageExtractor(VscoExtractor): pattern = USER_PATTERN + r"/media/([0-9a-fA-F]+)" example = "https://vsco.co/USER/media/0123456789abcdef" - def __init__(self, match): - VscoExtractor.__init__(self, match) - self.media_id = match.group(2) - def images(self): - url = "{}/{}/media/{}".format(self.root, self.user, self.media_id) + url = "{}/{}/media/{}".format(self.root, self.user, self.groups[1]) data = self._extract_preload_state(url) media = data["medias"]["byId"].popitem()[1]["media"] return (self._transform_media(media),) + + +class VscoVideoExtractor(VscoExtractor): + """Extractor for vsco.co videos links""" + subcategory = "video" + pattern = USER_PATTERN + r"/video/([^/?#]+)" + example = "https://vsco.co/USER/video/012345678-9abc-def0" + + def images(self): + url = "{}/{}/video/{}".format(self.root, self.user, self.groups[1]) + data = self._extract_preload_state(url) + media = data["medias"]["byId"].popitem()[1]["media"] + + return ({ + "_id" : media["id"], + "is_video" : True, + "grid_name" : "", + "upload_date" : media["createdDate"], + "responsive_url": media["posterUrl"], + "video_url" : "ytdl:" + media.get("playbackUrl"), + "image_meta" : None, + "width" : media["width"], + "height" : media["height"], + "description" : media["description"], + },) diff --git a/test/results/vsco.py b/test/results/vsco.py index 6ea89ac6..60f82918 100644 --- a/test/results/vsco.py +++ b/test/results/vsco.py @@ -108,4 +108,24 @@ __tests__ = ( "video": True, }, +{ + "#url" : "https://vsco.co/shavonec/video/c5eb34bb-dd13-4d7a-a09c-2a7cd719c9fa", + "#category": ("", "vsco", "video"), + "#class" : vsco.VscoVideoExtractor, + "#pattern" : r"ytdl:https://stream\.mux\.com/3o01XbjqTI4rkeRwPzR17H9i7VSFdWX1h\.m3u8\?token=ey.+", + + "date" : "dt:2020-02-04 15:11:52", + "description": "Big news: 🎥 YOU CAN NOW POST VIDEOS TO VSCO ⚡️⚡️💪🏾. ⁣\n⁣\n🔗BTS from my #FashionIsActivism panel with the California African American Arts museum ✊🏾", + "extension" : "mp4", + "filename" : "3o01XbjqTI4rkeRwPzR17H9i7VSFdWX1h", + "grid" : "", + "id" : "c5eb34bb-dd13-4d7a-a09c-2a7cd719c9fa", + "meta" : {}, + "tags" : [], + "user" : "shavonec", + "video" : True, + "width" : 624, + "height" : 1232, +}, + )