prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  plugins.ard_mediathek: No playable streams found on this URL
  ### 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 build from the master branch
  
  ### Description
  
  The ARD (German Public TV) seems not to be working at the moment with Streamlink. 
  
  It gives a 'error: No playable streams found on this URL: https://www.ardmediathek.de/daserste/live/Y3JpZDovL2Rhc2Vyc3RlLmRlL0xpdmVzdHJlYW0tRGFzRXJzdGU'
  
  
  ### Debug log
  
  ```text
  [cli][debug] OS:         Linux-5.10.0-15-amd64-x86_64-with-glibc2.31
  [cli][debug] Python:     3.9.2
  [cli][debug] Streamlink: 0.0.0+unknown
  [cli][debug] Dependencies:
  [cli][debug]  PySocks: 1.7.1
  [cli][debug]  isodate: 0.6.1
  [cli][debug]  lxml: 4.8.0
  [cli][debug]  pycountry: 22.3.5
  [cli][debug]  pycryptodome: 3.14.1
  [cli][debug]  requests: 2.27.1
  [cli][debug]  websocket-client: 1.3.1
  [cli][debug]  importlib-metadata: 4.11.3
  [cli][debug] Arguments:
  [cli][debug]  url=https://www.ardmediathek.de/daserste/live/Y3JpZDovL2Rhc2Vyc3RlLmRlL0xpdmVzdHJlYW0tRGFzRXJzdGU
  [cli][debug]  stream=['720p']
  [cli][debug]  --loglevel=debug
  [cli][debug]  --output=blah.mp4
  [cli][debug]  --http-proxy=socks5h://xxx.xxxd@xxxx.dynv6.net:8200
  [cli][info] Found matching plugin ard_mediathek for URL https://www.ardmediathek.de/daserste/live/Y3JpZDovL2Rhc2Vyc3RlLmRlL0xpdmVzdHJlYW0tRGFzRXJzdGU
  error: No playable streams found on this URL: https://www.ardmediathek.de/daserste/live/Y3JpZDovL2Rhc2Vyc3RlLmRlL0xpdmVzdHJlYW0tRGFzRXJzdGU
  ```
  
  
  --- 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/ard_mediathek.py`
  Content:
  ```
  1 """
  2 $description Live TV channels and video on-demand service from ARD, a German public, independent broadcaster.
  3 $url ardmediathek.de
  4 $url mediathek.daserste.de
  5 $type live, vod
  6 $region Germany
  7 """
  8 
  9 import logging
  10 import re
  11 
  12 from streamlink.plugin import Plugin, pluginmatcher
  13 from streamlink.plugin.api import validate
  14 from streamlink.stream.hls import HLSStream
  15 from streamlink.stream.http import HTTPStream
  16 
  17 
  18 log = logging.getLogger(__name__)
  19 
  20 
  21 @pluginmatcher(re.compile(
  22     r"https?://(?:(\w+\.)?ardmediathek\.de/|mediathek\.daserste\.de/)"
  23 ))
  24 class ARDMediathek(Plugin):
  25     _QUALITY_MAP = {
  26         4: "1080p",
  27         3: "720p",
  28         2: "540p",
  29         1: "360p",
  30         0: "270p"
  31     }
  32 
  33     def _get_streams(self):
  34         data_json = self.session.http.get(self.url, schema=validate.Schema(
  35             validate.parse_html(),
  36             validate.xml_findtext(".//script[@id='fetchedContextValue'][@type='application/json']"),
  37             validate.any(None, validate.all(
  38                 validate.parse_json(),
  39                 {str: dict},
  40                 validate.transform(lambda obj: list(obj.items())),
  41                 validate.filter(lambda item: item[0].startswith("https://api.ardmediathek.de/page-gateway/pages/")),
  42                 validate.any(validate.get((0, 1)), [])
  43             ))
  44         ))
  45         if not data_json:
  46             return
  47 
  48         schema_data = validate.Schema({
  49             "id": str,
  50             "widgets": validate.all(
  51                 [dict],
  52                 validate.filter(lambda item: item.get("mediaCollection")),
  53                 validate.get(0),
  54                 validate.any(None, validate.all(
  55                     {
  56                         "geoblocked": bool,
  57                         "publicationService": {
  58                             "name": str,
  59                         },
  60                         "show": validate.any(None, validate.all(
  61                             {"title": str},
  62                             validate.get("title")
  63                         )),
  64                         "title": str,
  65                         "mediaCollection": {
  66                             "embedded": {
  67                                 "_mediaArray": [validate.all(
  68                                     {
  69                                         "_mediaStreamArray": [validate.all(
  70                                             {
  71                                                 "_quality": validate.any(str, int),
  72                                                 "_stream": validate.url(),
  73                                             },
  74                                             validate.union_get("_quality", "_stream")
  75                                         )]
  76                                     },
  77                                     validate.get("_mediaStreamArray"),
  78                                     validate.transform(dict)
  79                                 )]
  80                             }
  81                         },
  82                     },
  83                     validate.union_get(
  84                         "geoblocked",
  85                         ("mediaCollection", "embedded", "_mediaArray", 0),
  86                         ("publicationService", "name"),
  87                         "title",
  88                         "show",
  89                     )
  90                 ))
  91             )
  92         })
  93         data = schema_data.validate(data_json)
  94 
  95         log.debug(f"Found media id: {data['id']}")
  96         if not data["widgets"]:
  97             log.info("The content is unavailable")
  98             return
  99 
  100         geoblocked, media, self.author, self.title, show = data["widgets"]
  101         if geoblocked:
  102             log.info("The content is not available in your region")
  103             return
  104         if show:
  105             self.title = f"{show}: {self.title}"
  106 
  107         if media.get("auto"):
  108             yield from HLSStream.parse_variant_playlist(self.session, media.get("auto")).items()
  109         else:
  110             for quality, stream in media.items():
  111                 yield self._QUALITY_MAP.get(quality, quality), HTTPStream(self.session, stream)
  112 
  113 
  114 __plugin__ = ARDMediathek
  115
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/src/streamlink/plugins/ard_mediathek.py b/src/streamlink/plugins/ard_mediathek.py
  --- a/src/streamlink/plugins/ard_mediathek.py
  +++ b/src/streamlink/plugins/ard_mediathek.py
  @@ -19,29 +19,50 @@
   
   
   @pluginmatcher(re.compile(
  -    r"https?://(?:(\w+\.)?ardmediathek\.de/|mediathek\.daserste\.de/)"
  +    r"""
  +        https?://(\w+\.)?ardmediathek\.de/
  +        (?:
  +            live/(?:[^/]+/)?(?P<id_live>\w+)
  +            |
  +            video/(?:[^/]+/[^/]+/[^/]+/)?(?P<id_video>\w+)
  +        )
  +        (?:\?|$)
  +    """,
  +    re.VERBOSE,
   ))
   class ARDMediathek(Plugin):
  +    _URL_API = "https://api.ardmediathek.de/page-gateway/pages/ard/item/{item}"
       _QUALITY_MAP = {
           4: "1080p",
           3: "720p",
           2: "540p",
           1: "360p",
  -        0: "270p"
  +        0: "270p",
       }
   
       def _get_streams(self):
           data_json = self.session.http.get(self.url, schema=validate.Schema(
               validate.parse_html(),
  -            validate.xml_findtext(".//script[@id='fetchedContextValue'][@type='application/json']"),
  -            validate.any(None, validate.all(
  +            validate.xml_xpath_string(".//script[@type='application/json'][@id='fetchedContextValue2'][1]/text()"),
  +            validate.none_or_all(
                   validate.parse_json(),
  -                {str: dict},
  -                validate.transform(lambda obj: list(obj.items())),
  +                [validate.list(str, {"data": dict})],
                   validate.filter(lambda item: item[0].startswith("https://api.ardmediathek.de/page-gateway/pages/")),
  -                validate.any(validate.get((0, 1)), [])
  -            ))
  +                validate.any(
  +                    validate.get((0, 1, "data")),
  +                    [],
  +                ),
  +            ),
           ))
  +        if not data_json:
  +            data_json = self.session.http.get(
  +                self._URL_API.format(item=self.match.group("id_live") or self.match.group("id_video")),
  +                params={
  +                    "devicetype": "pc",
  +                    "embedded": "false",
  +                },
  +                schema=validate.Schema(validate.parse_json()),
  +            )
           if not data_json:
               return
  
verification_info: {"golden_diff": "diff --git a/src/streamlink/plugins/ard_mediathek.py b/src/streamlink/plugins/ard_mediathek.py\n--- a/src/streamlink/plugins/ard_mediathek.py\n+++ b/src/streamlink/plugins/ard_mediathek.py\n@@ -19,29 +19,50 @@\n \n \n @pluginmatcher(re.compile(\n-    r\"https?://(?:(\\w+\\.)?ardmediathek\\.de/|mediathek\\.daserste\\.de/)\"\n+    r\"\"\"\n+        https?://(\\w+\\.)?ardmediathek\\.de/\n+        (?:\n+            live/(?:[^/]+/)?(?P<id_live>\\w+)\n+            |\n+            video/(?:[^/]+/[^/]+/[^/]+/)?(?P<id_video>\\w+)\n+        )\n+        (?:\\?|$)\n+    \"\"\",\n+    re.VERBOSE,\n ))\n class ARDMediathek(Plugin):\n+    _URL_API = \"https://api.ardmediathek.de/page-gateway/pages/ard/item/{item}\"\n     _QUALITY_MAP = {\n         4: \"1080p\",\n         3: \"720p\",\n         2: \"540p\",\n         1: \"360p\",\n-        0: \"270p\"\n+        0: \"270p\",\n     }\n \n     def _get_streams(self):\n         data_json = self.session.http.get(self.url, schema=validate.Schema(\n             validate.parse_html(),\n-            validate.xml_findtext(\".//script[@id='fetchedContextValue'][@type='application/json']\"),\n-            validate.any(None, validate.all(\n+            validate.xml_xpath_string(\".//script[@type='application/json'][@id='fetchedContextValue2'][1]/text()\"),\n+            validate.none_or_all(\n                 validate.parse_json(),\n-                {str: dict},\n-                validate.transform(lambda obj: list(obj.items())),\n+                [validate.list(str, {\"data\": dict})],\n                 validate.filter(lambda item: item[0].startswith(\"https://api.ardmediathek.de/page-gateway/pages/\")),\n-                validate.any(validate.get((0, 1)), [])\n-            ))\n+                validate.any(\n+                    validate.get((0, 1, \"data\")),\n+                    [],\n+                ),\n+            ),\n         ))\n+        if not data_json:\n+            data_json = self.session.http.get(\n+                self._URL_API.format(item=self.match.group(\"id_live\") or self.match.group(\"id_video\")),\n+                params={\n+                    \"devicetype\": \"pc\",\n+                    \"embedded\": \"false\",\n+                },\n+                schema=validate.Schema(validate.parse_json()),\n+            )\n         if not data_json:\n             return\n", "issue": "plugins.ard_mediathek: No playable streams found on this URL\n### Checklist\r\n\r\n- [X] This is a plugin issue and not a different kind of issue\r\n- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)\r\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)\r\n- [X] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)\r\n\r\n### Streamlink version\r\n\r\nLatest build from the master branch\r\n\r\n### Description\r\n\r\nThe ARD (German Public TV) seems not to be working at the moment with Streamlink. \r\n\r\nIt gives a 'error: No playable streams found on this URL: https://www.ardmediathek.de/daserste/live/Y3JpZDovL2Rhc2Vyc3RlLmRlL0xpdmVzdHJlYW0tRGFzRXJzdGU'\r\n\r\n\r\n### Debug log\r\n\r\n```text\r\n[cli][debug] OS:         Linux-5.10.0-15-amd64-x86_64-with-glibc2.31\r\n[cli][debug] Python:     3.9.2\r\n[cli][debug] Streamlink: 0.0.0+unknown\r\n[cli][debug] Dependencies:\r\n[cli][debug]  PySocks: 1.7.1\r\n[cli][debug]  isodate: 0.6.1\r\n[cli][debug]  lxml: 4.8.0\r\n[cli][debug]  pycountry: 22.3.5\r\n[cli][debug]  pycryptodome: 3.14.1\r\n[cli][debug]  requests: 2.27.1\r\n[cli][debug]  websocket-client: 1.3.1\r\n[cli][debug]  importlib-metadata: 4.11.3\r\n[cli][debug] Arguments:\r\n[cli][debug]  url=https://www.ardmediathek.de/daserste/live/Y3JpZDovL2Rhc2Vyc3RlLmRlL0xpdmVzdHJlYW0tRGFzRXJzdGU\r\n[cli][debug]  stream=['720p']\r\n[cli][debug]  --loglevel=debug\r\n[cli][debug]  --output=blah.mp4\r\n[cli][debug]  --http-proxy=socks5h://xxx.xxxd@xxxx.dynv6.net:8200\r\n[cli][info] Found matching plugin ard_mediathek for URL https://www.ardmediathek.de/daserste/live/Y3JpZDovL2Rhc2Vyc3RlLmRlL0xpdmVzdHJlYW0tRGFzRXJzdGU\r\nerror: No playable streams found on this URL: https://www.ardmediathek.de/daserste/live/Y3JpZDovL2Rhc2Vyc3RlLmRlL0xpdmVzdHJlYW0tRGFzRXJzdGU\r\n```\r\n\n", "before_files": [{"content": "\"\"\"\n$description Live TV channels and video on-demand service from ARD, a German public, independent broadcaster.\n$url ardmediathek.de\n$url mediathek.daserste.de\n$type live, vod\n$region Germany\n\"\"\"\n\nimport logging\nimport re\n\nfrom streamlink.plugin import Plugin, pluginmatcher\nfrom streamlink.plugin.api import validate\nfrom streamlink.stream.hls import HLSStream\nfrom streamlink.stream.http import HTTPStream\n\n\nlog = logging.getLogger(__name__)\n\n\n@pluginmatcher(re.compile(\n    r\"https?://(?:(\\w+\\.)?ardmediathek\\.de/|mediathek\\.daserste\\.de/)\"\n))\nclass ARDMediathek(Plugin):\n    _QUALITY_MAP = {\n        4: \"1080p\",\n        3: \"720p\",\n        2: \"540p\",\n        1: \"360p\",\n        0: \"270p\"\n    }\n\n    def _get_streams(self):\n        data_json = self.session.http.get(self.url, schema=validate.Schema(\n            validate.parse_html(),\n            validate.xml_findtext(\".//script[@id='fetchedContextValue'][@type='application/json']\"),\n            validate.any(None, validate.all(\n                validate.parse_json(),\n                {str: dict},\n                validate.transform(lambda obj: list(obj.items())),\n                validate.filter(lambda item: item[0].startswith(\"https://api.ardmediathek.de/page-gateway/pages/\")),\n                validate.any(validate.get((0, 1)), [])\n            ))\n        ))\n        if not data_json:\n            return\n\n        schema_data = validate.Schema({\n            \"id\": str,\n            \"widgets\": validate.all(\n                [dict],\n                validate.filter(lambda item: item.get(\"mediaCollection\")),\n                validate.get(0),\n                validate.any(None, validate.all(\n                    {\n                        \"geoblocked\": bool,\n                        \"publicationService\": {\n                            \"name\": str,\n                        },\n                        \"show\": validate.any(None, validate.all(\n                            {\"title\": str},\n                            validate.get(\"title\")\n                        )),\n                        \"title\": str,\n                        \"mediaCollection\": {\n                            \"embedded\": {\n                                \"_mediaArray\": [validate.all(\n                                    {\n                                        \"_mediaStreamArray\": [validate.all(\n                                            {\n                                                \"_quality\": validate.any(str, int),\n                                                \"_stream\": validate.url(),\n                                            },\n                                            validate.union_get(\"_quality\", \"_stream\")\n                                        )]\n                                    },\n                                    validate.get(\"_mediaStreamArray\"),\n                                    validate.transform(dict)\n                                )]\n                            }\n                        },\n                    },\n                    validate.union_get(\n                        \"geoblocked\",\n                        (\"mediaCollection\", \"embedded\", \"_mediaArray\", 0),\n                        (\"publicationService\", \"name\"),\n                        \"title\",\n                        \"show\",\n                    )\n                ))\n            )\n        })\n        data = schema_data.validate(data_json)\n\n        log.debug(f\"Found media id: {data['id']}\")\n        if not data[\"widgets\"]:\n            log.info(\"The content is unavailable\")\n            return\n\n        geoblocked, media, self.author, self.title, show = data[\"widgets\"]\n        if geoblocked:\n            log.info(\"The content is not available in your region\")\n            return\n        if show:\n            self.title = f\"{show}: {self.title}\"\n\n        if media.get(\"auto\"):\n            yield from HLSStream.parse_variant_playlist(self.session, media.get(\"auto\")).items()\n        else:\n            for quality, stream in media.items():\n                yield self._QUALITY_MAP.get(quality, quality), HTTPStream(self.session, stream)\n\n\n__plugin__ = ARDMediathek\n", "path": "src/streamlink/plugins/ard_mediathek.py"}], "after_files": [{"content": "\"\"\"\n$description Live TV channels and video on-demand service from ARD, a German public, independent broadcaster.\n$url ardmediathek.de\n$url mediathek.daserste.de\n$type live, vod\n$region Germany\n\"\"\"\n\nimport logging\nimport re\n\nfrom streamlink.plugin import Plugin, pluginmatcher\nfrom streamlink.plugin.api import validate\nfrom streamlink.stream.hls import HLSStream\nfrom streamlink.stream.http import HTTPStream\n\n\nlog = logging.getLogger(__name__)\n\n\n@pluginmatcher(re.compile(\n    r\"\"\"\n        https?://(\\w+\\.)?ardmediathek\\.de/\n        (?:\n            live/(?:[^/]+/)?(?P<id_live>\\w+)\n            |\n            video/(?:[^/]+/[^/]+/[^/]+/)?(?P<id_video>\\w+)\n        )\n        (?:\\?|$)\n    \"\"\",\n    re.VERBOSE,\n))\nclass ARDMediathek(Plugin):\n    _URL_API = \"https://api.ardmediathek.de/page-gateway/pages/ard/item/{item}\"\n    _QUALITY_MAP = {\n        4: \"1080p\",\n        3: \"720p\",\n        2: \"540p\",\n        1: \"360p\",\n        0: \"270p\",\n    }\n\n    def _get_streams(self):\n        data_json = self.session.http.get(self.url, schema=validate.Schema(\n            validate.parse_html(),\n            validate.xml_xpath_string(\".//script[@type='application/json'][@id='fetchedContextValue2'][1]/text()\"),\n            validate.none_or_all(\n                validate.parse_json(),\n                [validate.list(str, {\"data\": dict})],\n                validate.filter(lambda item: item[0].startswith(\"https://api.ardmediathek.de/page-gateway/pages/\")),\n                validate.any(\n                    validate.get((0, 1, \"data\")),\n                    [],\n                ),\n            ),\n        ))\n        if not data_json:\n            data_json = self.session.http.get(\n                self._URL_API.format(item=self.match.group(\"id_live\") or self.match.group(\"id_video\")),\n                params={\n                    \"devicetype\": \"pc\",\n                    \"embedded\": \"false\",\n                },\n                schema=validate.Schema(validate.parse_json()),\n            )\n        if not data_json:\n            return\n\n        schema_data = validate.Schema({\n            \"id\": str,\n            \"widgets\": validate.all(\n                [dict],\n                validate.filter(lambda item: item.get(\"mediaCollection\")),\n                validate.get(0),\n                validate.any(None, validate.all(\n                    {\n                        \"geoblocked\": bool,\n                        \"publicationService\": {\n                            \"name\": str,\n                        },\n                        \"show\": validate.any(None, validate.all(\n                            {\"title\": str},\n                            validate.get(\"title\")\n                        )),\n                        \"title\": str,\n                        \"mediaCollection\": {\n                            \"embedded\": {\n                                \"_mediaArray\": [validate.all(\n                                    {\n                                        \"_mediaStreamArray\": [validate.all(\n                                            {\n                                                \"_quality\": validate.any(str, int),\n                                                \"_stream\": validate.url(),\n                                            },\n                                            validate.union_get(\"_quality\", \"_stream\")\n                                        )]\n                                    },\n                                    validate.get(\"_mediaStreamArray\"),\n                                    validate.transform(dict)\n                                )]\n                            }\n                        },\n                    },\n                    validate.union_get(\n                        \"geoblocked\",\n                        (\"mediaCollection\", \"embedded\", \"_mediaArray\", 0),\n                        (\"publicationService\", \"name\"),\n                        \"title\",\n                        \"show\",\n                    )\n                ))\n            )\n        })\n        data = schema_data.validate(data_json)\n\n        log.debug(f\"Found media id: {data['id']}\")\n        if not data[\"widgets\"]:\n            log.info(\"The content is unavailable\")\n            return\n\n        geoblocked, media, self.author, self.title, show = data[\"widgets\"]\n        if geoblocked:\n            log.info(\"The content is not available in your region\")\n            return\n        if show:\n            self.title = f\"{show}: {self.title}\"\n\n        if media.get(\"auto\"):\n            yield from HLSStream.parse_variant_playlist(self.session, media.get(\"auto\")).items()\n        else:\n            for quality, stream in media.items():\n                yield self._QUALITY_MAP.get(quality, quality), HTTPStream(self.session, stream)\n\n\n__plugin__ = ARDMediathek\n", "path": "src/streamlink/plugins/ard_mediathek.py"}]}