Skip to content

Commit 1acc53b

Browse files
committed
[PeerTube] Add support for HLS streams
1 parent 3a3ade2 commit 1acc53b

2 files changed

Lines changed: 80 additions & 14 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeStreamExtractor.java

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,37 @@ public List<AudioStream> getAudioStreams() {
211211
public List<VideoStream> getVideoStreams() throws ExtractionException {
212212
assertPageFetched();
213213
final List<VideoStream> videoStreams = new ArrayList<>();
214+
// mp4
214215
try {
215-
final JsonArray streams = json.getArray("files");
216+
videoStreams.addAll(getVideoStreamsFromArray(json.getArray("files")));
217+
} catch (Exception ignored) { }
218+
// HLS
219+
try {
220+
final JsonArray streamingPlaylists = json.getArray("streamingPlaylists");
221+
for (final Object p : streamingPlaylists) {
222+
if (!(p instanceof JsonObject)) continue;
223+
final JsonObject playlist = (JsonObject) p;
224+
videoStreams.addAll(getVideoStreamsFromArray(playlist.getArray("files")));
225+
}
226+
} catch (Exception e) {
227+
throw new ParsingException("Could not get video streams", e);
228+
}
229+
230+
return videoStreams;
231+
}
232+
233+
private List<VideoStream> getVideoStreamsFromArray(final JsonArray streams) throws ParsingException {
234+
try {
235+
final List<VideoStream> videoStreams = new ArrayList<>();
216236
for (final Object s : streams) {
217237
if (!(s instanceof JsonObject)) continue;
218238
final JsonObject stream = (JsonObject) s;
219-
final String url = JsonUtils.getString(stream, "fileUrl");
239+
final String url;
240+
if (stream.has("fileDownloadUrl")) {
241+
url = JsonUtils.getString(stream, "fileDownloadUrl");
242+
} else {
243+
url = JsonUtils.getString(stream, "fileUrl");
244+
}
220245
final String torrentUrl = JsonUtils.getString(stream, "torrentUrl");
221246
final String resolution = JsonUtils.getString(stream, "resolution.label");
222247
final String extension = url.substring(url.lastIndexOf(".") + 1);
@@ -226,14 +251,13 @@ public List<VideoStream> getVideoStreams() throws ExtractionException {
226251
videoStreams.add(videoStream);
227252
}
228253
}
254+
return videoStreams;
229255
} catch (Exception e) {
230-
throw new ParsingException("Could not get video streams", e);
256+
throw new ParsingException("Could not get video streams from array");
231257
}
232258

233-
return videoStreams;
234259
}
235260

236-
237261
@Override
238262
public List<VideoStream> getVideoOnlyStreams() {
239263
return Collections.emptyList();

extractor/src/test/java/org/schabi/newpipe/extractor/services/peertube/PeertubeStreamExtractorTest.java

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222
import static org.junit.Assert.assertEquals;
2323
import static org.schabi.newpipe.extractor.ServiceList.PeerTube;
2424

25-
public class PeertubeStreamExtractorTest {
25+
public abstract class PeertubeStreamExtractorTest extends DefaultStreamExtractorTest {
2626
private static final String BASE_URL = "/videos/watch/";
2727

28-
public static class WhatIsPeertube extends DefaultStreamExtractorTest {
28+
@Override public boolean expectedHasAudioStreams() { return false; }
29+
@Override public boolean expectedHasFrames() { return false; }
30+
31+
public static class WhatIsPeertube extends PeertubeStreamExtractorTest {
2932
private static final String ID = "9c9de5e8-0a1e-484a-b099-e80766180a6d";
3033
private static final String INSTANCE = "https://framatube.org";
3134
private static final int TIMESTAMP_MINUTE = 1;
@@ -85,18 +88,60 @@ public void testGetLanguageInformation() throws ParsingException {
8588
@Nullable @Override public String expectedTextualUploadDate() { return "2018-10-01T10:52:46.396Z"; }
8689
@Override public long expectedLikeCountAtLeast() { return 120; }
8790
@Override public long expectedDislikeCountAtLeast() { return 0; }
88-
@Override public boolean expectedHasAudioStreams() { return false; }
89-
@Override public boolean expectedHasFrames() { return false; }
9091
@Override public String expectedHost() { return "framatube.org"; }
9192
@Override public String expectedCategory() { return "Science & Technology"; }
9293
@Override public String expectedLicence() { return "Attribution - Share Alike"; }
9394
@Override public Locale expectedLanguageInfo() { return Locale.forLanguageTag("en"); }
9495
@Override public List<String> expectedTags() { return Arrays.asList("framasoft", "peertube"); }
95-
@Override public int expectedStreamSegmentsCount() { return 0; }
96+
}
97+
98+
public static class HlsOnlyStreams extends PeertubeStreamExtractorTest {
99+
private static final String ID = "41342cb4-6fa8-402d-a116-1f63a7f438a3";
100+
private static final String INSTANCE = "https://tilvids.com";
101+
102+
private static final String URL = INSTANCE + BASE_URL + ID;
103+
private static StreamExtractor extractor;
104+
105+
@BeforeClass
106+
public static void setUp() throws Exception {
107+
NewPipe.init(DownloaderTestImpl.getInstance());
108+
// setting instance might break test when running in parallel (!)
109+
PeerTube.setInstance(new PeertubeInstance(INSTANCE, "TILvids"));
110+
extractor = PeerTube.getStreamExtractor(URL);
111+
extractor.fetchPage();
112+
}
113+
114+
@Override public StreamExtractor extractor() { return extractor; }
115+
@Override public StreamingService expectedService() { return PeerTube; }
116+
@Override public String expectedName() { return "A Goodbye to Flash Games"; }
117+
@Override public String expectedId() { return ID; }
118+
@Override public String expectedUrlContains() { return INSTANCE + BASE_URL + ID; }
119+
@Override public String expectedOriginalUrlContains() { return URL; }
120+
121+
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
122+
@Override public String expectedUploaderName() { return "Marinauts"; }
123+
@Override public String expectedUploaderUrl() { return "https://tilvids.com/accounts/marinauts@tilvids.com"; }
124+
@Override public String expectedSubChannelName() { return "Main marinauts channel"; }
125+
@Override public String expectedSubChannelUrl() { return "https://tilvids.com/video-channels/marinauts_channel"; }
126+
@Override public List<String> expectedDescriptionContains() { // CRLF line ending
127+
return Arrays.asList("Goodbye", "Flash Games", "Anthony takes a minute", "Songs used:");
128+
}
129+
@Override public long expectedLength() { return 362; }
130+
@Override public long expectedViewCountAtLeast() { return 20; }
131+
@Nullable @Override public String expectedUploadDate() { return "2021-04-08 20:15:32.434"; }
132+
@Nullable @Override public String expectedTextualUploadDate() { return "2021-04-08T20:15:32.434Z"; }
133+
@Override public long expectedLikeCountAtLeast() { return 6; }
134+
@Override public long expectedDislikeCountAtLeast() { return 0; }
135+
@Override public boolean expectedHasSubtitles() { return false; }
136+
@Override public String expectedHost() { return "tilvids.com"; }
137+
@Override public String expectedCategory() { return "Entertainment"; }
138+
@Override public String expectedLicence() { return "Unknown"; }
139+
@Override public Locale expectedLanguageInfo() { return null; }
140+
@Override public List<String> expectedTags() { return Arrays.asList("Marinauts", "adobe flash", "adobe flash player", "flash games", "the marinauts"); }
96141
}
97142

98143
@Ignore("Test broken, SSL problem")
99-
public static class AgeRestricted extends DefaultStreamExtractorTest {
144+
public static class AgeRestricted extends PeertubeStreamExtractorTest {
100145
private static final String ID = "dbd8e5e1-c527-49b6-b70c-89101dbb9c08";
101146
private static final String INSTANCE = "https://nocensoring.net";
102147
private static final String URL = INSTANCE + "/videos/embed/" + ID;
@@ -134,9 +179,6 @@ public static void setUp() throws Exception {
134179
@Override public long expectedLikeCountAtLeast() { return 1; }
135180
@Override public long expectedDislikeCountAtLeast() { return 0; }
136181
@Override public int expectedAgeLimit() { return 18; }
137-
@Override public boolean expectedHasAudioStreams() { return false; }
138-
@Override public boolean expectedHasSubtitles() { return false; }
139-
@Override public boolean expectedHasFrames() { return false; }
140182
@Override public String expectedHost() { return "nocensoring.net"; }
141183
@Override public String expectedCategory() { return "Art"; }
142184
@Override public String expectedLicence() { return "Attribution"; }

0 commit comments

Comments
 (0)