Repository: streamlink/streamlink

Issue:
bfmtv - No playable streams found on this URL
<!--
Thanks for reporting a plugin issue!
USE THE TEMPLATE. Otherwise your plugin issue may be rejected.

First, see the contribution guidelines:
https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink

Also check the list of open and closed plugin issues:
https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+issue%22

Please see the text preview to avoid unnecessary formatting errors.
-->


## Plugin Issue

<!-- Replace [ ] with [x] in order to check the box -->
- [x] This is a plugin issue and I have read the contribution guidelines.


### Description

<!-- Explain the plugin issue as thoroughly as you can. -->
There is no playable streams for bfmtv

### Reproduction steps / Explicit stream URLs to test

<!-- How can we reproduce this? Please note the exact steps below using the list format supplied. If you need more steps please add them. -->

`streamlink https://www.bfmtv.com/en-direct/ best`

or `streamlink https://www.bfmtv.com/paris/en-direct/ best`
or any other channels supported by this plugin


### Log output

<!--
TEXT LOG OUTPUT IS REQUIRED for a plugin issue!
Use the `--loglevel debug` parameter and avoid using parameters which suppress log output.
https://streamlink.github.io/cli.html#cmdoption-l

Make sure to **remove usernames and passwords**
You can copy the output to https://gist.github.com/ or paste it below.

Don't post screenshots of the log output and instead copy the text from your terminal application.
-->

```
streamlink --loglevel debug https://www.bfmtv.com/en-direct/ best
[cli][debug] OS:         Linux-5.8.15-201.fc32.x86_64-x86_64-with-glibc2.2.5
[cli][debug] Python:     3.8.6
[cli][debug] Streamlink: 1.7.0
[cli][debug] Requests(2.24.0), Socks(1.7.1), Websocket(0.57.0)
[cli][info] Found matching plugin bfmtv for URL https://www.bfmtv.com/en-direct/
error: No playable streams found on this URL: https://www.bfmtv.com/en-direct/
```


### Additional comments, etc.

As a workaround you can use their dailymotion stream: `streamlink https://www.dailymotion.com/embed/video/xgz4t1 best`


Discussion:

Resolving patch:
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,45 +1,46 @@
+import logging
 import re
 
 from streamlink.plugin import Plugin
 from streamlink.plugins.brightcove import BrightcovePlayer
-from streamlink.stream import HLSStream
+
+log = logging.getLogger(__name__)
 
 
 class BFMTV(Plugin):
     _url_re = re.compile(r'https://.+\.(?:bfmtv|01net)\.com')
+    _dailymotion_url = 'https://www.dailymotion.com/embed/video/{}'
     _brightcove_video_re = re.compile(
-        r'data-holder="video(?P<video_id>[0-9]+)" data-account="(?P<account_id>[0-9]+)"'
-    )
-    _brightcove_video_alt_re = re.compile(
-        r'data-account="(?P<account_id>[0-9]+).*?data-video-id="(?P<video_id>[0-9]+)"',
+        r'accountid="(?P<account_id>[0-9]+).*?videoid="(?P<video_id>[0-9]+)"',
         re.DOTALL
     )
-    _embed_video_url_re = re.compile(
-        r"\$YOPLAYER\('liveStitching', {.+?file: '(?P<video_url>[^\"]+?)'.+?}\);",
+    _embed_video_id_re = re.compile(
+        r'<iframe.*?src=".*?/(?P<video_id>\w+)"',
         re.DOTALL
     )
 
     @classmethod
     def can_handle_url(cls, url):
-        return BFMTV._url_re.match(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)
+        match = self._brightcove_video_re.search(res.text)
         if match is not None:
             account_id = match.group('account_id')
+            log.debug(f'Account ID: {account_id}')
             video_id = match.group('video_id')
+            log.debug(f'Video ID: {video_id}')
             player = BrightcovePlayer(self.session, account_id)
-            for stream in player.get_streams(video_id):
-                yield stream
+            yield from player.get_streams(video_id)
         else:
-            # Try to get the stream URL in the page
-            match = self._embed_video_url_re.search(res.text)
+            # Try to find the Dailymotion video ID
+            match = self._embed_video_id_re.search(res.text)
             if match is not None:
-                video_url = match.group('video_url')
-                if '.m3u8' in video_url:
-                    yield from HLSStream.parse_variant_playlist(self.session, video_url).items()
+                video_id = match.group('video_id')
+                log.debug(f'Video ID: {video_id}')
+                yield from self.session.streams(self._dailymotion_url.format(video_id)).items()
 
 
 __plugin__ = BFMTV


Test patch: