Thanks to visit codestin.com
Credit goes to github.com

Skip to content

plugins.sportschau: fix sportschau#6104

Merged
bastimeyer merged 6 commits into
streamlink:masterfrom
gsilvan:fix-sportschau
Aug 2, 2024
Merged

plugins.sportschau: fix sportschau#6104
bastimeyer merged 6 commits into
streamlink:masterfrom
gsilvan:fix-sportschau

Conversation

@gsilvan

@gsilvan gsilvan commented Aug 1, 2024

Copy link
Copy Markdown
Contributor

The current plugin for sportschau.de is not working.

Example: https://www.sportschau.de/olympia/sportschiessen-luftpistole-10m-mixed-im-re-live,video-olympia-sportschiessen-104.html

streamlink https://www.sportschau.de/olympia/sportschiessen-luftpistole-10m-mixed-im-re-live,video-olympia-sportschiessen-104.html
[cli][info] Found matching plugin sportschau for URL https://www.sportschau.de/olympia/sportschiessen-luftpistole-10m-mixed-im-re-live,video-olympia-sportschiessen-104.html
error: No playable streams found on this URL: https://www.sportschau.de/olympia/sportschiessen-luftpistole-10m-mixed-im-re-live,video-olympia-sportschiessen-104.html

This PR fixes it.

@bastimeyer bastimeyer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, but I'm afraid the plugin can't be (fully) fixed right now. Not because of the data extraction, but because of the HLS streams, which include packed audio streams, which is still unsupported by Streamlink. ARD Mediathek for example suffers from the same issue. See #4721.

The only workaround right now is using the --stream-url option without selecting a specific stream, so that the HLS multivariant playlist URL is returned, which can then be used as the player's launch argument, if the player does support HLS playlist inputs. --player-passthrough=hls does not work with multivariant playlist (which I just noticed).

mpv "$(streamlink sportschau.de --stream-url)"

Apart from that, there's some room for improvements here. The validation schema is not validating anything, which it really should, or else ugly errors will be raised by the plugin when there's an issue with the expected data, and metadata is also missing. The HTTPStream VODs are also unneeded, as the same content is always available via HLS (without packed audio streams).

The following diff would fix that (I don't want to add multiple review comments for this, because it's unnecessarily confusing and a waste of time):

diff --git a/src/streamlink/plugins/sportschau.py b/src/streamlink/plugins/sportschau.py
index fce34ac7..9eb124a8 100644
--- a/src/streamlink/plugins/sportschau.py
+++ b/src/streamlink/plugins/sportschau.py
@@ -1,7 +1,9 @@
 """
-$description German sports magazine live stream, owned by ARD.
+$description German sports magazine live streams and VOD content, owned by ARD.
 $url sportschau.de
 $type live
+$metadata id
+$metadata title
 """
 
 import logging
@@ -10,38 +12,65 @@ import re
 from streamlink.plugin import Plugin, pluginmatcher
 from streamlink.plugin.api import validate
 from streamlink.stream.hls import HLSStream
-from streamlink.stream.http import HTTPStream
+
 
 log = logging.getLogger(__name__)
 
 
-@pluginmatcher(
-    re.compile(
-        r"https?://(?:\w+\.)*sportschau\.de/",
-    )
-)
+@pluginmatcher(re.compile(r"https?://(?:\w+\.)*sportschau\.de/"))
 class Sportschau(Plugin):
-    def _get_streams(self):
-        streams = self.session.http.get(
-            self.url,
-            schema=validate.Schema(
-                validate.parse_html(),
-                validate.xml_xpath_string("(//*[@data-v-type='MediaPlayer'])[1]/@data-v"),
-                validate.parse_json(),
-                validate.get("mc"),
-                validate.get("streams"),
+    _schema_media = validate.Schema(
+        validate.parse_html(),
+        validate.xml_xpath_string(".//*[@data-v-type='MediaPlayer'][@data-v][1]/@data-v"),
+        validate.none_or_all(
+            validate.parse_json(),
+            {
+                "mc": {
+                    validate.optional("id"): str,
+                    "meta": {
+                        "title": str,
+                    },
+                    "streams": [
+                        validate.all(
+                            {
+                                "media": [
+                                    validate.all(
+                                        {
+                                            "mimeType": str,
+                                            "url": validate.url(),
+                                        },
+                                        validate.union_get(
+                                            "mimeType",
+                                            "url",
+                                        ),
+                                    ),
+                                ],
+                            },
+                            validate.get("media"),
+                        ),
+                    ],
+                },
+            },
+            validate.get("mc"),
+            validate.union_get(
+                "id",
+                ("meta", "title"),
+                "streams",
             ),
-        )
-        for stream in streams:
-            for media in stream.get("media"):
-                url = media.get("url")
-                is_hls = media.get("mimeType") == "application/vnd.apple.mpegurl"
-                is_audio_only = stream.get("isAudioOnly")
-                if is_hls:
+        ),
+    )
+
+    def _get_streams(self):
+        data = self.session.http.get(self.url, schema=self._schema_media)
+        if not data:
+            return
+
+        self.id, self.title, streams = data
+
+        for media in streams:
+            for mime_type, url in media:
+                if mime_type == "application/vnd.apple.mpegurl":
                     yield from HLSStream.parse_variant_playlist(self.session, url).items()
-                else:
-                    media_type = "audio" if is_audio_only else "video"
-                    yield media_type, HTTPStream(self.session, url)
 
 
 __plugin__ = Sportschau
diff --git a/tests/plugins/test_sportschau.py b/tests/plugins/test_sportschau.py
index 235159e5..dcbcaa6b 100644
--- a/tests/plugins/test_sportschau.py
+++ b/tests/plugins/test_sportschau.py
@@ -6,6 +6,6 @@ class TestPluginCanHandleUrlSportschau(PluginCanHandleUrl):
     __plugin__ = Sportschau
 
     should_match = [
-        "http://www.sportschau.de/wintersport/videostream-livestream---wintersport-im-ersten-242.html",
-        "https://www.sportschau.de/weitere/allgemein/video-kite-surf-world-tour-100.html",
+        "https://www.sportschau.de/fussball/uefa-euro-2024/spaniens-europameister-begeistert-empfangen,em-spanien-feier-100.html",
+        "https://www.sportschau.de/olympia/live/schwimmen-finals-m-f,livestream-olympia-schwimmen-110.html",
     ]
$ ./script/test-plugin-urls.py sportschau -m
:: https://www.sportschau.de/fussball/uefa-euro-2024/spaniens-europameister-begeistert-empfangen,em-spanien-feier-100.html
::  270p, 360p, 540p, 720p, 1080p, worst, best
::   {'id': None, 'author': None, 'category': None, 'title': 'Nach Finalsieg in Berlin: Spaniens Europameister werden empfangen'}
:: https://www.sportschau.de/olympia/live/schwimmen-finals-m-f,livestream-olympia-schwimmen-110.html
::  270p, 360p, 540p, 720p, 1080p, worst, best
::   {'id': 'paris-2024-ecms-epg-1940-livestream', 'author': None, 'category': None, 'title': 'Olympia live - Schwimmen: Finals (M, F)'}

@bastimeyer bastimeyer added plugin issue A Plugin does not work correctly stream: HLS labels Aug 1, 2024
@gsilvan

gsilvan commented Aug 1, 2024

Copy link
Copy Markdown
Contributor Author

Thanks for your review!

Applied your patch, but i left the HTTPStream in for the sake of audio-on-demand and icecast-live.

Examples:

Couldn't find a HLS for those yet. Any thoughts on that?

Comment thread src/streamlink/plugins/sportschau.py Outdated
Comment thread tests/plugins/test_sportschau.py
@bastimeyer

Copy link
Copy Markdown
Member

Thanks. Should be fine now. Well, apart from the HLS packed audio situation of course which will require the --stream-url workaround.

$ ./script/test-plugin-urls.py sportschau -m
:: https://www.sportschau.de/fussball/uefa-euro-2024/spaniens-europameister-begeistert-empfangen,em-spanien-feier-100.html
::  270p, 360p, 540p, 720p, 1080p, worst, best
::   {'id': None, 'author': None, 'category': None, 'title': 'Nach Finalsieg in Berlin: Spaniens Europameister werden empfangen'}
:: https://www.sportschau.de/olympia/live/schwimmen-finals-m-f,livestream-olympia-schwimmen-110.html
::  270p, 360p, 540p, 720p, 1080p, worst, best
::   {'id': None, 'author': None, 'category': None, 'title': 'Olympia 2024 - Schwimmen: Finals (M, F) im Re-Live'}
:: https://www.sportschau.de/podcasts/sportschau-olympia-podcast/tag-6-vier-gewinnt,audio-tag-6-vier-gewinnt-100.html
::  audio, worst, best
::   {'id': None, 'author': None, 'category': None, 'title': 'Der Sportschau-Olympia-Podcast: Tag 6 - Vier gewinnt'}

For the record, pages without media content are also working correctly:

$ streamlink https://www.sportschau.de/olympia/kroppen-unruh-kaempfen-sich-ins-viertelfinale,olympia-paris-bogenschiessen-mixed-team-100.html
[cli][info] Found matching plugin sportschau for URL https://www.sportschau.de/olympia/kroppen-unruh-kaempfen-sich-ins-viertelfinale,olympia-paris-bogenschiessen-mixed-team-100.html
error: No playable streams found on this URL: https://www.sportschau.de/olympia/kroppen-unruh-kaempfen-sich-ins-viertelfinale,olympia-paris-bogenschiessen-mixed-team-100.html

@bastimeyer bastimeyer merged commit e502494 into streamlink:master Aug 2, 2024
@gsilvan

gsilvan commented Aug 2, 2024

Copy link
Copy Markdown
Contributor Author

Thanks for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

plugin issue A Plugin does not work correctly stream: HLS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants