Skip to content

Commit 1259521

Browse files
authored
Merge pull request #500 from TeamNewPipe/media.ccc.de_live
[media.ccc.de] live stream kiosk
2 parents b283769 + b4e1913 commit 1259521

16 files changed

Lines changed: 834 additions & 15 deletions

extractor/src/main/java/org/schabi/newpipe/extractor/kiosk/KioskExtractor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ public String getId() {
4545
}
4646

4747
/**
48-
* Id should be the name of the kiosk, tho Id is used for identifing it in the frontend,
48+
* Id should be the name of the kiosk, tho Id is used for identifying it in the frontend,
4949
* so id should be kept in english.
5050
* In order to get the name of the kiosk in the desired language we have to
5151
* crawl if from the website.
52-
* @return the tranlsated version of id
52+
* @return the translated version of id
5353
* @throws ParsingException
5454
*/
5555
@Nonnull

extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,8 @@
1414
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory;
1515
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
1616
import org.schabi.newpipe.extractor.search.SearchExtractor;
17-
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCConferenceExtractor;
18-
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCConferenceKiosk;
19-
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCSearchExtractor;
20-
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCStreamExtractor;
21-
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferenceLinkHandlerFactory;
22-
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferencesListLinkHandlerFactory;
23-
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory;
24-
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCStreamLinkHandlerFactory;
17+
import org.schabi.newpipe.extractor.services.media_ccc.extractors.*;
18+
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.*;
2519
import org.schabi.newpipe.extractor.stream.StreamExtractor;
2620
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
2721
import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor;
@@ -62,6 +56,9 @@ public SearchQueryHandlerFactory getSearchQHFactory() {
6256

6357
@Override
6458
public StreamExtractor getStreamExtractor(final LinkHandler linkHandler) {
59+
if (MediaCCCParsingHelper.isLiveStreamId(linkHandler.getId())) {
60+
return new MediaCCCLiveStreamExtractor(this, linkHandler);
61+
}
6562
return new MediaCCCStreamExtractor(this, linkHandler);
6663
}
6764

@@ -95,7 +92,28 @@ public KioskExtractor createNewKiosk(final StreamingService streamingService,
9592
new MediaCCCConferencesListLinkHandlerFactory().fromUrl(url), kioskId);
9693
}
9794
}, new MediaCCCConferencesListLinkHandlerFactory(), "conferences");
98-
list.setDefaultKiosk("conferences");
95+
96+
list.addKioskEntry(new KioskList.KioskExtractorFactory() {
97+
@Override
98+
public KioskExtractor createNewKiosk(final StreamingService streamingService,
99+
final String url, final String kioskId)
100+
throws ExtractionException {
101+
return new MediaCCCRecentKiosk(MediaCCCService.this,
102+
new MediaCCCRecentListLinkHandlerFactory().fromUrl(url), kioskId);
103+
}
104+
}, new MediaCCCRecentListLinkHandlerFactory(), "recent");
105+
106+
list.addKioskEntry(new KioskList.KioskExtractorFactory() {
107+
@Override
108+
public KioskExtractor createNewKiosk(final StreamingService streamingService,
109+
final String url, final String kioskId)
110+
throws ExtractionException {
111+
return new MediaCCCLiveStreamKiosk(MediaCCCService.this,
112+
new MediaCCCLiveListLinkHandlerFactory().fromUrl(url), kioskId);
113+
}
114+
}, new MediaCCCLiveListLinkHandlerFactory(), "live");
115+
116+
list.setDefaultKiosk("recent");
99117
} catch (Exception e) {
100118
throw new ExtractionException(e);
101119
}
Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
package org.schabi.newpipe.extractor.services.media_ccc.extractors;
2+
3+
import com.grack.nanojson.JsonArray;
4+
import com.grack.nanojson.JsonObject;
5+
import org.schabi.newpipe.extractor.MediaFormat;
6+
import org.schabi.newpipe.extractor.MetaInfo;
7+
import org.schabi.newpipe.extractor.StreamingService;
8+
import org.schabi.newpipe.extractor.downloader.Downloader;
9+
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
10+
import org.schabi.newpipe.extractor.exceptions.ParsingException;
11+
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
12+
import org.schabi.newpipe.extractor.localization.DateWrapper;
13+
import org.schabi.newpipe.extractor.stream.*;
14+
15+
import javax.annotation.Nonnull;
16+
import javax.annotation.Nullable;
17+
import java.io.IOException;
18+
import java.util.ArrayList;
19+
import java.util.Collections;
20+
import java.util.List;
21+
import java.util.Locale;
22+
23+
public class MediaCCCLiveStreamExtractor extends StreamExtractor {
24+
private JsonArray doc = null;
25+
private JsonObject conference = null;
26+
private String group = "";
27+
private JsonObject room = null;
28+
29+
public MediaCCCLiveStreamExtractor(StreamingService service, LinkHandler linkHandler) {
30+
super(service, linkHandler);
31+
}
32+
33+
@Override
34+
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
35+
doc = MediaCCCParsingHelper.getLiveStreams(downloader, getExtractorLocalization());
36+
// find correct room
37+
for (int c = 0; c < doc.size(); c++) {
38+
final JsonObject conference = doc.getObject(c);
39+
final JsonArray groups = conference.getArray("groups");
40+
for (int g = 0; g < groups.size(); g++) {
41+
final String group = groups.getObject(g).getString("group");
42+
final JsonArray rooms = groups.getObject(g).getArray("rooms");
43+
for (int r = 0; r < rooms.size(); r++) {
44+
final JsonObject room = rooms.getObject(r);
45+
if (getId().equals(conference.getString("slug") + "/" + room.getString("slug"))) {
46+
this.conference = conference;
47+
this.group = group;
48+
this.room = room;
49+
return;
50+
}
51+
}
52+
}
53+
}
54+
throw new ExtractionException("Could not find room matching id: '" + getId() + "'");
55+
}
56+
57+
@Nonnull
58+
@Override
59+
public String getName() throws ParsingException {
60+
return room.getString("display");
61+
}
62+
63+
@Nullable
64+
@Override
65+
public String getTextualUploadDate() throws ParsingException {
66+
return null;
67+
}
68+
69+
@Nullable
70+
@Override
71+
public DateWrapper getUploadDate() throws ParsingException {
72+
return null;
73+
}
74+
75+
@Nonnull
76+
@Override
77+
public String getThumbnailUrl() throws ParsingException {
78+
return room.getString("thumb");
79+
}
80+
81+
@Nonnull
82+
@Override
83+
public Description getDescription() throws ParsingException {
84+
return new Description(conference.getString("description") + " - " + group, Description.PLAIN_TEXT);
85+
}
86+
87+
@Override
88+
public int getAgeLimit() {
89+
return 0;
90+
}
91+
92+
@Override
93+
public long getLength() {
94+
return 0;
95+
}
96+
97+
@Override
98+
public long getTimeStamp() throws ParsingException {
99+
return 0;
100+
}
101+
102+
@Override
103+
public long getViewCount() {
104+
return -1;
105+
}
106+
107+
@Override
108+
public long getLikeCount() {
109+
return -1;
110+
}
111+
112+
@Override
113+
public long getDislikeCount() {
114+
return -1;
115+
}
116+
117+
@Nonnull
118+
@Override
119+
public String getUploaderUrl() throws ParsingException {
120+
return "https://streaming.media.ccc.de/" + conference.getString("slug");
121+
}
122+
123+
@Nonnull
124+
@Override
125+
public String getUploaderName() throws ParsingException {
126+
return conference.getString("conference");
127+
}
128+
129+
@Nonnull
130+
@Override
131+
public String getUploaderAvatarUrl() {
132+
return "";
133+
}
134+
135+
@Nonnull
136+
@Override
137+
public String getSubChannelUrl() {
138+
return "";
139+
}
140+
141+
@Nonnull
142+
@Override
143+
public String getSubChannelName() {
144+
return "";
145+
}
146+
147+
@Nonnull
148+
@Override
149+
public String getSubChannelAvatarUrl() {
150+
return "";
151+
}
152+
153+
@Nonnull
154+
@Override
155+
public String getDashMpdUrl() throws ParsingException {
156+
return "";
157+
}
158+
159+
@Nonnull
160+
@Override
161+
public String getHlsUrl() {
162+
// TODO: There are multiple HLS streams.
163+
// Make getHlsUrl() and getDashMpdUrl() return lists of VideoStreams, so the user can choose a resolution.
164+
for (int s = 0; s < room.getArray("streams").size(); s++) {
165+
final JsonObject stream = room.getArray("streams").getObject(s);
166+
if (stream.getString("type").equals("video")) {
167+
final String resolution = stream.getArray("videoSize").getInt(0) + "x"
168+
+ stream.getArray("videoSize").getInt(1);
169+
if (stream.has("hls")) {
170+
return stream.getObject("urls").getObject("hls").getString("url");
171+
}
172+
}
173+
}
174+
return "";
175+
}
176+
177+
@Override
178+
public List<AudioStream> getAudioStreams() throws IOException, ExtractionException {
179+
final List<AudioStream> audioStreams = new ArrayList<>();
180+
for (int s = 0; s < room.getArray("streams").size(); s++) {
181+
final JsonObject stream = room.getArray("streams").getObject(s);
182+
if (stream.getString("type").equals("audio")) {
183+
for (final String type :stream.getObject("urls").keySet()) {
184+
final JsonObject url = stream.getObject("urls").getObject(type);
185+
audioStreams.add(new AudioStream(url.getString("url"), MediaFormat.getFromSuffix(type), -1));
186+
}
187+
}
188+
}
189+
return audioStreams;
190+
}
191+
192+
@Override
193+
public List<VideoStream> getVideoStreams() throws IOException, ExtractionException {
194+
final List<VideoStream> videoStreams = new ArrayList<>();
195+
for (int s = 0; s < room.getArray("streams").size(); s++) {
196+
final JsonObject stream = room.getArray("streams").getObject(s);
197+
if (stream.getString("type").equals("video")) {
198+
final String resolution = stream.getArray("videoSize").getInt(0) + "x"
199+
+ stream.getArray("videoSize").getInt(1);
200+
for (final String type :stream.getObject("urls").keySet()) {
201+
if (!type.equals("hls")) {
202+
final JsonObject url = stream.getObject("urls").getObject(type);
203+
videoStreams.add(new VideoStream(
204+
url.getString("url"),
205+
MediaFormat.getFromSuffix(type),
206+
resolution));
207+
}
208+
}
209+
}
210+
}
211+
return videoStreams;
212+
}
213+
214+
@Override
215+
public List<VideoStream> getVideoOnlyStreams() throws IOException, ExtractionException {
216+
return null;
217+
}
218+
219+
@Nonnull
220+
@Override
221+
public List<SubtitlesStream> getSubtitlesDefault(){
222+
return Collections.emptyList();
223+
}
224+
225+
@Nonnull
226+
@Override
227+
public List<SubtitlesStream> getSubtitles(MediaFormat format) {
228+
return Collections.emptyList();
229+
}
230+
231+
@Override
232+
public StreamType getStreamType() throws ParsingException {
233+
return StreamType.LIVE_STREAM; // TODO: video and audio only streams are both available
234+
}
235+
236+
@Nullable
237+
@Override
238+
public StreamInfoItemsCollector getRelatedStreams() {
239+
return null;
240+
}
241+
242+
@Override
243+
public String getErrorMessage() {
244+
return null;
245+
}
246+
247+
@Nonnull
248+
@Override
249+
public String getHost() throws ParsingException {
250+
return null;
251+
}
252+
253+
@Nonnull
254+
@Override
255+
public String getPrivacy() {
256+
return "Public";
257+
}
258+
259+
@Nonnull
260+
@Override
261+
public String getCategory() {
262+
return group;
263+
}
264+
265+
@Nonnull
266+
@Override
267+
public String getLicence() {
268+
return "";
269+
}
270+
271+
@Nullable
272+
@Override
273+
public Locale getLanguageInfo() {
274+
return null;
275+
}
276+
277+
@Nonnull
278+
@Override
279+
public List<String> getTags() {
280+
return Collections.emptyList();
281+
}
282+
283+
@Nonnull
284+
@Override
285+
public String getSupportInfo() {
286+
return "";
287+
}
288+
289+
@Nonnull
290+
@Override
291+
public List<StreamSegment> getStreamSegments() {
292+
return Collections.emptyList();
293+
}
294+
295+
@Nonnull
296+
@Override
297+
public List<MetaInfo> getMetaInfo() {
298+
return Collections.emptyList();
299+
}
300+
}

0 commit comments

Comments
 (0)