We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
plugins.picarto: Could not find server netloc
### Checklist

- [X] This is a plugin issue and not a different kind of issue
- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)
- [X] [I have checked the list of open and recently closed plugin issues](https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+issue%22)
- [X] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)

### Streamlink version

Latest stable release

### Description

Plugin suddenly stopped working today. 
Checked on multiple streams as well as on Linux and Windows 10 with the same result.
I can still manually watch the streams on VLC with "https://1-edge1-eu-west.picarto.tv/stream/hls/golive%2bUSERNAME/index.m3u8" as URL source.

### Debug log

```text
C:\PICARTO>streamlink https://picarto.tv/USERNAME best -l debug
[cli][debug] OS:         Windows 10
[cli][debug] Python:     3.10.5
[cli][debug] Streamlink: 4.2.0
[cli][debug] Dependencies:
[cli][debug]  isodate: 0.6.1
[cli][debug]  lxml: 4.9.1
[cli][debug]  pycountry: 22.3.5
[cli][debug]  pycryptodome: 3.15.0
[cli][debug]  PySocks: 1.7.1
[cli][debug]  requests: 2.28.1
[cli][debug]  websocket-client: 1.3.3
[cli][debug] Arguments:
[cli][debug]  url=https://picarto.tv/USERNAME
[cli][debug]  stream=['best']
[cli][debug]  --loglevel=debug
[cli][debug]  --ffmpeg-ffmpeg=C:\Program Files\Streamlink\ffmpeg\ffmpeg.exe
[cli][info] Found matching plugin picarto for URL https://picarto.tv/USERNAME
[plugins.picarto][debug] Type=Live
[plugins.picarto][error] Could not find server netloc
error: No playable streams found on this URL: https://picarto.tv/USERNAME
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/streamlink/plugins/picarto.py`
Content:
```
1 """
2 $description Global live streaming and video hosting platform for the creative community.
3 $url picarto.tv
4 $type live, vod
5 """
6 
7 import logging
8 import re
9 from urllib.parse import urlparse
10 
11 from streamlink.plugin import Plugin, pluginmatcher
12 from streamlink.plugin.api import validate
13 from streamlink.stream.hls import HLSStream
14 
15 log = logging.getLogger(__name__)
16 
17 
18 @pluginmatcher(re.compile(r"""
19     https?://(?:www\.)?picarto\.tv/
20     (?:
21         streampopout/(?P<po_user>[^/]+)/public
22     |
23         videopopout/(?P<po_vod_id>\d+)
24     |
25         [^/]+/videos/(?P<vod_id>\d+)
26     |
27         (?P<user>[^/?&]+)
28     )$
29 """, re.VERBOSE))
30 class Picarto(Plugin):
31     API_URL_LIVE = "https://ptvintern.picarto.tv/api/channel/detail/{username}"
32     API_URL_VOD = "https://ptvintern.picarto.tv/ptvapi"
33     HLS_URL = "https://{netloc}/stream/hls/{file_name}/index.m3u8"
34 
35     def get_live(self, username):
36         netloc = self.session.http.get(self.url, schema=validate.Schema(
37             validate.parse_html(),
38             validate.xml_xpath_string(".//script[contains(@src,'/stream/player.js')][1]/@src"),
39             validate.any(None, validate.transform(lambda src: urlparse(src).netloc))
40         ))
41         if not netloc:
42             log.error("Could not find server netloc")
43             return
44 
45         channel, multistreams = self.session.http.get(self.API_URL_LIVE.format(username=username), schema=validate.Schema(
46             validate.parse_json(),
47             {
48                 "channel": validate.any(None, {
49                     "stream_name": str,
50                     "title": str,
51                     "online": bool,
52                     "private": bool,
53                     "categories": [{"label": str}],
54                 }),
55                 "getMultiStreams": validate.any(None, {
56                     "multistream": bool,
57                     "streams": [{
58                         "name": str,
59                         "online": bool,
60                     }],
61                 }),
62             },
63             validate.union_get("channel", "getMultiStreams")
64         ))
65         if not channel or not multistreams:
66             log.debug("Missing channel or streaming data")
67             return
68 
69         log.trace(f"netloc={netloc!r}")
70         log.trace(f"channel={channel!r}")
71         log.trace(f"multistreams={multistreams!r}")
72 
73         if not channel["online"]:
74             log.error("User is not online")
75             return
76 
77         if channel["private"]:
78             log.info("This is a private stream")
79             return
80 
81         self.author = username
82         self.category = channel["categories"][0]["label"]
83         self.title = channel["title"]
84 
85         hls_url = self.HLS_URL.format(
86             netloc=netloc,
87             file_name=channel["stream_name"]
88         )
89 
90         return HLSStream.parse_variant_playlist(self.session, hls_url)
91 
92     def get_vod(self, vod_id):
93         data = {
94             'query': (
95                 'query ($videoId: ID!) {\n'
96                 '  video(id: $videoId) {\n'
97                 '    id\n'
98                 '    title\n'
99                 '    file_name\n'
100                 '    video_recording_image_url\n'
101                 '    channel {\n'
102                 '      name\n'
103                 '      }'
104                 '  }\n'
105                 '}\n'
106             ),
107             'variables': {'videoId': vod_id},
108         }
109         vod_data = self.session.http.post(self.API_URL_VOD, json=data, schema=validate.Schema(
110             validate.parse_json(),
111             {"data": {
112                 "video": validate.any(None, {
113                     "id": str,
114                     "title": str,
115                     "file_name": str,
116                     "video_recording_image_url": str,
117                     "channel": {"name": str},
118                 }),
119             }},
120             validate.get(("data", "video"))
121         ))
122 
123         if not vod_data:
124             log.debug("Missing video data")
125             return
126 
127         log.trace(f"vod_data={vod_data!r}")
128 
129         self.author = vod_data["channel"]["name"]
130         self.category = "VOD"
131         self.title = vod_data["title"]
132 
133         netloc = urlparse(vod_data["video_recording_image_url"]).netloc
134         hls_url = self.HLS_URL.format(
135             netloc=netloc,
136             file_name=vod_data["file_name"]
137         )
138 
139         return HLSStream.parse_variant_playlist(self.session, hls_url)
140 
141     def _get_streams(self):
142         m = self.match.groupdict()
143 
144         if m['po_vod_id'] or m['vod_id']:
145             log.debug('Type=VOD')
146             return self.get_vod(m['po_vod_id'] or m['vod_id'])
147         elif m['po_user'] or m['user']:
148             log.debug('Type=Live')
149             return self.get_live(m['po_user'] or m['user'])
150 
151 
152 __plugin__ = Picarto
153
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/streamlink/plugins/picarto.py b/src/streamlink/plugins/picarto.py
--- a/src/streamlink/plugins/picarto.py
+++ b/src/streamlink/plugins/picarto.py
@@ -33,40 +33,37 @@
     HLS_URL = "https://{netloc}/stream/hls/{file_name}/index.m3u8"
 
     def get_live(self, username):
-        netloc = self.session.http.get(self.url, schema=validate.Schema(
-            validate.parse_html(),
-            validate.xml_xpath_string(".//script[contains(@src,'/stream/player.js')][1]/@src"),
-            validate.any(None, validate.transform(lambda src: urlparse(src).netloc))
-        ))
-        if not netloc:
-            log.error("Could not find server netloc")
-            return
-
-        channel, multistreams = self.session.http.get(self.API_URL_LIVE.format(username=username), schema=validate.Schema(
-            validate.parse_json(),
-            {
-                "channel": validate.any(None, {
-                    "stream_name": str,
-                    "title": str,
-                    "online": bool,
-                    "private": bool,
-                    "categories": [{"label": str}],
-                }),
-                "getMultiStreams": validate.any(None, {
-                    "multistream": bool,
-                    "streams": [{
-                        "name": str,
+        channel, multistreams, loadbalancer = self.session.http.get(
+            self.API_URL_LIVE.format(username=username),
+            schema=validate.Schema(
+                validate.parse_json(),
+                {
+                    "channel": validate.any(None, {
+                        "stream_name": str,
+                        "title": str,
                         "online": bool,
-                    }],
-                }),
-            },
-            validate.union_get("channel", "getMultiStreams")
-        ))
-        if not channel or not multistreams:
+                        "private": bool,
+                        "categories": [{"label": str}],
+                    }),
+                    "getMultiStreams": validate.any(None, {
+                        "multistream": bool,
+                        "streams": [{
+                            "name": str,
+                            "online": bool,
+                        }],
+                    }),
+                    "getLoadBalancerUrl": validate.any(None, {
+                        "url": validate.any(None, validate.transform(lambda url: urlparse(url).netloc))
+                    })
+                },
+                validate.union_get("channel", "getMultiStreams", "getLoadBalancerUrl"),
+            )
+        )
+        if not channel or not multistreams or not loadbalancer:
             log.debug("Missing channel or streaming data")
             return
 
-        log.trace(f"netloc={netloc!r}")
+        log.trace(f"loadbalancer={loadbalancer!r}")
         log.trace(f"channel={channel!r}")
         log.trace(f"multistreams={multistreams!r}")
 
@@ -83,7 +80,7 @@
         self.title = channel["title"]
 
         hls_url = self.HLS_URL.format(
-            netloc=netloc,
+            netloc=loadbalancer["url"],
             file_name=channel["stream_name"]
         )
 
@@ -110,7 +107,7 @@
             validate.parse_json(),
             {"data": {
                 "video": validate.any(None, {
-                    "id": str,
+                    "id": int,
                     "title": str,
                     "file_name": str,
                     "video_recording_image_url": str,

{"golden_diff": "diff --git a/src/streamlink/plugins/picarto.py b/src/streamlink/plugins/picarto.py\n--- a/src/streamlink/plugins/picarto.py\n+++ b/src/streamlink/plugins/picarto.py\n@@ -33,40 +33,37 @@\n     HLS_URL = \"https://{netloc}/stream/hls/{file_name}/index.m3u8\"\n \n     def get_live(self, username):\n-        netloc = self.session.http.get(self.url, schema=validate.Schema(\n-            validate.parse_html(),\n-            validate.xml_xpath_string(\".//script[contains(@src,'/stream/player.js')][1]/@src\"),\n-            validate.any(None, validate.transform(lambda src: urlparse(src).netloc))\n-        ))\n-        if not netloc:\n-            log.error(\"Could not find server netloc\")\n-            return\n-\n-        channel, multistreams = self.session.http.get(self.API_URL_LIVE.format(username=username), schema=validate.Schema(\n-            validate.parse_json(),\n-            {\n-                \"channel\": validate.any(None, {\n-                    \"stream_name\": str,\n-                    \"title\": str,\n-                    \"online\": bool,\n-                    \"private\": bool,\n-                    \"categories\": [{\"label\": str}],\n-                }),\n-                \"getMultiStreams\": validate.any(None, {\n-                    \"multistream\": bool,\n-                    \"streams\": [{\n-                        \"name\": str,\n+        channel, multistreams, loadbalancer = self.session.http.get(\n+            self.API_URL_LIVE.format(username=username),\n+            schema=validate.Schema(\n+                validate.parse_json(),\n+                {\n+                    \"channel\": validate.any(None, {\n+                        \"stream_name\": str,\n+                        \"title\": str,\n                         \"online\": bool,\n-                    }],\n-                }),\n-            },\n-            validate.union_get(\"channel\", \"getMultiStreams\")\n-        ))\n-        if not channel or not multistreams:\n+                        \"private\": bool,\n+                        \"categories\": [{\"label\": str}],\n+                    }),\n+                    \"getMultiStreams\": validate.any(None, {\n+                        \"multistream\": bool,\n+                        \"streams\": [{\n+                            \"name\": str,\n+                            \"online\": bool,\n+                        }],\n+                    }),\n+                    \"getLoadBalancerUrl\": validate.any(None, {\n+                        \"url\": validate.any(None, validate.transform(lambda url: urlparse(url).netloc))\n+                    })\n+                },\n+                validate.union_get(\"channel\", \"getMultiStreams\", \"getLoadBalancerUrl\"),\n+            )\n+        )\n+        if not channel or not multistreams or not loadbalancer:\n             log.debug(\"Missing channel or streaming data\")\n             return\n \n-        log.trace(f\"netloc={netloc!r}\")\n+        log.trace(f\"loadbalancer={loadbalancer!r}\")\n         log.trace(f\"channel={channel!r}\")\n         log.trace(f\"multistreams={multistreams!r}\")\n \n@@ -83,7 +80,7 @@\n         self.title = channel[\"title\"]\n \n         hls_url = self.HLS_URL.format(\n-            netloc=netloc,\n+            netloc=loadbalancer[\"url\"],\n             file_name=channel[\"stream_name\"]\n         )\n \n@@ -110,7 +107,7 @@\n             validate.parse_json(),\n             {\"data\": {\n                 \"video\": validate.any(None, {\n-                    \"id\": str,\n+                    \"id\": int,\n                     \"title\": str,\n                     \"file_name\": str,\n                     \"video_recording_image_url\": str,\n", "issue": "plugins.picarto: Could not find server netloc\n### Checklist\n\n- [X] This is a plugin issue and not a different kind of issue\n- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)\n- [X] [I have checked the list of open and recently closed plugin issues](https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+issue%22)\n- [X] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)\n\n### Streamlink version\n\nLatest stable release\n\n### Description\n\nPlugin suddenly stopped working today. \r\nChecked on multiple streams as well as on Linux and Windows 10 with the same result.\r\nI can still manually watch the streams on VLC with \"https://1-edge1-eu-west.picarto.tv/stream/hls/golive%2bUSERNAME/index.m3u8\" as URL source.\n\n### Debug log\n\n```text\nC:\\PICARTO>streamlink https://picarto.tv/USERNAME best -l debug\r\n[cli][debug] OS:         Windows 10\r\n[cli][debug] Python:     3.10.5\r\n[cli][debug] Streamlink: 4.2.0\r\n[cli][debug] Dependencies:\r\n[cli][debug]  isodate: 0.6.1\r\n[cli][debug]  lxml: 4.9.1\r\n[cli][debug]  pycountry: 22.3.5\r\n[cli][debug]  pycryptodome: 3.15.0\r\n[cli][debug]  PySocks: 1.7.1\r\n[cli][debug]  requests: 2.28.1\r\n[cli][debug]  websocket-client: 1.3.3\r\n[cli][debug] Arguments:\r\n[cli][debug]  url=https://picarto.tv/USERNAME\r\n[cli][debug]  stream=['best']\r\n[cli][debug]  --loglevel=debug\r\n[cli][debug]  --ffmpeg-ffmpeg=C:\\Program Files\\Streamlink\\ffmpeg\\ffmpeg.exe\r\n[cli][info] Found matching plugin picarto for URL https://picarto.tv/USERNAME\r\n[plugins.picarto][debug] Type=Live\r\n[plugins.picarto][error] Could not find server netloc\r\nerror: No playable streams found on this URL: https://picarto.tv/USERNAME\n```\n\n", "before_files": [{"content": "\"\"\"\n$description Global live streaming and video hosting platform for the creative community.\n$url picarto.tv\n$type live, vod\n\"\"\"\n\nimport logging\nimport re\nfrom urllib.parse import urlparse\n\nfrom streamlink.plugin import Plugin, pluginmatcher\nfrom streamlink.plugin.api import validate\nfrom streamlink.stream.hls import HLSStream\n\nlog = logging.getLogger(__name__)\n\n\n@pluginmatcher(re.compile(r\"\"\"\n    https?://(?:www\\.)?picarto\\.tv/\n    (?:\n        streampopout/(?P<po_user>[^/]+)/public\n    |\n        videopopout/(?P<po_vod_id>\\d+)\n    |\n        [^/]+/videos/(?P<vod_id>\\d+)\n    |\n        (?P<user>[^/?&]+)\n    )$\n\"\"\", re.VERBOSE))\nclass Picarto(Plugin):\n    API_URL_LIVE = \"https://ptvintern.picarto.tv/api/channel/detail/{username}\"\n    API_URL_VOD = \"https://ptvintern.picarto.tv/ptvapi\"\n    HLS_URL = \"https://{netloc}/stream/hls/{file_name}/index.m3u8\"\n\n    def get_live(self, username):\n        netloc = self.session.http.get(self.url, schema=validate.Schema(\n            validate.parse_html(),\n            validate.xml_xpath_string(\".//script[contains(@src,'/stream/player.js')][1]/@src\"),\n            validate.any(None, validate.transform(lambda src: urlparse(src).netloc))\n        ))\n        if not netloc:\n            log.error(\"Could not find server netloc\")\n            return\n\n        channel, multistreams = self.session.http.get(self.API_URL_LIVE.format(username=username), schema=validate.Schema(\n            validate.parse_json(),\n            {\n                \"channel\": validate.any(None, {\n                    \"stream_name\": str,\n                    \"title\": str,\n                    \"online\": bool,\n                    \"private\": bool,\n                    \"categories\": [{\"label\": str}],\n                }),\n                \"getMultiStreams\": validate.any(None, {\n                    \"multistream\": bool,\n                    \"streams\": [{\n                        \"name\": str,\n                        \"online\": bool,\n                    }],\n                }),\n            },\n            validate.union_get(\"channel\", \"getMultiStreams\")\n        ))\n        if not channel or not multistreams:\n            log.debug(\"Missing channel or streaming data\")\n            return\n\n        log.trace(f\"netloc={netloc!r}\")\n        log.trace(f\"channel={channel!r}\")\n        log.trace(f\"multistreams={multistreams!r}\")\n\n        if not channel[\"online\"]:\n            log.error(\"User is not online\")\n            return\n\n        if channel[\"private\"]:\n            log.info(\"This is a private stream\")\n            return\n\n        self.author = username\n        self.category = channel[\"categories\"][0][\"label\"]\n        self.title = channel[\"title\"]\n\n        hls_url = self.HLS_URL.format(\n            netloc=netloc,\n            file_name=channel[\"stream_name\"]\n        )\n\n        return HLSStream.parse_variant_playlist(self.session, hls_url)\n\n    def get_vod(self, vod_id):\n        data = {\n            'query': (\n                'query ($videoId: ID!) {\\n'\n                '  video(id: $videoId) {\\n'\n                '    id\\n'\n                '    title\\n'\n                '    file_name\\n'\n                '    video_recording_image_url\\n'\n                '    channel {\\n'\n                '      name\\n'\n                '      }'\n                '  }\\n'\n                '}\\n'\n            ),\n            'variables': {'videoId': vod_id},\n        }\n        vod_data = self.session.http.post(self.API_URL_VOD, json=data, schema=validate.Schema(\n            validate.parse_json(),\n            {\"data\": {\n                \"video\": validate.any(None, {\n                    \"id\": str,\n                    \"title\": str,\n                    \"file_name\": str,\n                    \"video_recording_image_url\": str,\n                    \"channel\": {\"name\": str},\n                }),\n            }},\n            validate.get((\"data\", \"video\"))\n        ))\n\n        if not vod_data:\n            log.debug(\"Missing video data\")\n            return\n\n        log.trace(f\"vod_data={vod_data!r}\")\n\n        self.author = vod_data[\"channel\"][\"name\"]\n        self.category = \"VOD\"\n        self.title = vod_data[\"title\"]\n\n        netloc = urlparse(vod_data[\"video_recording_image_url\"]).netloc\n        hls_url = self.HLS_URL.format(\n            netloc=netloc,\n            file_name=vod_data[\"file_name\"]\n        )\n\n        return HLSStream.parse_variant_playlist(self.session, hls_url)\n\n    def _get_streams(self):\n        m = self.match.groupdict()\n\n        if m['po_vod_id'] or m['vod_id']:\n            log.debug('Type=VOD')\n            return self.get_vod(m['po_vod_id'] or m['vod_id'])\n        elif m['po_user'] or m['user']:\n            log.debug('Type=Live')\n            return self.get_live(m['po_user'] or m['user'])\n\n\n__plugin__ = Picarto\n", "path": "src/streamlink/plugins/picarto.py"}], "after_files": [{"content": "\"\"\"\n$description Global live streaming and video hosting platform for the creative community.\n$url picarto.tv\n$type live, vod\n\"\"\"\n\nimport logging\nimport re\nfrom urllib.parse import urlparse\n\nfrom streamlink.plugin import Plugin, pluginmatcher\nfrom streamlink.plugin.api import validate\nfrom streamlink.stream.hls import HLSStream\n\nlog = logging.getLogger(__name__)\n\n\n@pluginmatcher(re.compile(r\"\"\"\n    https?://(?:www\\.)?picarto\\.tv/\n    (?:\n        streampopout/(?P<po_user>[^/]+)/public\n    |\n        videopopout/(?P<po_vod_id>\\d+)\n    |\n        [^/]+/videos/(?P<vod_id>\\d+)\n    |\n        (?P<user>[^/?&]+)\n    )$\n\"\"\", re.VERBOSE))\nclass Picarto(Plugin):\n    API_URL_LIVE = \"https://ptvintern.picarto.tv/api/channel/detail/{username}\"\n    API_URL_VOD = \"https://ptvintern.picarto.tv/ptvapi\"\n    HLS_URL = \"https://{netloc}/stream/hls/{file_name}/index.m3u8\"\n\n    def get_live(self, username):\n        channel, multistreams, loadbalancer = self.session.http.get(\n            self.API_URL_LIVE.format(username=username),\n            schema=validate.Schema(\n                validate.parse_json(),\n                {\n                    \"channel\": validate.any(None, {\n                        \"stream_name\": str,\n                        \"title\": str,\n                        \"online\": bool,\n                        \"private\": bool,\n                        \"categories\": [{\"label\": str}],\n                    }),\n                    \"getMultiStreams\": validate.any(None, {\n                        \"multistream\": bool,\n                        \"streams\": [{\n                            \"name\": str,\n                            \"online\": bool,\n                        }],\n                    }),\n                    \"getLoadBalancerUrl\": validate.any(None, {\n                        \"url\": validate.any(None, validate.transform(lambda url: urlparse(url).netloc))\n                    })\n                },\n                validate.union_get(\"channel\", \"getMultiStreams\", \"getLoadBalancerUrl\"),\n            )\n        )\n        if not channel or not multistreams or not loadbalancer:\n            log.debug(\"Missing channel or streaming data\")\n            return\n\n        log.trace(f\"loadbalancer={loadbalancer!r}\")\n        log.trace(f\"channel={channel!r}\")\n        log.trace(f\"multistreams={multistreams!r}\")\n\n        if not channel[\"online\"]:\n            log.error(\"User is not online\")\n            return\n\n        if channel[\"private\"]:\n            log.info(\"This is a private stream\")\n            return\n\n        self.author = username\n        self.category = channel[\"categories\"][0][\"label\"]\n        self.title = channel[\"title\"]\n\n        hls_url = self.HLS_URL.format(\n            netloc=loadbalancer[\"url\"],\n            file_name=channel[\"stream_name\"]\n        )\n\n        return HLSStream.parse_variant_playlist(self.session, hls_url)\n\n    def get_vod(self, vod_id):\n        data = {\n            'query': (\n                'query ($videoId: ID!) {\\n'\n                '  video(id: $videoId) {\\n'\n                '    id\\n'\n                '    title\\n'\n                '    file_name\\n'\n                '    video_recording_image_url\\n'\n                '    channel {\\n'\n                '      name\\n'\n                '      }'\n                '  }\\n'\n                '}\\n'\n            ),\n            'variables': {'videoId': vod_id},\n        }\n        vod_data = self.session.http.post(self.API_URL_VOD, json=data, schema=validate.Schema(\n            validate.parse_json(),\n            {\"data\": {\n                \"video\": validate.any(None, {\n                    \"id\": int,\n                    \"title\": str,\n                    \"file_name\": str,\n                    \"video_recording_image_url\": str,\n                    \"channel\": {\"name\": str},\n                }),\n            }},\n            validate.get((\"data\", \"video\"))\n        ))\n\n        if not vod_data:\n            log.debug(\"Missing video data\")\n            return\n\n        log.trace(f\"vod_data={vod_data!r}\")\n\n        self.author = vod_data[\"channel\"][\"name\"]\n        self.category = \"VOD\"\n        self.title = vod_data[\"title\"]\n\n        netloc = urlparse(vod_data[\"video_recording_image_url\"]).netloc\n        hls_url = self.HLS_URL.format(\n            netloc=netloc,\n            file_name=vod_data[\"file_name\"]\n        )\n\n        return HLSStream.parse_variant_playlist(self.session, hls_url)\n\n    def _get_streams(self):\n        m = self.match.groupdict()\n\n        if m['po_vod_id'] or m['vod_id']:\n            log.debug('Type=VOD')\n            return self.get_vod(m['po_vod_id'] or m['vod_id'])\n        elif m['po_user'] or m['user']:\n            log.debug('Type=Live')\n            return self.get_live(m['po_user'] or m['user'])\n\n\n__plugin__ = Picarto\n", "path": "src/streamlink/plugins/picarto.py"}]}