Repository: streamlink/streamlink

Issue:
Request: Add more functions to facebook plugin
### Checklist

- [x] This is a bug report.
- [ ] This is a feature request.
- [x] This is a plugin (improvement) request.
- [ ] I have read the contribution guidelines.

### Description
Reminder that with the new initial support of Mpeg Dash #880 and #990 might be fixable now, depending on what streamlink supports and how Facebook's videos and livestreaming has changed since this was last looked it.



Discussion:
there dash stream does not work with streamlink

```
[console][info] Found matching plugin dash for URL https://video.fhaj1-1.fna.fbcdn.net/.../live-dash/dash-abr4/000.mpd?...
[plugin.dash][debug] Parsing MPD URL: https://video.fhaj1-1.fna.fbcdn.net/.../live-dash/dash-abr4/000.mpd?...
[console][info] Available streams: 240p (worst), 360p, 480p, 720p (best)
[console][info] Opening stream: 720p (dash)
[stream.dash][debug] Opening DASH reader for: live-hd1-v
[stream.dash][debug] Opening DASH reader for: live-md-a
[stream.dash_manifest][debug] Generating segment timeline for dynamic playlist (id=live-hd1-v))
[stream.dash][debug] Reloading manifest (live-hd1-v)
[stream.dash_manifest][debug] Generating segment timeline for dynamic playlist (id=live-md-a))
[stream.dash][debug] Reloading manifest (live-md-a)
[stream.mp4mux-ffmpeg][debug] ffmpeg command: /usr/bin/ffmpeg -nostats -y -i /tmp/ffmpeg-18118-462 -i /tmp/ffmpeg-18118-804 -c:v copy -c:a copy -copyts -f matroska pipe:1
[stream.ffmpegmux][debug] Starting copy to pipe: /tmp/ffmpeg-18118-462
[stream.ffmpegmux][debug] Starting copy to pipe: /tmp/ffmpeg-18118-804
[console][debug] Pre-buffering 8192 bytes
[stream.dash][debug] Download of segment: .../live-dash/live-hd1-v/000-init.m4v complete
[stream.dash][debug] Download of segment: .../live-dash/live-md-a/000-init.m4a complete
[stream.dash][debug] Download of segment: .../live-dash/live-hd1-v/000-11894667.m4v complete
[stream.dash][debug] Download of segment: .../live-dash/live-md-a/000-11894667.m4a complete
[console][info] Starting player: /usr/bin/mpv
[console][debug] Writing stream to output
[stream.dash_manifest][debug] Generating segment timeline for dynamic playlist (id=live-hd1-v))
[stream.dash][debug] Reloading manifest (live-hd1-v)
[stream.dash_manifest][debug] Generating segment timeline for dynamic playlist (id=live-md-a))
[stream.dash][debug] Reloading manifest (live-md-a)
[stream.dash_manifest][debug] Generating segment timeline for dynamic playlist (id=live-hd1-v))
[stream.dash][debug] Reloading manifest (live-hd1-v)
[stream.dash_manifest][debug] Generating segment timeline for dynamic playlist (id=live-md-a))
[stream.dash][debug] Reloading manifest (live-md-a)
[stream.dash_manifest][debug] Generating segment timeline for dynamic playlist (id=live-hd1-v))
[stream.dash][debug] Reloading manifest (live-hd1-v)
[stream.dash_manifest][debug] Generating segment timeline for dynamic playlist (id=live-md-a))
[stream.dash][debug] Reloading manifest (live-md-a)
```
@back-to any chance of a redacted mpd on gist?
sure https://gist.github.com/back-to/bc2437374b0ae1a47d67eb3a5b386e2f
@back-to is it OK to include that mpd in the test resources?
@back-to would you be able to upload 2 mpds 5 seconds apart? I cannot see why it wouldn't work. (I don't use Facebook).
here is a git-diff

https://gist.github.com/back-to/bc2437374b0ae1a47d67eb3a5b386e2f#file-123-diff

it does not change that much

---

the probleme is

it works for **2 sec**,
but it won't reload for the next segments
Perfect, thanks @back-to 
Looks like they don't update `MPD@publishTime`... I'm working on a more reliable method to detect changes in the segments.

Resolving patch:
diff --git a/src/streamlink/plugins/facebook.py b/src/streamlink/plugins/facebook.py
--- a/src/streamlink/plugins/facebook.py
+++ b/src/streamlink/plugins/facebook.py
@@ -1,26 +1,42 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.stream import HLSStream
-
-_playlist_url = "https://www.facebook.com/video/playback/playlist.m3u8?v={0}"
-
-_url_re = re.compile(r"http(s)?://(www\.)?facebook\.com/[^/]+/videos/(?P<video_id>\d+)")
+from streamlink.plugin.api import http, useragents
+from streamlink.stream import DASHStream, HTTPStream
+from streamlink.utils import parse_json
 
 
 class Facebook(Plugin):
+    _url_re = re.compile(r"https?://(?:www\.)?facebook\.com/[^/]+/videos")
+    _mpd_re = re.compile(r'''(sd|hd)_src["']?\s*:\s*(?P<quote>["'])(?P<url>.+?)(?P=quote)''')
+    _playlist_re = re.compile(r'''video:\[({url:".+?}\])''')
+    _plurl_re = re.compile(r'''url:"(.*?)"''')
+
     @classmethod
     def can_handle_url(cls, url):
-        return _url_re.match(url)
+        return cls._url_re.match(url)
 
-    @Plugin.broken(990)
     def _get_streams(self):
-        match = _url_re.match(self.url)
-        video = match.group("video_id")
+        res = http.get(self.url, headers={"User-Agent": useragents.CHROME})
+        with open("temp.html", "w") as f:
+            f.write(res.text)
+
+        for match in self._mpd_re.finditer(res.text):
+            manifest_url = match.group("url")
+            if "\\/" in manifest_url:
+                # if the URL is json encoded, decode it
+                manifest_url = parse_json("\"{}\"".format(manifest_url))
+            for s in DASHStream.parse_manifest(self.session, manifest_url).items():
+                yield s
+        else:
+            match = self._playlist_re.search(res.text)
+            playlist = match and match.group(1)
+            if playlist:
+                for url in {url.group(1) for url in self._plurl_re.finditer(playlist)}:
+                    yield "live", HTTPStream(self.session, url)
+
 
-        playlist = _playlist_url.format(video)
 
-        return HLSStream.parse_variant_playlist(self.session, playlist)
 
 
 __plugin__ = Facebook


Test patch: