|
12 | 12 | import org.schabi.newpipe.extractor.stream.AudioStream; |
13 | 13 | import org.schabi.newpipe.extractor.stream.DeliveryMethod; |
14 | 14 | import org.schabi.newpipe.extractor.stream.Description; |
| 15 | +import org.schabi.newpipe.extractor.stream.Stream; |
15 | 16 | import org.schabi.newpipe.extractor.stream.StreamExtractor; |
16 | 17 | import org.schabi.newpipe.extractor.stream.StreamType; |
17 | 18 | import org.schabi.newpipe.extractor.stream.VideoStream; |
18 | 19 |
|
19 | 20 | import java.io.IOException; |
20 | | -import java.util.ArrayList; |
21 | 21 | import java.util.Collections; |
22 | 22 | import java.util.List; |
23 | | -import java.util.stream.IntStream; |
| 23 | +import java.util.function.Function; |
| 24 | +import java.util.stream.Collectors; |
24 | 25 |
|
25 | 26 | import javax.annotation.Nonnull; |
26 | 27 |
|
@@ -58,9 +59,9 @@ public void onFetchPage(@Nonnull final Downloader downloader) |
58 | 59 | final JsonObject roomObject = rooms.getObject(r); |
59 | 60 | if (getId().equals(conferenceObject.getString("slug") + "/" |
60 | 61 | + roomObject.getString("slug"))) { |
61 | | - this.conference = conferenceObject; |
62 | | - this.group = groupObject; |
63 | | - this.room = roomObject; |
| 62 | + conference = conferenceObject; |
| 63 | + group = groupObject; |
| 64 | + room = roomObject; |
64 | 65 | return; |
65 | 66 | } |
66 | 67 | } |
@@ -109,122 +110,120 @@ public String getUploaderName() throws ParsingException { |
109 | 110 | * Get the URL of the first DASH stream found. |
110 | 111 | * |
111 | 112 | * <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. |
113 | 115 | * </p> |
114 | 116 | * |
115 | 117 | * <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()} |
117 | 119 | * </p> |
118 | 120 | */ |
119 | 121 | @Nonnull |
120 | 122 | @Override |
121 | 123 | 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"); |
132 | 125 | } |
133 | 126 |
|
134 | 127 | /** |
135 | 128 | * Get the URL of the first HLS stream found. |
136 | 129 | * |
137 | 130 | * <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. |
139 | 133 | * </p> |
140 | 134 | * |
141 | 135 | * <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()} |
143 | 137 | * </p> |
144 | 138 | */ |
145 | 139 | @Nonnull |
146 | 140 | @Override |
147 | 141 | 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); |
156 | 155 | } |
157 | 156 |
|
158 | 157 | @Override |
159 | 158 | 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 | + }); |
189 | 178 | } |
190 | 179 |
|
191 | 180 | @Override |
192 | 181 | 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()); |
228 | 227 | } |
229 | 228 |
|
230 | 229 | @Override |
|
0 commit comments