Repository: streamlink/streamlink

Issue:
Stadium plugin request
### Checklist

- [x ] This is a feature request.

### Description

Can anyone help with a plugin for Stadium TV here:

https://watchstadium.com/live/


Cheers!



Discussion:
Can you provide more details on the streams or what the network connection looks like etc.?
https://04476b7c682c4da8b8b4bfe23ef879c1.midas.us-east-1.amazonaws.com/v1/manifest 

m3u8 from amazonaws ends up to this playable:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:7
#EXT-X-MEDIA-SEQUENCE:35988
#EXT-X-PROGRAM-DATE-TIME:2017-08-26T22:07:22.133Z
#EXTINF:6.006,
https://stadiumlivein-i.akamaihd.net/hls/live/522512/mux_4/20170824T060520/master_3000/00071/master_3000_00488.ts
https://04476b7c682c4da8b8b4bfe23ef879c1.midas.us-east-1.amazonaws.com/v1/manifest/61a556f78e4547c8ab5c6297ea291d6350767ca2/Mux/ffe7bfb2-e4dc-4d43-8f8c-48868174d97c/0.m3u8


Already have that but when the stream changes a plugin will be able to get the correct stream again.
Did you mean to close this?
Actually no, not sure how that happened.. I only just noticed.. can you  please look into this new plugin. Thanks.
Just to let folks know, this is the exact same issue as this:

https://github.com/streamlink/streamlink/issues/687

It's a channel run by Sinclair and bearybig stated #EXT-X-DISCONTINUITY is an issue when the "We'll be right back" shows up instead of commercials.

I mean I realize the other channels use "uplynk" while this one uses "amazonaws" but it appears to be run very similar to the other 3 channels.
@RedPenguin2 

What do you mean, this channel has been playing fine when you grab the end stream. I think you made a comment on the wrong issue.

I just wanted to know if a plugin was possible as the stream changes.



Resolving patch:
diff --git a/src/streamlink/plugins/stadium.py b/src/streamlink/plugins/stadium.py
new file mode 100644
--- /dev/null
+++ b/src/streamlink/plugins/stadium.py
@@ -0,0 +1,42 @@
+import re
+import logging
+
+from streamlink.plugin import Plugin
+from streamlink.stream import HLSStream
+from streamlink.utils import parse_json
+
+log = logging.getLogger(__name__)
+
+
+class Stadium(Plugin):
+    url_re = re.compile(r"""https?://(?:www\.)?watchstadium\.com/live""")
+    API_URL = "https://player-api.new.livestream.com/accounts/{account_id}/events/{event_id}/stream_info"
+    _stream_data_re = re.compile(r"var StadiumSiteData = (\{.*?});", re.M | re.DOTALL)
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls.url_re.match(url) is not None
+
+    def _get_streams(self):
+        res = self.session.http.get(self.url)
+        m = self._stream_data_re.search(res.text)
+        if m:
+            data = parse_json(m.group(1))
+            if data['LivestreamEnabled'] == '1':
+                account_id = data['LivestreamArgs']['account_id']
+                event_id = data['LivestreamArgs']['event_id']
+                log.debug("Found account_id={account_id} and event_id={event_id}".format(account_id=account_id, event_id=event_id))
+
+                url = self.API_URL.format(account_id=account_id, event_id=event_id)
+                api_res = self.session.http.get(url)
+                api_data = self.session.http.json(api_res)
+                stream_url = api_data.get('secure_m3u8_url') or api_data.get('m3u8_url')
+                if stream_url:
+                    return HLSStream.parse_variant_playlist(self.session, stream_url)
+                else:
+                    log.error("Could not find m3u8_url")
+            else:
+                log.error("Stream is offline")
+
+
+__plugin__ = Stadium


Test patch:
diff --git a/tests/plugins/test_stadium.py b/tests/plugins/test_stadium.py
new file mode 100644
--- /dev/null
+++ b/tests/plugins/test_stadium.py
@@ -0,0 +1,16 @@
+from streamlink.plugins.stadium import Stadium
+import unittest
+
+
+class TestPluginStadium(unittest.TestCase):
+    def test_can_handle_url(self):
+        # should match
+        self.assertTrue(Stadium.can_handle_url("http://www.watchstadium.com/live"))
+        self.assertTrue(Stadium.can_handle_url("https://www.watchstadium.com/live"))
+        self.assertTrue(Stadium.can_handle_url("https://watchstadium.com/live"))
+        self.assertTrue(Stadium.can_handle_url("http://watchstadium.com/live"))
+
+        # shouldn't match
+        self.assertFalse(Stadium.can_handle_url("http://www.watchstadium.com/anything/else"))
+        self.assertFalse(Stadium.can_handle_url("http://www.tvcatchup.com/"))
+        self.assertFalse(Stadium.can_handle_url("http://www.youtube.com/"))