Skip to content

Commit fd49f2c

Browse files
committed
plugins.vimeo: fix event and player URLs
1 parent 90fe9e4 commit fd49f2c

File tree

2 files changed

+62
-15
lines changed

2 files changed

+62
-15
lines changed

src/streamlink/plugins/vimeo.py

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import re
1313
from urllib.parse import urljoin, urlparse
1414

15+
from streamlink.exceptions import NoStreamsError
1516
from streamlink.plugin import Plugin, pluginmatcher
1617
from streamlink.plugin.api import validate
1718
from streamlink.stream.dash import DASHStream
@@ -26,7 +27,11 @@
2627

2728
@pluginmatcher(
2829
name="default",
29-
pattern=re.compile(r"https?://(?:www\.)?vimeo\.com/.+"),
30+
pattern=re.compile(r"https?://(?:www\.)?vimeo\.com/(?!event/).+"),
31+
)
32+
@pluginmatcher(
33+
name="event",
34+
pattern=re.compile(r"https?://(?:www\.)?vimeo\.com/event/(?P<event_id>\d+)"),
3035
)
3136
@pluginmatcher(
3237
name="player",
@@ -35,6 +40,7 @@
3540
class Vimeo(Plugin):
3641
VIEWER_URL = "https://vimeo.com/_next/viewer"
3742
OEMBED_URL = "https://vimeo.com/api/oembed.json"
43+
EVENT_EMBED_URL = "https://vimeo.com/event/{id}/embed"
3844

3945
@staticmethod
4046
def _schema_config(config):
@@ -110,15 +116,19 @@ def _get_dash_url(self, url):
110116

111117
def _query_player(self):
112118
return self.session.http.get(self.url, schema=validate.Schema(
113-
re.compile(r"playerConfig\s*=\s*({.+?})\s*var"),
119+
validate.parse_html(),
120+
validate.xml_xpath_string(".//script[contains(text(),'window.playerConfig')][1]/text()"),
114121
validate.none_or_all(
115-
validate.get(1),
116-
validate.parse_json(),
117-
validate.transform(self._schema_config),
122+
re.compile(r"^\s*window\.playerConfig\s*=\s*(?P<json>{.+?})\s*$"),
123+
validate.none_or_all(
124+
validate.get("json"),
125+
validate.parse_json(),
126+
validate.transform(self._schema_config),
127+
),
118128
),
119129
))
120130

121-
def _query_api(self):
131+
def _get_config_url(self):
122132
jwt, api_url = self.session.http.get(
123133
self.VIEWER_URL,
124134
schema=validate.Schema(
@@ -135,10 +145,13 @@ def _query_api(self):
135145
params={"url": self.url},
136146
schema=validate.Schema(
137147
validate.parse_json(),
138-
{"uri": str},
148+
{validate.optional("uri"): str},
139149
validate.get("uri"),
140150
),
141151
)
152+
if not uri:
153+
return
154+
142155
player_config_url = urljoin(update_scheme("https://", api_url), uri)
143156
config_url = self.session.http.get(
144157
player_config_url,
@@ -151,6 +164,38 @@ def _query_api(self):
151164
),
152165
)
153166

167+
return config_url
168+
169+
def _get_config_url_event(self):
170+
return self.session.http.get(
171+
self.EVENT_EMBED_URL.format(id=self.match["event_id"]),
172+
schema=validate.Schema(
173+
validate.parse_html(),
174+
validate.xml_xpath_string(".//script[contains(text(),'var htmlString')][1]/text()"),
175+
validate.none_or_all(
176+
re.compile(r"var htmlString\s*=\s*`(?P<html>.+?)`;", re.DOTALL),
177+
validate.none_or_all(
178+
validate.get("html"),
179+
validate.parse_html(),
180+
validate.xml_xpath_string(".//*[@data-config-url][1]/@data-config-url"),
181+
),
182+
),
183+
),
184+
)
185+
186+
def _query_api(self):
187+
config_url = ""
188+
if self.matches["event"]:
189+
log.debug("Getting event config_url")
190+
config_url = self._get_config_url_event()
191+
if not config_url:
192+
log.debug("Getting config_url")
193+
config_url = self._get_config_url()
194+
195+
if not config_url:
196+
log.error("The content is not available")
197+
raise NoStreamsError
198+
154199
return self.session.http.get(config_url, schema=validate.Schema(
155200
validate.parse_json(),
156201
validate.transform(self._schema_config),

tests/plugins/test_vimeo.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
class TestPluginCanHandleUrlVimeo(PluginCanHandleUrl):
66
__plugin__ = Vimeo
77

8-
should_match = [
9-
("default", "https://vimeo.com/783455878"),
10-
("default", "https://vimeo.com/channels/music/176894130"),
11-
("default", "https://vimeo.com/album/3706071/video/148903960"),
12-
("default", "https://vimeo.com/ondemand/worldoftomorrow3/467204924"),
13-
("default", "https://vimeo.com/ondemand/100footsurfingdays"),
14-
("default", "https://vimeo.com/771745400/840d05200c"),
15-
("player", "https://player.vimeo.com/video/176894130"),
8+
should_match_groups = [
9+
(("default", "https://vimeo.com/783455878"), {}),
10+
(("default", "https://vimeo.com/channels/music/176894130"), {}),
11+
(("default", "https://vimeo.com/ondemand/worldoftomorrow3/467204924"), {}),
12+
(("default", "https://vimeo.com/ondemand/100footsurfingdays"), {}),
13+
14+
(("player", "https://player.vimeo.com/video/176894130"), {}),
15+
16+
(("event", "https://vimeo.com/event/4154130"), {"event_id": "4154130"}),
17+
(("event", "https://vimeo.com/event/4154130/embed"), {"event_id": "4154130"}),
1618
]
1719

1820
should_not_match = [

0 commit comments

Comments
 (0)