prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  plugins.bfmtv: No playable streams found
   Hello. for few days, the plugin isn't working anymore
  
  
  /usr/local/bin/streamlink --loglevel debug  https://rmcdecouverte.bfmtv.com/mediaplayer-direct/ best
  [cli][info] streamlink is running as root! Be careful!
  [cli][debug] OS:         Linux-5.8.0-44-generic-x86_64-with-glibc2.29
  [cli][debug] Python:     3.8.5
  [cli][debug] Streamlink: 2.1.1
  [cli][debug] Requests(2.22.0), Socks(1.7.1), Websocket(0.58.0)
  [cli][debug] Arguments:
  [cli][debug]  url=https://rmcdecouverte.bfmtv.com/mediaplayer-direct/
  [cli][debug]  stream=['best']
  [cli][debug]  --loglevel=debug
  [cli][info] Found matching plugin bfmtv for URL https://rmcdecouverte.bfmtv.com/mediaplayer-direct/
  error: No playable streams found on this URL: https://rmcdecouverte.bfmtv.com/mediaplayer-direct/
  
  --- 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/bfmtv.py`
  Content:
  ```
  1 import logging
  2 import re
  3 
  4 from streamlink.plugin import Plugin
  5 from streamlink.plugins.brightcove import BrightcovePlayer
  6 
  7 log = logging.getLogger(__name__)
  8 
  9 
  10 class BFMTV(Plugin):
  11     _url_re = re.compile(r'https://.+\.(?:bfmtv|01net)\.com')
  12     _dailymotion_url = 'https://www.dailymotion.com/embed/video/{}'
  13     _brightcove_video_re = re.compile(
  14         r'accountid="(?P<account_id>[0-9]+).*?videoid="(?P<video_id>[0-9]+)"',
  15         re.DOTALL
  16     )
  17     _brightcove_video_alt_re = re.compile(
  18         r'data-account="(?P<account_id>[0-9]+).*?data-video-id="(?P<video_id>[0-9]+)"',
  19         re.DOTALL
  20     )
  21     _embed_video_id_re = re.compile(
  22         r'<iframe.*?src=".*?/(?P<video_id>\w+)"',
  23         re.DOTALL
  24     )
  25 
  26     @classmethod
  27     def can_handle_url(cls, url):
  28         return cls._url_re.match(url) is not None
  29 
  30     def _get_streams(self):
  31         # Retrieve URL page and search for Brightcove video data
  32         res = self.session.http.get(self.url)
  33         match = self._brightcove_video_re.search(res.text) or self._brightcove_video_alt_re.search(res.text)
  34         if match is not None:
  35             account_id = match.group('account_id')
  36             log.debug(f'Account ID: {account_id}')
  37             video_id = match.group('video_id')
  38             log.debug(f'Video ID: {video_id}')
  39             player = BrightcovePlayer(self.session, account_id)
  40             yield from player.get_streams(video_id)
  41         else:
  42             # Try to find the Dailymotion video ID
  43             match = self._embed_video_id_re.search(res.text)
  44             if match is not None:
  45                 video_id = match.group('video_id')
  46                 log.debug(f'Video ID: {video_id}')
  47                 yield from self.session.streams(self._dailymotion_url.format(video_id)).items()
  48 
  49 
  50 __plugin__ = BFMTV
  51
  ```
  --- 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/bfmtv.py b/src/streamlink/plugins/bfmtv.py
  --- a/src/streamlink/plugins/bfmtv.py
  +++ b/src/streamlink/plugins/bfmtv.py
  @@ -1,8 +1,11 @@
   import logging
   import re
  +from urllib.parse import urljoin, urlparse
   
   from streamlink.plugin import Plugin
  +from streamlink.plugin.api.utils import itertags
   from streamlink.plugins.brightcove import BrightcovePlayer
  +from streamlink.stream import HTTPStream
   
   log = logging.getLogger(__name__)
   
  @@ -22,29 +25,68 @@
           r'<iframe.*?src=".*?/(?P<video_id>\w+)"',
           re.DOTALL
       )
  +    _main_js_url_re = re.compile(r'src="([\w/]+/main\.\w+\.js)"')
  +    _js_brightcove_video_re = re.compile(
  +        r'i\?\([A-Z]="[^"]+",y="(?P<video_id>[0-9]+).*"data-account"\s*:\s*"(?P<account_id>[0-9]+)',
  +    )
   
       @classmethod
       def can_handle_url(cls, url):
           return cls._url_re.match(url) is not None
   
       def _get_streams(self):
  -        # Retrieve URL page and search for Brightcove video data
           res = self.session.http.get(self.url)
  -        match = self._brightcove_video_re.search(res.text) or self._brightcove_video_alt_re.search(res.text)
  -        if match is not None:
  -            account_id = match.group('account_id')
  +
  +        m = self._brightcove_video_re.search(res.text) or self._brightcove_video_alt_re.search(res.text)
  +        if m:
  +            account_id = m.group('account_id')
               log.debug(f'Account ID: {account_id}')
  -            video_id = match.group('video_id')
  +            video_id = m.group('video_id')
               log.debug(f'Video ID: {video_id}')
               player = BrightcovePlayer(self.session, account_id)
               yield from player.get_streams(video_id)
  -        else:
  -            # Try to find the Dailymotion video ID
  -            match = self._embed_video_id_re.search(res.text)
  -            if match is not None:
  -                video_id = match.group('video_id')
  +            return
  +
  +        # Try to find the Dailymotion video ID
  +        m = self._embed_video_id_re.search(res.text)
  +        if m:
  +            video_id = m.group('video_id')
  +            log.debug(f'Video ID: {video_id}')
  +            yield from self.session.streams(self._dailymotion_url.format(video_id)).items()
  +            return
  +
  +        # Try the JS for Brightcove video data
  +        m = self._main_js_url_re.search(res.text)
  +        if m:
  +            log.debug(f'JS URL: {urljoin(self.url, m.group(1))}')
  +            res = self.session.http.get(urljoin(self.url, m.group(1)))
  +            m = self._js_brightcove_video_re.search(res.text)
  +            if m:
  +                account_id = m.group('account_id')
  +                log.debug(f'Account ID: {account_id}')
  +                video_id = m.group('video_id')
                   log.debug(f'Video ID: {video_id}')
  -                yield from self.session.streams(self._dailymotion_url.format(video_id)).items()
  +                player = BrightcovePlayer(self.session, account_id)
  +                yield from player.get_streams(video_id)
  +                return
  +
  +        # Audio Live
  +        audio_url = None
  +        for source in itertags(res.text, 'source'):
  +            url = source.attributes.get('src')
  +            if url:
  +                p_url = urlparse(url)
  +                if p_url.path.endswith(('.mp3')):
  +                    audio_url = url
  +
  +        # Audio VOD
  +        for div in itertags(res.text, 'div'):
  +            if div.attributes.get('class') == 'audio-player':
  +                audio_url = div.attributes.get('data-media-url')
  +
  +        if audio_url:
  +            yield 'audio', HTTPStream(self.session, audio_url)
  +            return
   
   
   __plugin__ = BFMTV
  
verification_info: {"golden_diff": "diff --git a/src/streamlink/plugins/bfmtv.py b/src/streamlink/plugins/bfmtv.py\n--- a/src/streamlink/plugins/bfmtv.py\n+++ b/src/streamlink/plugins/bfmtv.py\n@@ -1,8 +1,11 @@\n import logging\n import re\n+from urllib.parse import urljoin, urlparse\n \n from streamlink.plugin import Plugin\n+from streamlink.plugin.api.utils import itertags\n from streamlink.plugins.brightcove import BrightcovePlayer\n+from streamlink.stream import HTTPStream\n \n log = logging.getLogger(__name__)\n \n@@ -22,29 +25,68 @@\n         r'<iframe.*?src=\".*?/(?P<video_id>\\w+)\"',\n         re.DOTALL\n     )\n+    _main_js_url_re = re.compile(r'src=\"([\\w/]+/main\\.\\w+\\.js)\"')\n+    _js_brightcove_video_re = re.compile(\n+        r'i\\?\\([A-Z]=\"[^\"]+\",y=\"(?P<video_id>[0-9]+).*\"data-account\"\\s*:\\s*\"(?P<account_id>[0-9]+)',\n+    )\n \n     @classmethod\n     def can_handle_url(cls, url):\n         return cls._url_re.match(url) is not None\n \n     def _get_streams(self):\n-        # Retrieve URL page and search for Brightcove video data\n         res = self.session.http.get(self.url)\n-        match = self._brightcove_video_re.search(res.text) or self._brightcove_video_alt_re.search(res.text)\n-        if match is not None:\n-            account_id = match.group('account_id')\n+\n+        m = self._brightcove_video_re.search(res.text) or self._brightcove_video_alt_re.search(res.text)\n+        if m:\n+            account_id = m.group('account_id')\n             log.debug(f'Account ID: {account_id}')\n-            video_id = match.group('video_id')\n+            video_id = m.group('video_id')\n             log.debug(f'Video ID: {video_id}')\n             player = BrightcovePlayer(self.session, account_id)\n             yield from player.get_streams(video_id)\n-        else:\n-            # Try to find the Dailymotion video ID\n-            match = self._embed_video_id_re.search(res.text)\n-            if match is not None:\n-                video_id = match.group('video_id')\n+            return\n+\n+        # Try to find the Dailymotion video ID\n+        m = self._embed_video_id_re.search(res.text)\n+        if m:\n+            video_id = m.group('video_id')\n+            log.debug(f'Video ID: {video_id}')\n+            yield from self.session.streams(self._dailymotion_url.format(video_id)).items()\n+            return\n+\n+        # Try the JS for Brightcove video data\n+        m = self._main_js_url_re.search(res.text)\n+        if m:\n+            log.debug(f'JS URL: {urljoin(self.url, m.group(1))}')\n+            res = self.session.http.get(urljoin(self.url, m.group(1)))\n+            m = self._js_brightcove_video_re.search(res.text)\n+            if m:\n+                account_id = m.group('account_id')\n+                log.debug(f'Account ID: {account_id}')\n+                video_id = m.group('video_id')\n                 log.debug(f'Video ID: {video_id}')\n-                yield from self.session.streams(self._dailymotion_url.format(video_id)).items()\n+                player = BrightcovePlayer(self.session, account_id)\n+                yield from player.get_streams(video_id)\n+                return\n+\n+        # Audio Live\n+        audio_url = None\n+        for source in itertags(res.text, 'source'):\n+            url = source.attributes.get('src')\n+            if url:\n+                p_url = urlparse(url)\n+                if p_url.path.endswith(('.mp3')):\n+                    audio_url = url\n+\n+        # Audio VOD\n+        for div in itertags(res.text, 'div'):\n+            if div.attributes.get('class') == 'audio-player':\n+                audio_url = div.attributes.get('data-media-url')\n+\n+        if audio_url:\n+            yield 'audio', HTTPStream(self.session, audio_url)\n+            return\n \n \n __plugin__ = BFMTV\n", "issue": "plugins.bfmtv: No playable streams found\n Hello. for few days, the plugin isn't working anymore\r\n\r\n\r\n/usr/local/bin/streamlink --loglevel debug  https://rmcdecouverte.bfmtv.com/mediaplayer-direct/ best\r\n[cli][info] streamlink is running as root! Be careful!\r\n[cli][debug] OS:         Linux-5.8.0-44-generic-x86_64-with-glibc2.29\r\n[cli][debug] Python:     3.8.5\r\n[cli][debug] Streamlink: 2.1.1\r\n[cli][debug] Requests(2.22.0), Socks(1.7.1), Websocket(0.58.0)\r\n[cli][debug] Arguments:\r\n[cli][debug]  url=https://rmcdecouverte.bfmtv.com/mediaplayer-direct/\r\n[cli][debug]  stream=['best']\r\n[cli][debug]  --loglevel=debug\r\n[cli][info] Found matching plugin bfmtv for URL https://rmcdecouverte.bfmtv.com/mediaplayer-direct/\r\nerror: No playable streams found on this URL: https://rmcdecouverte.bfmtv.com/mediaplayer-direct/\n", "before_files": [{"content": "import logging\nimport re\n\nfrom streamlink.plugin import Plugin\nfrom streamlink.plugins.brightcove import BrightcovePlayer\n\nlog = logging.getLogger(__name__)\n\n\nclass BFMTV(Plugin):\n    _url_re = re.compile(r'https://.+\\.(?:bfmtv|01net)\\.com')\n    _dailymotion_url = 'https://www.dailymotion.com/embed/video/{}'\n    _brightcove_video_re = re.compile(\n        r'accountid=\"(?P<account_id>[0-9]+).*?videoid=\"(?P<video_id>[0-9]+)\"',\n        re.DOTALL\n    )\n    _brightcove_video_alt_re = re.compile(\n        r'data-account=\"(?P<account_id>[0-9]+).*?data-video-id=\"(?P<video_id>[0-9]+)\"',\n        re.DOTALL\n    )\n    _embed_video_id_re = re.compile(\n        r'<iframe.*?src=\".*?/(?P<video_id>\\w+)\"',\n        re.DOTALL\n    )\n\n    @classmethod\n    def can_handle_url(cls, url):\n        return cls._url_re.match(url) is not None\n\n    def _get_streams(self):\n        # Retrieve URL page and search for Brightcove video data\n        res = self.session.http.get(self.url)\n        match = self._brightcove_video_re.search(res.text) or self._brightcove_video_alt_re.search(res.text)\n        if match is not None:\n            account_id = match.group('account_id')\n            log.debug(f'Account ID: {account_id}')\n            video_id = match.group('video_id')\n            log.debug(f'Video ID: {video_id}')\n            player = BrightcovePlayer(self.session, account_id)\n            yield from player.get_streams(video_id)\n        else:\n            # Try to find the Dailymotion video ID\n            match = self._embed_video_id_re.search(res.text)\n            if match is not None:\n                video_id = match.group('video_id')\n                log.debug(f'Video ID: {video_id}')\n                yield from self.session.streams(self._dailymotion_url.format(video_id)).items()\n\n\n__plugin__ = BFMTV\n", "path": "src/streamlink/plugins/bfmtv.py"}], "after_files": [{"content": "import logging\nimport re\nfrom urllib.parse import urljoin, urlparse\n\nfrom streamlink.plugin import Plugin\nfrom streamlink.plugin.api.utils import itertags\nfrom streamlink.plugins.brightcove import BrightcovePlayer\nfrom streamlink.stream import HTTPStream\n\nlog = logging.getLogger(__name__)\n\n\nclass BFMTV(Plugin):\n    _url_re = re.compile(r'https://.+\\.(?:bfmtv|01net)\\.com')\n    _dailymotion_url = 'https://www.dailymotion.com/embed/video/{}'\n    _brightcove_video_re = re.compile(\n        r'accountid=\"(?P<account_id>[0-9]+).*?videoid=\"(?P<video_id>[0-9]+)\"',\n        re.DOTALL\n    )\n    _brightcove_video_alt_re = re.compile(\n        r'data-account=\"(?P<account_id>[0-9]+).*?data-video-id=\"(?P<video_id>[0-9]+)\"',\n        re.DOTALL\n    )\n    _embed_video_id_re = re.compile(\n        r'<iframe.*?src=\".*?/(?P<video_id>\\w+)\"',\n        re.DOTALL\n    )\n    _main_js_url_re = re.compile(r'src=\"([\\w/]+/main\\.\\w+\\.js)\"')\n    _js_brightcove_video_re = re.compile(\n        r'i\\?\\([A-Z]=\"[^\"]+\",y=\"(?P<video_id>[0-9]+).*\"data-account\"\\s*:\\s*\"(?P<account_id>[0-9]+)',\n    )\n\n    @classmethod\n    def can_handle_url(cls, url):\n        return cls._url_re.match(url) is not None\n\n    def _get_streams(self):\n        res = self.session.http.get(self.url)\n\n        m = self._brightcove_video_re.search(res.text) or self._brightcove_video_alt_re.search(res.text)\n        if m:\n            account_id = m.group('account_id')\n            log.debug(f'Account ID: {account_id}')\n            video_id = m.group('video_id')\n            log.debug(f'Video ID: {video_id}')\n            player = BrightcovePlayer(self.session, account_id)\n            yield from player.get_streams(video_id)\n            return\n\n        # Try to find the Dailymotion video ID\n        m = self._embed_video_id_re.search(res.text)\n        if m:\n            video_id = m.group('video_id')\n            log.debug(f'Video ID: {video_id}')\n            yield from self.session.streams(self._dailymotion_url.format(video_id)).items()\n            return\n\n        # Try the JS for Brightcove video data\n        m = self._main_js_url_re.search(res.text)\n        if m:\n            log.debug(f'JS URL: {urljoin(self.url, m.group(1))}')\n            res = self.session.http.get(urljoin(self.url, m.group(1)))\n            m = self._js_brightcove_video_re.search(res.text)\n            if m:\n                account_id = m.group('account_id')\n                log.debug(f'Account ID: {account_id}')\n                video_id = m.group('video_id')\n                log.debug(f'Video ID: {video_id}')\n                player = BrightcovePlayer(self.session, account_id)\n                yield from player.get_streams(video_id)\n                return\n\n        # Audio Live\n        audio_url = None\n        for source in itertags(res.text, 'source'):\n            url = source.attributes.get('src')\n            if url:\n                p_url = urlparse(url)\n                if p_url.path.endswith(('.mp3')):\n                    audio_url = url\n\n        # Audio VOD\n        for div in itertags(res.text, 'div'):\n            if div.attributes.get('class') == 'audio-player':\n                audio_url = div.attributes.get('data-media-url')\n\n        if audio_url:\n            yield 'audio', HTTPStream(self.session, audio_url)\n            return\n\n\n__plugin__ = BFMTV\n", "path": "src/streamlink/plugins/bfmtv.py"}]}