Repository: streamlink/streamlink
Pull request #1596 (2018-04-10 14:47:29)

[TVP] New Plugin for Telewizja Polska S.A.
> Telewizja Polska S.A. (TVP S.A., or Polish Television) is a public broadcasting corporation,
> the only public TV broadcaster in the territory of the Republic of Poland.
> https://en.wikipedia.org/wiki/Telewizja_Polska

http://tvpstream.vod.tvp.pl
http://tvpstream.vod.tvp.pl/?channel_id=1455

```
[cli][info] Found matching plugin tvp for URL
http://tvpstream.vod.tvp.pl/?channel_id=1455
[cli][info] Available streams: none_101k, 288p_228k (worst), 288p_578k,
288p_1119k, 288p_1797k, 576p_2433k, 576p_3811k (best)
[cli][info] Opening stream: 576p_3811k (hls)
```

closes https://github.com/streamlink/streamlink/issues/1590

---

ping @remek30


Patch:
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index b5eec16a..dd5974a0 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -225,6 +225,7 @@ tv360               tv360.com.tr         Yes   No
 tvcatchup           tvcatchup.com        Yes   No    Streams may be geo-restricted to Great Britain.
 tvnbg               - tvn.bg             Yes   -
                     - live.tvn.bg
+tvp                 tvpstream.vod.tvp.pl Yes   No    Streams may be geo-restricted to Poland.
 tvplayer            tvplayer.com         Yes   No    Streams may be geo-restricted to Great Britain. Premium streams are not supported.
 tvrby               tvr.by               Yes   No    Streams may be geo-restricted to Belarus.
 tvrplus             tvrplus.ro           Yes   No    Streams may be geo-restricted to Romania.
diff --git a/src/streamlink/plugins/tvp.py b/src/streamlink/plugins/tvp.py
new file mode 100644
index 00000000..557feffa
--- /dev/null
+++ b/src/streamlink/plugins/tvp.py
@@ -0,0 +1,59 @@
+import re
+
+from streamlink.exceptions import PluginError
+from streamlink.plugin import Plugin
+from streamlink.plugin.api import http
+from streamlink.plugin.api import useragents
+from streamlink.stream import HLSStream
+from streamlink.stream import HTTPStream
+
+
+class TVP(Plugin):
+    '''Telewizja Polska S.A.
+       http://tvpstream.vod.tvp.pl
+    '''
+
+    player_url = 'https://www.tvp.pl/sess/tvplayer.php?object_id={0}&autoplay=true'
+
+    _url_re = re.compile(r'https?://tvpstream\.vod\.tvp\.pl')
+    _stream_re = re.compile(r'''src:["'](?P<url>[^"']+\.(?:m3u8|mp4))["']''')
+    _video_id_re = re.compile(r'''class=["']tvp_player["'][^>]+data-video-id=["'](?P<video_id>\d+)["']''')
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls._url_re.match(url) is not None
+
+    def get_embed_url(self):
+        res = http.get(self.url)
+
+        m = self._video_id_re.search(res.text)
+        if not m:
+            raise PluginError('Unable to find a video id')
+
+        video_id = m.group('video_id')
+        self.logger.debug('Found video id: {0}'.format(video_id))
+        p_url = self.player_url.format(video_id)
+        return p_url
+
+    def _get_streams(self):
+        http.headers.update({'User-Agent': useragents.FIREFOX})
+
+        embed_url = self.get_embed_url()
+        res = http.get(embed_url)
+        m = self._stream_re.findall(res.text)
+        if not m:
+            raise PluginError('Unable to find a stream url')
+
+        streams = []
+        for url in m:
+            self.logger.debug('URL={0}'.format(url))
+            if url.endswith('.m3u8'):
+                for s in HLSStream.parse_variant_playlist(self.session, url, name_fmt='{pixels}_{bitrate}').items():
+                    streams.append(s)
+            elif url.endswith('.mp4'):
+                streams.append(('vod', HTTPStream(self.session, url)))
+
+        return streams
+
+
+__plugin__ = TVP


Test patch:
diff --git a/tests/test_plugin_tvp.py b/tests/test_plugin_tvp.py
new file mode 100644
index 00000000..09b45107
--- /dev/null
+++ b/tests/test_plugin_tvp.py
@@ -0,0 +1,20 @@
+import unittest
+
+from streamlink.plugins.tvp import TVP
+
+
+class TestPluginTVP(unittest.TestCase):
+    def test_can_handle_url(self):
+        should_match = [
+            'http://tvpstream.vod.tvp.pl/?channel_id=14327511',
+            'http://tvpstream.vod.tvp.pl/?channel_id=1455',
+        ]
+        for url in should_match:
+            self.assertTrue(TVP.can_handle_url(url))
+
+        should_not_match = [
+            'http://tvp.pl/',
+            'http://vod.tvp.pl/',
+        ]
+        for url in should_not_match:
+            self.assertFalse(TVP.can_handle_url(url))