Skip to content

Commit aa4c10e

Browse files
committed
Improve documentation and adress most of the requested changes
Also fix some issues in several places, in the code and the documentation.
1 parent 6985167 commit aa4c10e

20 files changed

Lines changed: 762 additions & 525 deletions

extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampStreamExtractor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,9 @@ public DateWrapper getUploadDate() throws ParsingException {
120120
public String getThumbnailUrl() throws ParsingException {
121121
if (albumJson.isNull("art_id")) {
122122
return EMPTY_STRING;
123-
} else {
124-
return getImageUrl(albumJson.getLong("art_id"), true);
125123
}
124+
125+
return getImageUrl(albumJson.getLong("art_id"), true);
126126
}
127127

128128
@Nonnull

extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamExtractor.java

Lines changed: 90 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,16 @@
1212
import org.schabi.newpipe.extractor.stream.AudioStream;
1313
import org.schabi.newpipe.extractor.stream.DeliveryMethod;
1414
import org.schabi.newpipe.extractor.stream.Description;
15+
import org.schabi.newpipe.extractor.stream.Stream;
1516
import org.schabi.newpipe.extractor.stream.StreamExtractor;
1617
import org.schabi.newpipe.extractor.stream.StreamType;
1718
import org.schabi.newpipe.extractor.stream.VideoStream;
1819

1920
import java.io.IOException;
20-
import java.util.ArrayList;
2121
import java.util.Collections;
2222
import java.util.List;
23-
import java.util.stream.IntStream;
23+
import java.util.function.Function;
24+
import java.util.stream.Collectors;
2425

2526
import javax.annotation.Nonnull;
2627

@@ -58,9 +59,9 @@ public void onFetchPage(@Nonnull final Downloader downloader)
5859
final JsonObject roomObject = rooms.getObject(r);
5960
if (getId().equals(conferenceObject.getString("slug") + "/"
6061
+ roomObject.getString("slug"))) {
61-
this.conference = conferenceObject;
62-
this.group = groupObject;
63-
this.room = roomObject;
62+
conference = conferenceObject;
63+
group = groupObject;
64+
room = roomObject;
6465
return;
6566
}
6667
}
@@ -109,122 +110,120 @@ public String getUploaderName() throws ParsingException {
109110
* Get the URL of the first DASH stream found.
110111
*
111112
* <p>
112-
* There can be several DASH streams, so the URL of the first found is returned by this method.
113+
* There can be several DASH streams, so the URL of the first one found is returned by this
114+
* method.
113115
* </p>
114116
*
115117
* <p>
116-
* You can find the other video DASH streams by using {@link #getVideoStreams()}
118+
* You can find the other DASH video streams by using {@link #getVideoStreams()}
117119
* </p>
118120
*/
119121
@Nonnull
120122
@Override
121123
public String getDashMpdUrl() throws ParsingException {
122-
123-
for (int s = 0; s < room.getArray(STREAMS).size(); s++) {
124-
final JsonObject stream = room.getArray(STREAMS).getObject(s);
125-
final JsonObject urls = stream.getObject(URLS);
126-
if (urls.has("dash")) {
127-
return urls.getObject("dash").getString(URL, EMPTY_STRING);
128-
}
129-
}
130-
131-
return EMPTY_STRING;
124+
return getManifestOfDeliveryMethodWanted("dash");
132125
}
133126

134127
/**
135128
* Get the URL of the first HLS stream found.
136129
*
137130
* <p>
138-
* There can be several HLS streams, so the URL of the first found is returned by this method.
131+
* There can be several HLS streams, so the URL of the first one found is returned by this
132+
* method.
139133
* </p>
140134
*
141135
* <p>
142-
* You can find the other video HLS streams by using {@link #getVideoStreams()}
136+
* You can find the other HLS video streams by using {@link #getVideoStreams()}
143137
* </p>
144138
*/
145139
@Nonnull
146140
@Override
147141
public String getHlsUrl() {
148-
for (int s = 0; s < room.getArray(STREAMS).size(); s++) {
149-
final JsonObject stream = room.getArray(STREAMS).getObject(s);
150-
final JsonObject urls = stream.getObject(URLS);
151-
if (urls.has("hls")) {
152-
return urls.getObject("hls").getString(URL, EMPTY_STRING);
153-
}
154-
}
155-
return EMPTY_STRING;
142+
return getManifestOfDeliveryMethodWanted("hls");
143+
}
144+
145+
@Nonnull
146+
private String getManifestOfDeliveryMethodWanted(@Nonnull final String deliveryMethod) {
147+
return room.getArray(STREAMS).stream()
148+
.filter(JsonObject.class::isInstance)
149+
.map(JsonObject.class::cast)
150+
.map(streamObject -> streamObject.getObject(URLS))
151+
.filter(urls -> urls.has(deliveryMethod))
152+
.map(urls -> urls.getObject(deliveryMethod).getString(URL, EMPTY_STRING))
153+
.findFirst()
154+
.orElse(EMPTY_STRING);
156155
}
157156

158157
@Override
159158
public List<AudioStream> getAudioStreams() throws IOException, ExtractionException {
160-
final List<AudioStream> audioStreams = new ArrayList<>();
161-
IntStream.range(0, room.getArray(STREAMS).size())
162-
.mapToObj(s -> room.getArray(STREAMS).getObject(s))
163-
.filter(streamJsonObject -> streamJsonObject.getString("type").equals("audio"))
164-
.forEachOrdered(streamJsonObject -> streamJsonObject.getObject(URLS).keySet()
165-
.forEach(type -> {
166-
final JsonObject urlObject = streamJsonObject.getObject(URLS)
167-
.getObject(type);
168-
// The DASH manifest will be extracted with getDashMpdUrl
169-
if (!type.equals("dash")) {
170-
final AudioStream.Builder builder = new AudioStream.Builder()
171-
.setId(urlObject.getString("tech", ID_UNKNOWN))
172-
.setContent(urlObject.getString(URL), true)
173-
.setAverageBitrate(UNKNOWN_BITRATE);
174-
if (type.equals("hls")) {
175-
// We don't know with the type string what media format will
176-
// have HLS streams.
177-
// However, the tech string may contain some information
178-
// about the media format used.
179-
builder.setDeliveryMethod(DeliveryMethod.HLS);
180-
} else {
181-
builder.setMediaFormat(MediaFormat.getFromSuffix(type));
182-
}
183-
184-
audioStreams.add(builder.build());
185-
}
186-
}));
187-
188-
return audioStreams;
159+
return getStreams("audio",
160+
dto -> {
161+
final AudioStream.Builder builder = new AudioStream.Builder()
162+
.setId(dto.getUrlValue().getString("tech", ID_UNKNOWN))
163+
.setContent(dto.getUrlValue().getString(URL), true)
164+
.setAverageBitrate(UNKNOWN_BITRATE);
165+
166+
if ("hls".equals(dto.getUrlKey())) {
167+
// We don't know with the type string what media format will
168+
// have HLS streams.
169+
// However, the tech string may contain some information
170+
// about the media format used.
171+
return builder.setDeliveryMethod(DeliveryMethod.HLS)
172+
.build();
173+
}
174+
175+
return builder.setMediaFormat(MediaFormat.getFromSuffix(dto.getUrlKey()))
176+
.build();
177+
});
189178
}
190179

191180
@Override
192181
public List<VideoStream> getVideoStreams() throws IOException, ExtractionException {
193-
final List<VideoStream> videoStreams = new ArrayList<>();
194-
IntStream.range(0, room.getArray(STREAMS).size())
195-
.mapToObj(s -> room.getArray(STREAMS).getObject(s))
196-
.filter(stream -> stream.getString("type").equals("video"))
197-
.forEachOrdered(streamJsonObject -> streamJsonObject.getObject(URLS).keySet()
198-
.forEach(type -> {
199-
final String resolution =
200-
streamJsonObject.getArray("videoSize").getInt(0)
201-
+ "x"
202-
+ streamJsonObject.getArray("videoSize").getInt(1);
203-
final JsonObject urlObject = streamJsonObject.getObject(URLS)
204-
.getObject(type);
205-
// The DASH manifest will be extracted with getDashMpdUrl
206-
if (!type.equals("dash")) {
207-
final VideoStream.Builder builder = new VideoStream.Builder()
208-
.setId(urlObject.getString("tech", ID_UNKNOWN))
209-
.setContent(urlObject.getString(URL), true)
210-
.setIsVideoOnly(false)
211-
.setResolution(resolution);
212-
213-
if (type.equals("hls")) {
214-
// We don't know with the type string what media format will
215-
// have HLS streams.
216-
// However, the tech string may contain some information
217-
// about the media format used.
218-
builder.setDeliveryMethod(DeliveryMethod.HLS);
219-
} else {
220-
builder.setMediaFormat(MediaFormat.getFromSuffix(type));
221-
}
222-
223-
videoStreams.add(builder.build());
224-
}
225-
}));
226-
227-
return videoStreams;
182+
return getStreams("video",
183+
dto -> {
184+
final JsonArray videoSize = dto.getStreamJsonObj().getArray("videoSize");
185+
186+
final VideoStream.Builder builder = new VideoStream.Builder()
187+
.setId(dto.getUrlValue().getString("tech", ID_UNKNOWN))
188+
.setContent(dto.getUrlValue().getString(URL), true)
189+
.setIsVideoOnly(false)
190+
.setResolution(videoSize.getInt(0) + "x" + videoSize.getInt(1));
191+
192+
if ("hls".equals(dto.getUrlKey())) {
193+
// We don't know with the type string what media format will
194+
// have HLS streams.
195+
// However, the tech string may contain some information
196+
// about the media format used.
197+
return builder.setDeliveryMethod(DeliveryMethod.HLS)
198+
.build();
199+
}
200+
201+
return builder.setMediaFormat(MediaFormat.getFromSuffix(dto.getUrlKey()))
202+
.build();
203+
});
204+
}
205+
206+
private <T extends Stream> List<T> getStreams(
207+
@Nonnull final String streamType,
208+
@Nonnull final Function<MediaCCCLiveStreamMapperDTO, T> converter) {
209+
return room.getArray(STREAMS).stream()
210+
// Ensure that we use only process JsonObjects
211+
.filter(JsonObject.class::isInstance)
212+
.map(JsonObject.class::cast)
213+
// Only process audio streams
214+
.filter(streamJsonObj -> streamType.equals(streamJsonObj.getString("type")))
215+
// Flatmap Urls and ensure that we use only process JsonObjects
216+
.flatMap(streamJsonObj -> streamJsonObj.getObject(URLS).entrySet().stream()
217+
.filter(e -> e.getValue() instanceof JsonObject)
218+
.map(e -> new MediaCCCLiveStreamMapperDTO(
219+
streamJsonObj,
220+
e.getKey(),
221+
(JsonObject) e.getValue())))
222+
// The DASH manifest will be extracted with getDashMpdUrl
223+
.filter(dto -> !"dash".equals(dto.getUrlKey()))
224+
// Convert
225+
.map(converter)
226+
.collect(Collectors.toList());
228227
}
229228

230229
@Override
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.schabi.newpipe.extractor.services.media_ccc.extractors;
2+
3+
import com.grack.nanojson.JsonObject;
4+
5+
final class MediaCCCLiveStreamMapperDTO {
6+
private final JsonObject streamJsonObj;
7+
private final String urlKey;
8+
private final JsonObject urlValue;
9+
10+
MediaCCCLiveStreamMapperDTO(final JsonObject streamJsonObj,
11+
final String urlKey,
12+
final JsonObject urlValue) {
13+
this.streamJsonObj = streamJsonObj;
14+
this.urlKey = urlKey;
15+
this.urlValue = urlValue;
16+
}
17+
18+
JsonObject getStreamJsonObj() {
19+
return streamJsonObj;
20+
}
21+
22+
String getUrlKey() {
23+
return urlKey;
24+
}
25+
26+
JsonObject getUrlValue() {
27+
return urlValue;
28+
}
29+
}

extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCStreamExtractor.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public List<AudioStream> getAudioStreams() throws ExtractionException {
102102
final JsonObject recording = recordings.getObject(i);
103103
final String mimeType = recording.getString("mime_type");
104104
if (mimeType.startsWith("audio")) {
105-
// First we need to resolve the actual video data from CDN
105+
// First we need to resolve the actual video data from the CDN
106106
final MediaFormat mediaFormat;
107107
if (mimeType.endsWith("opus")) {
108108
mediaFormat = MediaFormat.OPUS;
@@ -115,7 +115,7 @@ public List<AudioStream> getAudioStreams() throws ExtractionException {
115115
}
116116

117117
// Don't use the containsSimilarStream method because it will always return
118-
// false so if there are multiples audio streams available, only the first will
118+
// false. So if there are multiple audio streams available, only the first one will
119119
// be extracted in this case.
120120
audioStreams.add(new AudioStream.Builder()
121121
.setId(recording.getString("filename", ID_UNKNOWN))
@@ -136,7 +136,7 @@ public List<VideoStream> getVideoStreams() throws ExtractionException {
136136
final JsonObject recording = recordings.getObject(i);
137137
final String mimeType = recording.getString("mime_type");
138138
if (mimeType.startsWith("video")) {
139-
// First we need to resolve the actual video data from CDN
139+
// First we need to resolve the actual video data from the CDN
140140

141141
final MediaFormat mediaFormat;
142142
if (mimeType.endsWith("webm")) {
@@ -148,7 +148,8 @@ public List<VideoStream> getVideoStreams() throws ExtractionException {
148148
}
149149

150150
// Don't use the containsSimilarStream method because it will remove the
151-
// extraction of some video versions (mostly languages)
151+
// extraction of some video versions (mostly languages). So if there are multiple
152+
// video streams available, only the first one will be extracted in this case.
152153
videoStreams.add(new VideoStream.Builder()
153154
.setId(recording.getString("filename", ID_UNKNOWN))
154155
.setContent(recording.getString("recording_url"), true)

0 commit comments

Comments
 (0)