We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
picarto updated streamlink no longer works
Hey guys picarto no longer works because they said they updated the player so html5 can be default soon.
when you run  the program it says found matching plugin picarto for url https:// https://picarto.tv/picknamehere
then the it says error: no stream on this URL: https://picarto.tv/picknamehere.
thanks guys for the awesome program hopefully it gets solved soon!

--- 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 import re
2 
3 from streamlink.plugin import Plugin
4 from streamlink.plugin.api import http
5 from streamlink.stream import RTMPStream
6 
7 API_CHANNEL_INFO = "https://picarto.tv/process/channel"
8 RTMP_URL = "rtmp://{}:1935/play/"
9 RTMP_PLAYPATH = "golive+{}?token={}"
10 
11 _url_re = re.compile(r"""
12     https?://(\w+\.)?picarto\.tv/[^&?/]
13 """, re.VERBOSE)
14 
15 _channel_casing_re = re.compile(r"""
16     <script>placeStreamChannel(Flash)?\('(?P<channel>[^']+)',[^,]+,[^,]+,'(?P<visibility>[^']+)'(,[^,]+)?\);</script>
17 """, re.VERBOSE)
18 
19 
20 class Picarto(Plugin):
21     @classmethod
22     def can_handle_url(self, url):
23         return _url_re.match(url)
24 
25     def _get_streams(self):
26         page_res = http.get(self.url)
27         match = _channel_casing_re.search(page_res.text)
28 
29         if not match:
30             return {}
31 
32         channel = match.group("channel")
33         visibility = match.group("visibility")
34 
35         channel_server_res = http.post(API_CHANNEL_INFO, data={
36             "loadbalancinginfo": channel
37         })
38 
39         streams = {}
40         streams["live"] = RTMPStream(self.session, {
41             "rtmp": RTMP_URL.format(channel_server_res.text),
42             "playpath": RTMP_PLAYPATH.format(channel, visibility),
43             "pageUrl": self.url,
44             "live": True
45         })
46         return streams
47 
48 __plugin__ = Picarto
49
```
--- 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
@@ -2,47 +2,69 @@
 
 from streamlink.plugin import Plugin
 from streamlink.plugin.api import http
+from streamlink.stream import HLSStream
 from streamlink.stream import RTMPStream
 
 API_CHANNEL_INFO = "https://picarto.tv/process/channel"
 RTMP_URL = "rtmp://{}:1935/play/"
 RTMP_PLAYPATH = "golive+{}?token={}"
+HLS_URL = "https://{}/hls/{}/index.m3u8?token={}"
 
 _url_re = re.compile(r"""
     https?://(\w+\.)?picarto\.tv/[^&?/]
 """, re.VERBOSE)
 
+# placeStream(channel, playerID, product, offlineImage, online, token, tech)
 _channel_casing_re = re.compile(r"""
-    <script>placeStreamChannel(Flash)?\('(?P<channel>[^']+)',[^,]+,[^,]+,'(?P<visibility>[^']+)'(,[^,]+)?\);</script>
+    <script>\s*placeStream\s*\((.*?)\);?\s*</script>
 """, re.VERBOSE)
 
 
 class Picarto(Plugin):
     @classmethod
-    def can_handle_url(self, url):
-        return _url_re.match(url)
+    def can_handle_url(cls, url):
+        return _url_re.match(url) is not None
+
+    @staticmethod
+    def _get_stream_arguments(page):
+        match = _channel_casing_re.search(page.text)
+        if not match:
+            raise ValueError
+
+        # transform the arguments
+        channel, player_id, product, offline_image, online, visibility, is_flash = \
+            map(lambda a: a.strip("' \""), match.group(1).split(","))
+        player_id, product, offline_image, online, is_flash = \
+            map(lambda a: bool(int(a)), [player_id, product, offline_image, online, is_flash])
+
+        return channel, player_id, product, offline_image, online, visibility, is_flash
 
     def _get_streams(self):
-        page_res = http.get(self.url)
-        match = _channel_casing_re.search(page_res.text)
+        page = http.get(self.url)
 
-        if not match:
-            return {}
+        try:
+            channel, _, _, _, online, visibility, is_flash = self._get_stream_arguments(page)
+        except ValueError:
+            return
 
-        channel = match.group("channel")
-        visibility = match.group("visibility")
+        if not online:
+            self.logger.error("This stream is currently offline")
+            return
 
         channel_server_res = http.post(API_CHANNEL_INFO, data={
             "loadbalancinginfo": channel
         })
 
-        streams = {}
-        streams["live"] = RTMPStream(self.session, {
-            "rtmp": RTMP_URL.format(channel_server_res.text),
-            "playpath": RTMP_PLAYPATH.format(channel, visibility),
-            "pageUrl": self.url,
-            "live": True
-        })
-        return streams
+        if is_flash:
+            return {"live": RTMPStream(self.session, {
+                "rtmp": RTMP_URL.format(channel_server_res.text),
+                "playpath": RTMP_PLAYPATH.format(channel, visibility),
+                "pageUrl": self.url,
+                "live": True
+            })}
+        else:
+            return HLSStream.parse_variant_playlist(self.session,
+                                                    HLS_URL.format(channel_server_res.text, channel, visibility),
+                                                    verify=False)
 
 __plugin__ = Picarto

{"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@@ -2,47 +2,69 @@\n \n from streamlink.plugin import Plugin\n from streamlink.plugin.api import http\n+from streamlink.stream import HLSStream\n from streamlink.stream import RTMPStream\n \n API_CHANNEL_INFO = \"https://picarto.tv/process/channel\"\n RTMP_URL = \"rtmp://{}:1935/play/\"\n RTMP_PLAYPATH = \"golive+{}?token={}\"\n+HLS_URL = \"https://{}/hls/{}/index.m3u8?token={}\"\n \n _url_re = re.compile(r\"\"\"\n     https?://(\\w+\\.)?picarto\\.tv/[^&?/]\n \"\"\", re.VERBOSE)\n \n+# placeStream(channel, playerID, product, offlineImage, online, token, tech)\n _channel_casing_re = re.compile(r\"\"\"\n-    <script>placeStreamChannel(Flash)?\\('(?P<channel>[^']+)',[^,]+,[^,]+,'(?P<visibility>[^']+)'(,[^,]+)?\\);</script>\n+    <script>\\s*placeStream\\s*\\((.*?)\\);?\\s*</script>\n \"\"\", re.VERBOSE)\n \n \n class Picarto(Plugin):\n     @classmethod\n-    def can_handle_url(self, url):\n-        return _url_re.match(url)\n+    def can_handle_url(cls, url):\n+        return _url_re.match(url) is not None\n+\n+    @staticmethod\n+    def _get_stream_arguments(page):\n+        match = _channel_casing_re.search(page.text)\n+        if not match:\n+            raise ValueError\n+\n+        # transform the arguments\n+        channel, player_id, product, offline_image, online, visibility, is_flash = \\\n+            map(lambda a: a.strip(\"' \\\"\"), match.group(1).split(\",\"))\n+        player_id, product, offline_image, online, is_flash = \\\n+            map(lambda a: bool(int(a)), [player_id, product, offline_image, online, is_flash])\n+\n+        return channel, player_id, product, offline_image, online, visibility, is_flash\n \n     def _get_streams(self):\n-        page_res = http.get(self.url)\n-        match = _channel_casing_re.search(page_res.text)\n+        page = http.get(self.url)\n \n-        if not match:\n-            return {}\n+        try:\n+            channel, _, _, _, online, visibility, is_flash = self._get_stream_arguments(page)\n+        except ValueError:\n+            return\n \n-        channel = match.group(\"channel\")\n-        visibility = match.group(\"visibility\")\n+        if not online:\n+            self.logger.error(\"This stream is currently offline\")\n+            return\n \n         channel_server_res = http.post(API_CHANNEL_INFO, data={\n             \"loadbalancinginfo\": channel\n         })\n \n-        streams = {}\n-        streams[\"live\"] = RTMPStream(self.session, {\n-            \"rtmp\": RTMP_URL.format(channel_server_res.text),\n-            \"playpath\": RTMP_PLAYPATH.format(channel, visibility),\n-            \"pageUrl\": self.url,\n-            \"live\": True\n-        })\n-        return streams\n+        if is_flash:\n+            return {\"live\": RTMPStream(self.session, {\n+                \"rtmp\": RTMP_URL.format(channel_server_res.text),\n+                \"playpath\": RTMP_PLAYPATH.format(channel, visibility),\n+                \"pageUrl\": self.url,\n+                \"live\": True\n+            })}\n+        else:\n+            return HLSStream.parse_variant_playlist(self.session,\n+                                                    HLS_URL.format(channel_server_res.text, channel, visibility),\n+                                                    verify=False)\n \n __plugin__ = Picarto\n", "issue": "picarto updated streamlink no longer works\nHey guys picarto no longer works because they said they updated the player so html5 can be default soon.\r\nwhen you run  the program it says found matching plugin picarto for url https:// https://picarto.tv/picknamehere\r\nthen the it says error: no stream on this URL: https://picarto.tv/picknamehere.\r\nthanks guys for the awesome program hopefully it gets solved soon!\n", "before_files": [{"content": "import re\n\nfrom streamlink.plugin import Plugin\nfrom streamlink.plugin.api import http\nfrom streamlink.stream import RTMPStream\n\nAPI_CHANNEL_INFO = \"https://picarto.tv/process/channel\"\nRTMP_URL = \"rtmp://{}:1935/play/\"\nRTMP_PLAYPATH = \"golive+{}?token={}\"\n\n_url_re = re.compile(r\"\"\"\n    https?://(\\w+\\.)?picarto\\.tv/[^&?/]\n\"\"\", re.VERBOSE)\n\n_channel_casing_re = re.compile(r\"\"\"\n    <script>placeStreamChannel(Flash)?\\('(?P<channel>[^']+)',[^,]+,[^,]+,'(?P<visibility>[^']+)'(,[^,]+)?\\);</script>\n\"\"\", re.VERBOSE)\n\n\nclass Picarto(Plugin):\n    @classmethod\n    def can_handle_url(self, url):\n        return _url_re.match(url)\n\n    def _get_streams(self):\n        page_res = http.get(self.url)\n        match = _channel_casing_re.search(page_res.text)\n\n        if not match:\n            return {}\n\n        channel = match.group(\"channel\")\n        visibility = match.group(\"visibility\")\n\n        channel_server_res = http.post(API_CHANNEL_INFO, data={\n            \"loadbalancinginfo\": channel\n        })\n\n        streams = {}\n        streams[\"live\"] = RTMPStream(self.session, {\n            \"rtmp\": RTMP_URL.format(channel_server_res.text),\n            \"playpath\": RTMP_PLAYPATH.format(channel, visibility),\n            \"pageUrl\": self.url,\n            \"live\": True\n        })\n        return streams\n\n__plugin__ = Picarto\n", "path": "src/streamlink/plugins/picarto.py"}], "after_files": [{"content": "import re\n\nfrom streamlink.plugin import Plugin\nfrom streamlink.plugin.api import http\nfrom streamlink.stream import HLSStream\nfrom streamlink.stream import RTMPStream\n\nAPI_CHANNEL_INFO = \"https://picarto.tv/process/channel\"\nRTMP_URL = \"rtmp://{}:1935/play/\"\nRTMP_PLAYPATH = \"golive+{}?token={}\"\nHLS_URL = \"https://{}/hls/{}/index.m3u8?token={}\"\n\n_url_re = re.compile(r\"\"\"\n    https?://(\\w+\\.)?picarto\\.tv/[^&?/]\n\"\"\", re.VERBOSE)\n\n# placeStream(channel, playerID, product, offlineImage, online, token, tech)\n_channel_casing_re = re.compile(r\"\"\"\n    <script>\\s*placeStream\\s*\\((.*?)\\);?\\s*</script>\n\"\"\", re.VERBOSE)\n\n\nclass Picarto(Plugin):\n    @classmethod\n    def can_handle_url(cls, url):\n        return _url_re.match(url) is not None\n\n    @staticmethod\n    def _get_stream_arguments(page):\n        match = _channel_casing_re.search(page.text)\n        if not match:\n            raise ValueError\n\n        # transform the arguments\n        channel, player_id, product, offline_image, online, visibility, is_flash = \\\n            map(lambda a: a.strip(\"' \\\"\"), match.group(1).split(\",\"))\n        player_id, product, offline_image, online, is_flash = \\\n            map(lambda a: bool(int(a)), [player_id, product, offline_image, online, is_flash])\n\n        return channel, player_id, product, offline_image, online, visibility, is_flash\n\n    def _get_streams(self):\n        page = http.get(self.url)\n\n        try:\n            channel, _, _, _, online, visibility, is_flash = self._get_stream_arguments(page)\n        except ValueError:\n            return\n\n        if not online:\n            self.logger.error(\"This stream is currently offline\")\n            return\n\n        channel_server_res = http.post(API_CHANNEL_INFO, data={\n            \"loadbalancinginfo\": channel\n        })\n\n        if is_flash:\n            return {\"live\": RTMPStream(self.session, {\n                \"rtmp\": RTMP_URL.format(channel_server_res.text),\n                \"playpath\": RTMP_PLAYPATH.format(channel, visibility),\n                \"pageUrl\": self.url,\n                \"live\": True\n            })}\n        else:\n            return HLSStream.parse_variant_playlist(self.session,\n                                                    HLS_URL.format(channel_server_res.text, channel, visibility),\n                                                    verify=False)\n\n__plugin__ = Picarto\n", "path": "src/streamlink/plugins/picarto.py"}]}