forked from streamlink/streamlink
/
livestream.py
122 lines (110 loc) · 4.4 KB
/
livestream.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"""
$description Global live-streaming and video on-demand hosting platform.
$url livestream.com
$type live
"""
import logging
import re
from operator import itemgetter
from streamlink.plugin import Plugin, pluginmatcher
from streamlink.plugin.api import validate
from streamlink.stream.hls import HLSStream
log = logging.getLogger(__name__)
@pluginmatcher(re.compile(
r"""
https?://(?P<subdomain>api\.new\.|www\.)?livestream\.com
/accounts/(?P<account>\d+)
(?:
/events/(?P<event>\d+)
|
/[^/]+
)?
(?:/videos/(?P<video>\d+))?
""",
re.VERBOSE,
))
class Livestream(Plugin):
URL_API_EVENTS = "https://api.new.livestream.com/accounts/{account}/events"
URL_API_EVENTS_EVENT = "https://api.new.livestream.com/accounts/{account}/events/{event}"
URL_API_VIDEO = "https://api.new.livestream.com/accounts/{account}/events/{event}/videos/{video}"
def _get_streams(self):
subdomain, account, event, video = itemgetter("subdomain", "account", "event", "video")(self.match.groupdict())
if event is None:
if video is None or subdomain == "api.new.":
event = self.session.http.get(
self.URL_API_EVENTS.format(account=account),
schema=validate.Schema(
validate.parse_json(),
{"data": [dict]},
validate.get(("data", 0)),
validate.none_or_all(
{"id": int},
validate.get("id"),
),
),
)
else:
event = self.session.http.get(
self.url,
schema=validate.Schema(
validate.parse_html(),
validate.xml_xpath_string(".//script[contains(text(), 'window.config = ')][1]/text()"),
validate.none_or_all(
re.compile(r"^window\.config\s*=\s*(\{.+});?\s*$"),
validate.none_or_all(
validate.get(1),
validate.parse_json(),
{"event": {"id": int}},
validate.get(("event", "id")),
),
),
),
)
if event is None:
log.error("Could not find event ID")
return
if video is None:
self.id, self.title, is_live, m3u8_url = self.session.http.get(
self.URL_API_EVENTS_EVENT.format(account=account, event=event),
schema=validate.Schema(
validate.parse_json(),
{
"stream_info": {
"broadcast_id": int,
validate.optional("stream_title"): validate.any(None, validate.text),
"is_live": bool,
"secure_m3u8_url": validate.url(path=validate.endswith(".m3u8")),
},
},
validate.get("stream_info"),
validate.union_get(
"broadcast_id",
"stream_title",
"is_live",
"secure_m3u8_url",
),
),
)
if not is_live:
log.error("The stream is not available")
return
else:
self.id, self.title, m3u8_url = self.session.http.get(
self.URL_API_VIDEO.format(account=account, event=event, video=video),
schema=validate.Schema(
validate.parse_json(),
{
"id": int,
validate.optional("description"): validate.any(None, validate.text),
"secure_m3u8_url": validate.url(path=validate.endswith(".m3u8")),
},
validate.union_get(
"id",
"description",
"secure_m3u8_url",
),
),
)
for s in HLSStream.parse_variant_playlist(self.session, m3u8_url).items():
yield s
__plugin__ = Livestream