nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: streamlink/streamlink
Pull request #1765 (2018-06-08 21:38:40)

plugins.rte: allow https


Patch:
diff --git a/src/streamlink/plugins/rte.py b/src/streamlink/plugins/rte.py
index 04fb9824..ec5fd13a 100644
--- a/src/streamlink/plugins/rte.py
+++ b/src/streamlink/plugins/rte.py
@@ -10,8 +10,7 @@ class RTE(Plugin):
     VOD_API_URL = 'http://www.rte.ie/rteavgen/getplaylist/?type=web&format=json&id={0}'
     LIVE_API_URL = 'http://feeds.rasset.ie/livelistings/playlist'
 
-    _url_re = re.compile(r'http://www\.rte\.ie/player/[a-z0-9]+/(?:show/[a-z-]+-[0-9]+/(?P<video_id>[0-9]+)|live/(?P<channel_id>[0-9]+))')
-
+    _url_re = re.compile(r'https?://www\.rte\.ie/player/[a-z0-9]+/(?:show/[a-z-]+-[0-9]+/(?P<video_id>[0-9]+)|live/(?P<channel_id>[0-9]+))')
     _vod_api_schema = validate.Schema({
         'current_date': validate.text,
         'shows': validate.Schema(


Test patch:
diff --git a/tests/test_plugin_rte.py b/tests/test_plugin_rte.py
index 62114a52..c134673c 100644
--- a/tests/test_plugin_rte.py
+++ b/tests/test_plugin_rte.py
@@ -10,10 +10,12 @@ class TestPluginRTE(unittest.TestCase):
         self.assertTrue(RTE.can_handle_url("http://www.rte.ie/player/99/live/10/"))
         self.assertTrue(RTE.can_handle_url("http://www.rte.ie/player/99/live/6/"))
         self.assertTrue(RTE.can_handle_url("http://www.rte.ie/player/99/live/7/"))
+        self.assertTrue(RTE.can_handle_url("https://www.rte.ie/player/de/live/7/"))
 
         self.assertTrue(RTE.can_handle_url("http://www.rte.ie/player/99/show/rte-news-one-oclock-30003248/10714679/"))
         self.assertTrue(RTE.can_handle_url("http://www.rte.ie/player/99/show/the-ray-darcy-show-extras-30003588/10714469/"))
         self.assertTrue(RTE.can_handle_url("http://www.rte.ie/player/99/show/lotto-1251/10714463/"))
+        self.assertTrue(RTE.can_handle_url("https://www.rte.ie/player/99/show/lotto-1251/10714463/"))
 
         # shouldn't match
         self.assertFalse(RTE.can_handle_url("http://www.rte.ie/"))
Repository: streamlink/streamlink
Pull request #1798 (2018-06-13 22:03:39)

plugins.tlctr: New Plugin for tlctv.com.tr/canli-izle
TV channel from Turkey

https://en.wikipedia.org/wiki/TLC_(Turkey)

Fixed https://github.com/streamlink/streamlink/issues/1516


Patch:
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index e8de3dee..e6cd82c6 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -208,6 +208,7 @@ tga                     - star.plu.cn        Yes   No
                         - star.longzhu.com
 theplatform             player.thepl... [7]_ No    Yes
 tigerdile               tigerdile.com        Yes   --
+tlctr                   tlctv.com.tr         Yes   No
 trt                     trt.net.tr           Yes   No    Some streams may be geo-restricted to Turkey.
 trtspor                 trtspor.com          Yes   No    Some streams are geo-restricted to Turkey.
 turkuvaz                - atv.com.tr         Yes   No
diff --git a/src/streamlink/plugins/tlctr.py b/src/streamlink/plugins/tlctr.py
new file mode 100644
index 00000000..c3f83ac7
--- /dev/null
+++ b/src/streamlink/plugins/tlctr.py
@@ -0,0 +1,40 @@
+import logging
+import re
+
+from streamlink.plugin import Plugin
+from streamlink.plugin.api import http
+from streamlink.plugin.api import useragents
+from streamlink.stream import HLSStream
+
+log = logging.getLogger(__name__)
+
+
+class TLCtr(Plugin):
+
+    _url_re = re.compile(r'https?://(?:www\.)?tlctv\.com\.tr/canli-izle')
+    _hls_re = re.compile(
+        r'''["'](?P<url>https?://[^/]+/live/hls/[^"']+)["']''')
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls._url_re.match(url) is not None
+
+    def _get_streams(self):
+        http.headers.update({'User-Agent': useragents.FIREFOX})
+        res = http.get(self.url)
+
+        m = self._hls_re.search(res.text)
+        if not m:
+            log.error('No playlist found.')
+            return
+
+        hls_url = m.group('url')
+        log.debug('URL={0}'.format(hls_url))
+        streams = HLSStream.parse_variant_playlist(self.session, hls_url)
+        if not streams:
+            return {'live': HLSStream(self.session, hls_url)}
+        else:
+            return streams
+
+
+__plugin__ = TLCtr


Test patch:
diff --git a/tests/test_plugin_tlctr.py b/tests/test_plugin_tlctr.py
new file mode 100644
index 00000000..50d544ef
--- /dev/null
+++ b/tests/test_plugin_tlctr.py
@@ -0,0 +1,18 @@
+import unittest
+
+from streamlink.plugins.tlctr import TLCtr
+
+
+class TestPluginTLCtr(unittest.TestCase):
+    def test_can_handle_url(self):
+        should_match = [
+            'https://www.tlctv.com.tr/canli-izle',
+        ]
+        for url in should_match:
+            self.assertTrue(TLCtr.can_handle_url(url))
+
+        should_not_match = [
+            'https://example.com/index.html',
+        ]
+        for url in should_not_match:
+            self.assertFalse(TLCtr.can_handle_url(url))
Repository: streamlink/streamlink
Pull request #2189 (2018-12-01 22:55:38)

plugins.stv: New Plugin for https://player.stv.tv/live
STV is a television channel serving Scotland.
- https://en.wikipedia.org/wiki/STV_(TV_channel)

closes https://github.com/streamlink/streamlink/issues/2038


Patch:
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index 81d3ec1d..690abea6 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -184,6 +184,7 @@ streamingvideoprovider  streamingvid... [2]_ Yes   --    RTMP streams requires r
                                                          K-S-V patches.
 streamme                stream.me            Yes   --
 streann                 ott.streann.com      Yes   Yes
+stv                     player.stv.tv        Yes   No    Streams are geo-restricted to Great Britain.
 svtplay                 - svtplay.se         Yes   Yes   Streams may be geo-restricted to Sweden.
                         - svtflow.se
                         - oppetarkiv.se
diff --git a/src/streamlink/plugins/stv.py b/src/streamlink/plugins/stv.py
new file mode 100644
index 00000000..1198b1ef
--- /dev/null
+++ b/src/streamlink/plugins/stv.py
@@ -0,0 +1,48 @@
+import logging
+import re
+
+from streamlink.exceptions import PluginError
+from streamlink.plugin import Plugin
+from streamlink.plugin.api import useragents
+from streamlink.stream import HLSStream
+
+log = logging.getLogger(__name__)
+
+
+class STV(Plugin):
+    _url_re = re.compile(r'https?://player\.stv\.tv/live')
+
+    API_URL = 'https://player.api.stv.tv/v1/streams/stv/'
+
+    title = None
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls._url_re.match(url) is not None
+
+    def get_title(self):
+        if self.title is None:
+            self._get_api_results()
+        return self.title
+
+    def _get_api_results(self):
+        self.session.http.headers.update({'User-Agent': useragents.FIREFOX})
+        res = self.session.http.get(self.API_URL)
+        data = self.session.http.json(res)
+
+        if data['success'] is False:
+            raise PluginError(data['reason']['message'])
+
+        try:
+            self.title = data['results']['now']['title']
+        except KeyError:
+            self.title = 'STV'
+
+        return data
+
+    def _get_streams(self):
+        hls_url = self._get_api_results()['results']['streamUrl']
+        return HLSStream.parse_variant_playlist(self.session, hls_url)
+
+
+__plugin__ = STV


Test patch:
diff --git a/tests/plugins/test_stv.py b/tests/plugins/test_stv.py
new file mode 100644
index 00000000..809bd2a2
--- /dev/null
+++ b/tests/plugins/test_stv.py
@@ -0,0 +1,12 @@
+import unittest
+
+from streamlink.plugins.stv import STV
+
+
+class TestPluginSTV(unittest.TestCase):
+    def test_can_handle_url(self):
+        self.assertTrue(STV.can_handle_url('https://player.stv.tv/live'))
+        self.assertTrue(STV.can_handle_url('http://player.stv.tv/live'))
+
+    def test_can_handle_url_negative(self):
+        self.assertFalse(STV.can_handle_url('http://example.com/live'))
Repository: streamlink/streamlink
Pull request #2241 (2019-01-11 18:39:30)

plugins.trt: Added support for https url, fixed logger error
Fixed https://github.com/streamlink/streamlink/issues/2214


Patch:
diff --git a/src/streamlink/plugins/trt.py b/src/streamlink/plugins/trt.py
index bca9b992..6b274a04 100644
--- a/src/streamlink/plugins/trt.py
+++ b/src/streamlink/plugins/trt.py
@@ -1,19 +1,20 @@
-from __future__ import print_function
+import logging
 import re
+
 from base64 import b64decode
 
+from streamlink.compat import parse_qsl, urlparse
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import validate
-from streamlink.compat import urlparse, parse_qsl
-from streamlink.stream import HDSStream
-from streamlink.stream import HLSStream
+from streamlink.stream import HDSStream, HLSStream
+
+log = logging.getLogger(__name__)
 
 
 class TRT(Plugin):
     """
     Support for the live TV streams on http://www.trt.net.tr/, some streams may be geo-locked
     """
-    url_re = re.compile(r"http://www.trt.net.tr/anasayfa/canli.aspx.*", re.I)
+    url_re = re.compile(r"https?://www\.trt\.net\.tr/anasayfa/canli\.aspx.*", re.I)
     stream_data_re = re.compile(r'<script>eval\(dcm1\("(.*?)"\)\);')
     f4mm_re = re.compile(r'''(?P<q>["'])(?P<url>http[^"']+?.f4m)(?P=q);''')
     m3u8_re = re.compile(r'''(?P<q>["'])(?P<url>http[^"']+?.m3u8)(?P=q);''')
@@ -27,7 +28,7 @@ class TRT(Plugin):
     def _get_streams(self):
         args = dict(parse_qsl(urlparse(self.url).query))
         if "k" in args:
-            self.logger.debug("Loading channel: {k}", **args)
+            log.debug("Loading channel: {0}".format(args["k"]))
             res = self.session.http.get(self.url)
             stream_data_m = self.stream_data_re.search(res.text)
             if stream_data_m:


Test patch:
diff --git a/tests/plugins/test_trt.py b/tests/plugins/test_trt.py
index c79d2923..ab16c975 100644
--- a/tests/plugins/test_trt.py
+++ b/tests/plugins/test_trt.py
@@ -7,6 +7,7 @@ class TestPluginTRT(unittest.TestCase):
     def test_can_handle_url(self):
         should_match = [
             'http://www.trt.net.tr/anasayfa/canli.aspx?y=tv&k=trt1',
+            'https://www.trt.net.tr/anasayfa/canli.aspx?y=tv&k=trtworld',
         ]
         for url in should_match:
             self.assertTrue(TRT.can_handle_url(url))
@@ -14,6 +15,7 @@ class TestPluginTRT(unittest.TestCase):
     def test_can_handle_url_negative(self):
         should_not_match = [
             'https://example.com/index.html',
+            'https://trt.net.tr/anasayfa/canli.aspx?y=tv&k=trtworld',
         ]
         for url in should_not_match:
             self.assertFalse(TRT.can_handle_url(url))
Repository: streamlink/streamlink
Pull request #2362 (2019-03-18 16:41:21)

plugins.cdnbg: New domain videochanel.bstv.bg
closes https://github.com/streamlink/streamlink/issues/2343


Patch:
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index 6dd3bdde..d7647bfe 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -40,6 +40,7 @@ cdnbg                   - tv.bnt.bg          Yes   No    Streams may be geo-rest
                         - bgonair.bg
                         - bitelevision.com
                         - bloombergtv.bg
+                        - bstv.bg
                         - inlife.bg
                         - kanal3.bg
                         - mmtvmusic.com
diff --git a/src/streamlink/plugins/cdnbg.py b/src/streamlink/plugins/cdnbg.py
index dfb5591d..79b0172b 100644
--- a/src/streamlink/plugins/cdnbg.py
+++ b/src/streamlink/plugins/cdnbg.py
@@ -22,6 +22,7 @@ class CDNBG(Plugin):
             inlife\.bg|
             mmtvmusic\.com/live|
             mu-vi\.tv/LiveStreams/pages/Live\.aspx|
+            videochanel\.bstv\.bg|
             bloombergtv.bg/video
         )/?
     """, re.VERBOSE)


Test patch:
diff --git a/tests/plugins/test_cdnbg.py b/tests/plugins/test_cdnbg.py
index 7b6026a6..b98b16ee 100644
--- a/tests/plugins/test_cdnbg.py
+++ b/tests/plugins/test_cdnbg.py
@@ -22,6 +22,7 @@ class TestPluginCDNBG(unittest.TestCase):
         self.assertTrue(CDNBG.can_handle_url("http://inlife.bg/"))
         self.assertTrue(CDNBG.can_handle_url("https://mmtvmusic.com/live/"))
         self.assertTrue(CDNBG.can_handle_url("http://mu-vi.tv/LiveStreams/pages/Live.aspx"))
+        self.assertTrue(CDNBG.can_handle_url("http://videochanel.bstv.bg/"))
         self.assertTrue(CDNBG.can_handle_url("https://www.bloombergtv.bg/video"))
 
         # shouldn't match
Repository: streamlink/streamlink
Pull request #2560 (2019-07-23 10:14:41)

plugins.gulli: HTTPS support + fix live stream fetching
This PR enables HTTPS support for the Gulli plugin. It also fixes live stream fetching:

```
$ streamlink http://replay.gulli.fr/Direct
[cli][info] Found matching plugin gulli for URL http://replay.gulli.fr/Direct
error: Unable to parse JSON: Expecting property name enclosed in double quotes: line 4 column 21 (char 242) ('[\n                {\n             ...)
```


Patch:
diff --git a/src/streamlink/plugins/gulli.py b/src/streamlink/plugins/gulli.py
index f77dbf0a..da8cc4cb 100644
--- a/src/streamlink/plugins/gulli.py
+++ b/src/streamlink/plugins/gulli.py
@@ -7,17 +7,18 @@ from streamlink.utils import parse_json
 
 
 class Gulli(Plugin):
-    LIVE_PLAYER_URL = 'http://replay.gulli.fr/jwplayer/embedstreamtv'
-    VOD_PLAYER_URL = 'http://replay.gulli.fr/jwplayer/embed/{0}'
+    LIVE_PLAYER_URL = 'https://replay.gulli.fr/jwplayer/embedstreamtv'
+    VOD_PLAYER_URL = 'https://replay.gulli.fr/jwplayer/embed/{0}'
 
-    _url_re = re.compile(r'http://replay\.gulli\.fr/(?:Direct|.+/(?P<video_id>VOD[0-9]+))')
+    _url_re = re.compile(r'https?://replay\.gulli\.fr/(?:Direct|.+/(?P<video_id>VOD[0-9]+))')
     _playlist_re = re.compile(r'sources: (\[.+?\])', re.DOTALL)
     _vod_video_index_re = re.compile(r'jwplayer\(idplayer\).playlistItem\((?P<video_index>[0-9]+)\)')
     _mp4_bitrate_re = re.compile(r'.*_(?P<bitrate>[0-9]+)\.mp4')
 
     _video_schema = validate.Schema(
         validate.all(
-            validate.transform(lambda x: re.sub(r'"?file"?:\s*[\'"](.+?)[\'"]', r'"file": "\1"', x, flags=re.DOTALL)),
+            validate.transform(lambda x: re.sub(r'"?file"?:\s*[\'"](.+?)[\'"],?', r'"file": "\1"', x, flags=re.DOTALL)),
+            validate.transform(lambda x: re.sub(r'"?\w+?"?:\s*function\b.*?(?<={).*(?=})', "", x, flags=re.DOTALL)),
             validate.transform(parse_json),
             [
                 validate.Schema({


Test patch:
diff --git a/tests/plugins/test_gulli.py b/tests/plugins/test_gulli.py
index 21cb0837..7435ea00 100644
--- a/tests/plugins/test_gulli.py
+++ b/tests/plugins/test_gulli.py
@@ -8,8 +8,8 @@ class TestPluginGulli(unittest.TestCase):
         # should match
         self.assertTrue(Gulli.can_handle_url("http://replay.gulli.fr/Direct"))
         self.assertTrue(Gulli.can_handle_url("http://replay.gulli.fr/dessins-animes/My-Little-Pony-les-amies-c-est-magique/VOD68328764799000"))
-        self.assertTrue(Gulli.can_handle_url("http://replay.gulli.fr/emissions/In-Ze-Boite2/VOD68639028668000"))
-        self.assertTrue(Gulli.can_handle_url("http://replay.gulli.fr/series/Power-Rangers-Dino-Super-Charge/VOD68612908435000"))
+        self.assertTrue(Gulli.can_handle_url("https://replay.gulli.fr/emissions/In-Ze-Boite2/VOD68639028668000"))
+        self.assertTrue(Gulli.can_handle_url("https://replay.gulli.fr/series/Power-Rangers-Dino-Super-Charge/VOD68612908435000"))
 
         # shouldn't match
         self.assertFalse(Gulli.can_handle_url("http://replay.gulli.fr/"))
Repository: streamlink/streamlink
Pull request #2561 (2019-07-24 12:50:58)

plugins.tvrplus: fix for new website layout
Fixes the plugin after website layout change:
```
$ streamlink https://www.tvrplus.ro/live/tvr-international
error: No plugin can handle URL: https://www.tvrplus.ro/live/tvr-international
```



Patch:
diff --git a/src/streamlink/plugins/tvrplus.py b/src/streamlink/plugins/tvrplus.py
index 52e400fd..6d188d22 100644
--- a/src/streamlink/plugins/tvrplus.py
+++ b/src/streamlink/plugins/tvrplus.py
@@ -7,7 +7,7 @@ from streamlink.stream import HLSStream
 
 
 class TVRPlus(Plugin):
-    url_re = re.compile(r"https?://(?:www\.)?tvrplus\.ro/live-")
+    url_re = re.compile(r"https?://(?:www\.)?tvrplus\.ro/live/")
     hls_file_re = re.compile(r"""["'](?P<url>[^"']+\.m3u8(?:[^"']+)?)["']""")
 
     stream_schema = validate.Schema(


Test patch:
diff --git a/tests/plugins/test_tvrplus.py b/tests/plugins/test_tvrplus.py
index 8be192a4..84470b3b 100644
--- a/tests/plugins/test_tvrplus.py
+++ b/tests/plugins/test_tvrplus.py
@@ -6,10 +6,10 @@ from streamlink.plugins.tvrplus import TVRPlus
 class TestPluginTVRPlus(unittest.TestCase):
     def test_can_handle_url(self):
         should_match = [
-            "http://tvrplus.ro/live-tvr-1",
-            "http://www.tvrplus.ro/live-tvr-1",
-            "http://www.tvrplus.ro/live-tvr-3",
-            "http://www.tvrplus.ro/live-tvr-international",
+            "http://tvrplus.ro/live/tvr-1",
+            "http://www.tvrplus.ro/live/tvr-1",
+            "http://www.tvrplus.ro/live/tvr-3",
+            "http://www.tvrplus.ro/live/tvr-international",
         ]
         for url in should_match:
             self.assertTrue(TVRPlus.can_handle_url(url))
Repository: streamlink/streamlink
Pull request #2657 (2019-10-08 09:08:37)

plugins.idf1: HTTPS support
This PR enables HTTPS support for the IDF1 plugin.


Patch:
diff --git a/src/streamlink/plugins/idf1.py b/src/streamlink/plugins/idf1.py
index 0a083391..b3220b4a 100644
--- a/src/streamlink/plugins/idf1.py
+++ b/src/streamlink/plugins/idf1.py
@@ -11,7 +11,7 @@ class IDF1(Plugin):
     DACAST_API_URL = 'https://json.dacast.com/b/{}/{}/{}'
     DACAST_TOKEN_URL = 'https://services.dacast.com/token/i/b/{}/{}/{}'
 
-    _url_re = re.compile(r'http://www\.idf1\.fr/(videos/[^/]+/[^/]+\.html|live\b)')
+    _url_re = re.compile(r'https?://www\.idf1\.fr/(videos/[^/]+/[^/]+\.html|live\b)')
     _video_id_re = re.compile(r"dacast\('(?P<broadcaster_id>\d+)_(?P<video_type>[a-z]+)_(?P<video_id>\d+)', 'replay_content', data\);")
     _video_id_alt_re = re.compile(r'<script src="https://player.dacast.com/js/player.js" id="(?P<broadcaster_id>\d+)_(?P<video_type>[cf])_(?P<video_id>\d+)"')
     _player_url = 'http://ssl.p.jwpcdn.com/player/v/7.12.6/jwplayer.flash.swf'


Test patch:
diff --git a/tests/plugins/test_idf1.py b/tests/plugins/test_idf1.py
index 5b753494..737995a1 100644
--- a/tests/plugins/test_idf1.py
+++ b/tests/plugins/test_idf1.py
@@ -6,13 +6,13 @@ from streamlink.plugins.idf1 import IDF1
 class TestPluginIDF1(unittest.TestCase):
     def test_can_handle_url(self):
         # should match
-        self.assertTrue(IDF1.can_handle_url("http://www.idf1.fr/live"))
-        self.assertTrue(IDF1.can_handle_url("http://www.idf1.fr/videos/jlpp/best-of-2018-02-24-partie-2.html"))
+        self.assertTrue(IDF1.can_handle_url("https://www.idf1.fr/live"))
+        self.assertTrue(IDF1.can_handle_url("https://www.idf1.fr/videos/jlpp/best-of-2018-02-24-partie-2.html"))
         self.assertTrue(IDF1.can_handle_url("http://www.idf1.fr/videos/buzz-de-noel/partie-2.html"))
 
         # shouldn't match
-        self.assertFalse(IDF1.can_handle_url("http://www.idf1.fr/"))
-        self.assertFalse(IDF1.can_handle_url("http://www.idf1.fr/videos"))
-        self.assertFalse(IDF1.can_handle_url("http://www.idf1.fr/programmes/emissions/idf1-chez-vous.html"))
+        self.assertFalse(IDF1.can_handle_url("https://www.idf1.fr/"))
+        self.assertFalse(IDF1.can_handle_url("https://www.idf1.fr/videos"))
+        self.assertFalse(IDF1.can_handle_url("https://www.idf1.fr/programmes/emissions/idf1-chez-vous.html"))
         self.assertFalse(IDF1.can_handle_url("http://www.tvcatchup.com/"))
         self.assertFalse(IDF1.can_handle_url("http://www.youtube.com/"))
Repository: streamlink/streamlink
Pull request #2742 (2019-12-15 10:00:35)

plugins.ustream: Added support for video.ibm.com


Patch:
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index 1423894b..7f02e8a1 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -246,7 +246,8 @@ tvtoya                  tvtoya.pl            Yes   --
 twitcasting             twitcasting.tv       Yes   No
 twitch                  twitch.tv            Yes   Yes   Possible to authenticate for access to
                                                          subscription streams.
-ustreamtv               ustream.tv           Yes   Yes
+ustreamtv               - ustream.tv         Yes   Yes
+                        - video.ibm.com
 ustvnow                 ustvnow.com          Yes   --    All streams require an account, some streams require a subscription.
 vaughnlive              - vaughnlive.tv      Yes   --
                         - breakers.tv
diff --git a/src/streamlink/plugins/ustreamtv.py b/src/streamlink/plugins/ustreamtv.py
index 88fd84a1..c5a87275 100644
--- a/src/streamlink/plugins/ustreamtv.py
+++ b/src/streamlink/plugins/ustreamtv.py
@@ -359,7 +359,7 @@ class UHSStream(Stream):
 
 class UStreamTV(Plugin):
     url_re = re.compile(r"""(?x)
-    https?://(www\.)?ustream\.tv
+    https?://(?:(www\.)?ustream\.tv|video\.ibm\.com)
         (?:
             (/embed/|/channel/id/)(?P<channel_id>\d+)
         )?


Test patch:
diff --git a/tests/plugins/test_ustreamtv.py b/tests/plugins/test_ustreamtv.py
index 36f0a039..e286bb96 100644
--- a/tests/plugins/test_ustreamtv.py
+++ b/tests/plugins/test_ustreamtv.py
@@ -3,9 +3,9 @@ import unittest
 from streamlink import Streamlink
 
 try:
-    from unittest.mock import ANY, MagicMock, call
+    from unittest.mock import ANY, MagicMock
 except ImportError:
-    from mock import ANY, MagicMock, call
+    from mock import ANY, MagicMock
 from streamlink.plugins.ustreamtv import UStreamTV
 
 
@@ -17,10 +17,13 @@ class TestPluginUStreamTV(unittest.TestCase):
             "http://www.ustream.tv/embed/1234",
             "http://www.ustream.tv/recorded/6543",
             "http://www.ustream.tv/embed/recorded/6543",
+            "https://video.ibm.com/channel/H5rQLwmTGrW",
+            "https://video.ibm.com/recorded/124680279",
         ]
         for url in should_match:
             self.assertTrue(UStreamTV.can_handle_url(url))
 
+    def test_can_handle_url_negative(self):
         should_not_match = [
             "https://www.youtube.com/v/aqz-KE-bpKQ",
         ]