Repository: streamlink/streamlink

Issue:
sportschau: Does not work with the newly introduced bundesliga livestreams (Konferenz)
### Checklist

- [X] This is a plugin issue and not a different kind of issue
- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)
- [X] [I have checked the list of open and recently closed plugin issues](https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+issue%22)
- [X] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)

### Streamlink version

Latest stable release

### Description

Does not work with the newly introduced bundesliga livestreams (Konferenz).

e.g. https://www.sportschau.de/fussball/bundesliga/audiostream-die-konferenz---bundesliga-live-100.html

Neither under windows nor linux. The linux version (Mint 19) was installed with apt-get, maybe is an older version.
Windows version is actual.



### Debug log

```text
Windows:

c:\Users\deiss\Downloads\streamlink>streamlink  https://www.sportschau.de/fussball/bundesliga/audiostream-die-konferenz---bundesliga-live-100.html   "best"  --loglevel debug
[cli][debug] OS:         Windows 10
[cli][debug] Python:     3.7.9
[cli][debug] Streamlink: 2.1.2
[cli][debug] Requests(2.25.1), Socks(1.7.1), Websocket(1.0.0)
[cli][debug] Arguments:
[cli][debug]  url=https://www.sportschau.de/fussball/bundesliga/audiostream-die-konferenz---bundesliga-live-100.html
[cli][debug]  stream=['best']
[cli][debug]  --config=['c:\\Users\\deiss\\Downloads\\streamlink\\\\streamlinkrc']
[cli][debug]  --loglevel=debug
[cli][debug]  --rtmp-rtmpdump=c:\Users\deiss\Downloads\streamlink\\rtmpdump\rtmpdump.exe
[cli][debug]  --ffmpeg-ffmpeg=c:\Users\deiss\Downloads\streamlink\\ffmpeg\ffmpeg.exe
[cli][info] Found matching plugin sportschau for URL https://www.sportschau.de/fussball/bundesliga/audiostream-die-konferenz---bundesliga-live-100.html
[plugins.sportschau][debug] Found player js https://deviceids-medp.wdr.de/ondemand/247/2477304.js
[utils.l10n][debug] Language code: de_DE
error: Unable to open URL: https://b'' (HTTPSConnectionPool(host="b''", port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000001BAE8276108>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')))


Linux:

streamlink  https://www.sportschau.de/fussball/bundesliga/audiostream-die-konferenz---bundesliga-live-100.html   "best"  --loglevel debug
[cli][info] Found matching plugin sportschau for URL https://www.sportschau.de/fussball/bundesliga/audiostream-die-konferenz---bundesliga-live-100.html
[plugin.sportschau][info] Found player js http://deviceids-medp.wdr.de/ondemand/247/2477304.js
Traceback (most recent call last):
  File "/usr/bin/streamlink", line 11, in <module>
    load_entry_point('streamlink==0.10.0', 'console_scripts', 'streamlink')()
  File "/usr/share/streamlink/streamlink_cli/main.py", line 1055, in main
    handle_url()
  File "/usr/share/streamlink/streamlink_cli/main.py", line 486, in handle_url
    streams = fetch_streams(plugin)
  File "/usr/share/streamlink/streamlink_cli/main.py", line 398, in fetch_streams
    sorting_excludes=args.stream_sorting_excludes)
  File "/usr/lib/python3/dist-packages/streamlink/plugin/plugin.py", line 385, in get_streams
    return self.streams(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/streamlink/plugin/plugin.py", line 288, in streams
    ostreams = self._get_streams()
  File "/usr/lib/python3/dist-packages/streamlink/plugins/sportschau.py", line 40, in _get_streams
    return HDSStream.parse_manifest(self.session, stream_metadata['mediaResource']['dflt']['videoURL']).items()
KeyError: 'videoURL'
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 145, in apport_excepthook
    os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o640), 'wb') as f:
FileNotFoundError: [Errno 2] No such file or directory: '/var/crash/_usr_share_streamlink_streamlink.1000.crash'

Original exception was:
Traceback (most recent call last):
  File "/usr/bin/streamlink", line 11, in <module>
    load_entry_point('streamlink==0.10.0', 'console_scripts', 'streamlink')()
  File "/usr/share/streamlink/streamlink_cli/main.py", line 1055, in main
    handle_url()
```



Discussion:
Both of your Streamlink versions are out of date. That's not the problem here though.

The plugin's validation schema is expecting a `videoURL` property in the JSONP data. The URL you've posted however is not a video stream and it only includes an `audioURL` property instead.

Resolving patch:
diff --git a/src/streamlink/plugins/sportschau.py b/src/streamlink/plugins/sportschau.py
--- a/src/streamlink/plugins/sportschau.py
+++ b/src/streamlink/plugins/sportschau.py
@@ -3,7 +3,7 @@
 
 from streamlink.plugin import Plugin, pluginmatcher
 from streamlink.plugin.api import validate
-from streamlink.stream import HLSStream
+from streamlink.stream import HLSStream, HTTPStream
 from streamlink.utils import parse_json, update_scheme
 
 log = logging.getLogger(__name__)
@@ -16,33 +16,34 @@ class Sportschau(Plugin):
     _re_player = re.compile(r"https?:(//deviceids-medp.wdr.de/ondemand/\S+\.js)")
     _re_json = re.compile(r"\$mediaObject.jsonpHelper.storeAndPlay\(({.+})\);?")
 
-    _schema_player = validate.Schema(
-        validate.transform(_re_player.search),
-        validate.any(None, validate.Schema(
-            validate.get(1),
-            validate.transform(lambda url: update_scheme("https:", url))
-        ))
-    )
-    _schema_json = validate.Schema(
-        validate.transform(_re_json.match),
-        validate.get(1),
-        validate.transform(parse_json),
-        validate.get("mediaResource"),
-        validate.get("dflt"),
-        validate.get("videoURL"),
-        validate.transform(lambda url: update_scheme("https:", url))
-    )
-
     def _get_streams(self):
-        player_js = self.session.http.get(self.url, schema=self._schema_player)
+        player_js = self.session.http.get(self.url, schema=validate.Schema(
+            validate.transform(self._re_player.search),
+            validate.any(None, validate.Schema(
+                validate.get(1),
+                validate.transform(lambda url: update_scheme("https:", url))
+            ))
+        ))
         if not player_js:
             return
 
-        log.debug("Found player js {0}".format(player_js))
-
-        hls_url = self.session.http.get(player_js, schema=self._schema_json)
+        log.debug(f"Found player js {player_js}")
+        data = self.session.http.get(player_js, schema=validate.Schema(
+            validate.transform(self._re_json.match),
+            validate.get(1),
+            validate.transform(parse_json),
+            validate.get("mediaResource"),
+            validate.get("dflt"),
+            {
+                validate.optional("audioURL"): validate.url(),
+                validate.optional("videoURL"): validate.url()
+            }
+        ))
 
-        yield from HLSStream.parse_variant_playlist(self.session, hls_url).items()
+        if data.get("videoURL"):
+            yield from HLSStream.parse_variant_playlist(self.session, update_scheme("https:", data.get("videoURL"))).items()
+        if data.get("audioURL"):
+            yield "audio", HTTPStream(self.session, update_scheme("https:", data.get("audioURL")))
 
 
 __plugin__ = Sportschau


Test patch: