Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[media.ccc.de] Fix live stream extraction #767

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 "";
Expand All @@ -114,8 +111,11 @@ public List<AudioStream> 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));
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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())) {
Comment on lines +184 to +187
Copy link
Member

Choose a reason for hiding this comment

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

Mmmh, I think before only videoStreams and audioStreams were checked because in any other case the stream is a livestream. So NewPipe's player expected to need to use hls/dash urls only on livestreams. Does this change break that workflow, or is the check being done differently by NewPipe and so this is not an issue?


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);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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<InfoItem> 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.");
}
}

}