From 752825ced2bd63c75475074a16263e39af90b356 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Mon, 27 Dec 2021 19:18:36 +0100 Subject: [PATCH] [media.ccc.de] Fix live streams extraction The API was slightly changed and only HLS streams are provided anymore. Add a basic test for to check whether the required streamInfo fields are available. Closes #766 --- .../MediaCCCLiveStreamExtractor.java | 18 +++---- .../newpipe/extractor/stream/StreamInfo.java | 13 +++-- .../MediaCCCLiveStreamExtractorTest.java | 52 +++++++++++++++++++ 3 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCLiveStreamExtractorTest.java diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamExtractor.java index bd02d64838..2d1c0dd4c4 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamExtractor.java @@ -93,15 +93,12 @@ public String getUploaderName() throws ParsingException { @Override public String getHlsUrl() { // TODO: There are multiple HLS streams. - // Make getHlsUrl() and getDashMpdUrl() return lists of VideoStreams, so the user can choose a resolution. + // Make getHlsUrl() and getDashMpdUrl() return lists of VideoStreams + // to allow selecting a resolution. for (int s = 0; s < room.getArray("streams").size(); s++) { final JsonObject stream = room.getArray("streams").getObject(s); - if (stream.getString("type").equals("video")) { - final String resolution = stream.getArray("videoSize").getInt(0) + "x" - + stream.getArray("videoSize").getInt(1); - if (stream.has("hls")) { - return stream.getObject("urls").getObject("hls").getString("url"); - } + if (stream.getString("type").equals("video") && stream.getObject("urls").has("hls")) { + return stream.getObject("urls").getObject("hls").getString("url"); } } return ""; @@ -114,8 +111,11 @@ public List getAudioStreams() throws IOException, ExtractionExcepti final JsonObject stream = room.getArray("streams").getObject(s); if (stream.getString("type").equals("audio")) { for (final String type : stream.getObject("urls").keySet()) { - final JsonObject url = stream.getObject("urls").getObject(type); - audioStreams.add(new AudioStream(url.getString("url"), MediaFormat.getFromSuffix(type), -1)); + if (!type.equals("hls")) { + final JsonObject url = stream.getObject("urls").getObject(type); + audioStreams.add(new AudioStream( + url.getString("url"), MediaFormat.getFromSuffix(type), -1)); + } } } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java index 455f0dc46a..6a9d563e5a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java @@ -139,13 +139,13 @@ private static StreamInfo extractStreams(StreamInfo streamInfo, StreamExtractor } catch (Exception e) { streamInfo.addError(new ExtractionException("Couldn't get audio streams", e)); } - /* Extract video stream url */ + /* Extract video streams */ try { streamInfo.setVideoStreams(extractor.getVideoStreams()); } catch (Exception e) { streamInfo.addError(new ExtractionException("Couldn't get video streams", e)); } - /* Extract video only stream url */ + /* Extract video only streams */ try { streamInfo.setVideoOnlyStreams(extractor.getVideoOnlyStreams()); } catch (Exception e) { @@ -181,13 +181,16 @@ private static StreamInfo extractStreams(StreamInfo streamInfo, StreamExtractor // Either audio or video has to be available, otherwise we didn't get a stream // (since videoOnly are optional, they don't count). - if ((streamInfo.videoStreams.isEmpty()) && (streamInfo.audioStreams.isEmpty())) { + if (streamInfo.videoStreams.isEmpty() + && streamInfo.audioStreams.isEmpty() + && isNullOrEmpty(streamInfo.getHlsUrl()) + && isNullOrEmpty(streamInfo.getDashMpdUrl())) { if (dashMpdError != null) { // If we don't have any video or audio and the dashMpd 'errored', add it to the // error list - // (it's optional and it don't get added automatically, but it's good to have - // some additional error context) + // (It's optional, and it is not added automatically, + // but it's good to have some additional error context). streamInfo.addError(dashMpdError); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCLiveStreamExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCLiveStreamExtractorTest.java new file mode 100644 index 0000000000..56303a9c80 --- /dev/null +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCLiveStreamExtractorTest.java @@ -0,0 +1,52 @@ +package org.schabi.newpipe.extractor.services.media_ccc; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.schabi.newpipe.downloader.DownloaderTestImpl; +import org.schabi.newpipe.extractor.InfoItem; +import org.schabi.newpipe.extractor.NewPipe; +import org.schabi.newpipe.extractor.exceptions.ExtractionException; +import org.schabi.newpipe.extractor.kiosk.KioskExtractor; +import org.schabi.newpipe.extractor.stream.StreamExtractor; +import org.schabi.newpipe.extractor.stream.StreamInfo; + +import java.io.IOException; +import java.util.List; + +import static org.schabi.newpipe.extractor.ServiceList.MediaCCC; + +public class MediaCCCLiveStreamExtractorTest { + + private static KioskExtractor liveKiosk; + private static StreamExtractor extractor; + + private static List liveItems; + + @BeforeClass + public static void setUp() throws Exception { + NewPipe.init(DownloaderTestImpl.getInstance()); + liveKiosk = MediaCCC.getKioskList().getExtractorById("live", null); + liveKiosk.fetchPage(); + liveItems = liveKiosk.getInitialPage().getItems(); + Assume.assumeFalse( + "Received an empty list of live streams. Skipping MediaCCCLiveStreamExtractorTest", + liveItems.isEmpty()); + } + + @Test + public void testRequiredStreamInfo() { + // Try to get the StreamInfo for each live stream. + // If some required info is not present an exception will be thrown. + try { + for (final InfoItem item : liveItems) { + StreamInfo.getInfo(item.getUrl()); + } + } catch (ExtractionException | IOException e) { + e.printStackTrace(); + Assert.fail("An exception was thrown while getting a StreamInfo for a livestream."); + } + } + +}