From b4e191397117447364d137791ec4b1ca3672d75b Mon Sep 17 00:00:00 2001 From: TobiGr Date: Sun, 27 Dec 2020 13:25:48 +0100 Subject: [PATCH] [media.ccc.de] Play live streams --- .../services/media_ccc/MediaCCCService.java | 9 +- .../MediaCCCLiveStreamExtractor.java | 324 ++- .../extractors/MediaCCCLiveStreamKiosk.java | 1918 +---------------- .../MediaCCCLiveStreamKioskExtractor.java | 87 + .../extractors/MediaCCCParsingHelper.java | 32 + ...> MediaCCCLiveListLinkHandlerFactory.java} | 6 +- .../MediaCCCLiveStreamLinkHandlerFactory.java | 30 + .../MediaCCCStreamLinkHandlerFactory.java | 20 +- 8 files changed, 446 insertions(+), 1980 deletions(-) create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKioskExtractor.java rename extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/{MediaCCCLiveStreamListLinkHandlerFactory.java => MediaCCCLiveListLinkHandlerFactory.java} (76%) create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveStreamLinkHandlerFactory.java diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java index e7f41b313..02820c03a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java @@ -20,8 +20,6 @@ import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor; -import java.io.IOException; - import static java.util.Arrays.asList; import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO; import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.VIDEO; @@ -58,6 +56,9 @@ public class MediaCCCService extends StreamingService { @Override public StreamExtractor getStreamExtractor(final LinkHandler linkHandler) { + if (MediaCCCParsingHelper.isLiveStreamId(linkHandler.getId())) { + return new MediaCCCLiveStreamExtractor(this, linkHandler); + } return new MediaCCCStreamExtractor(this, linkHandler); } @@ -108,9 +109,9 @@ public class MediaCCCService extends StreamingService { final String url, final String kioskId) throws ExtractionException { return new MediaCCCLiveStreamKiosk(MediaCCCService.this, - new MediaCCCLiveStreamListLinkHandlerFactory().fromUrl(url), kioskId); + new MediaCCCLiveListLinkHandlerFactory().fromUrl(url), kioskId); } - }, new MediaCCCLiveStreamListLinkHandlerFactory(), "live"); + }, new MediaCCCLiveListLinkHandlerFactory(), "live"); list.setDefaultKiosk("recent"); } catch (Exception e) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamExtractor.java index c2f6e5ff0..605947946 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamExtractor.java @@ -1,75 +1,63 @@ package org.schabi.newpipe.extractor.services.media_ccc.extractors; +import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; +import org.schabi.newpipe.extractor.MediaFormat; +import org.schabi.newpipe.extractor.MetaInfo; +import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.linkhandler.LinkHandler; import org.schabi.newpipe.extractor.localization.DateWrapper; -import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; -import org.schabi.newpipe.extractor.stream.StreamType; +import org.schabi.newpipe.extractor.stream.*; +import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; -public class MediaCCCLiveStreamExtractor implements StreamInfoItemExtractor { +public class MediaCCCLiveStreamExtractor extends StreamExtractor { + private JsonArray doc = null; + private JsonObject conference = null; + private String group = ""; + private JsonObject room = null; - private final JsonObject conferenceInfo; - private final String group; - private final JsonObject roomInfo; - - public MediaCCCLiveStreamExtractor(JsonObject conferenceInfo, String group, JsonObject roomInfo) { - this.conferenceInfo = conferenceInfo; - this.group = group; - this.roomInfo = roomInfo; + public MediaCCCLiveStreamExtractor(StreamingService service, LinkHandler linkHandler) { + super(service, linkHandler); } @Override - public String getName() throws ParsingException { - return roomInfo.getString("schedulename"); - } - - @Override - public String getUrl() throws ParsingException { - return roomInfo.getString("link"); - } - - @Override - public String getThumbnailUrl() throws ParsingException { - return roomInfo.getString("thumb"); - } - - @Override - public StreamType getStreamType() throws ParsingException { - boolean isVideo = false; - for (Object stream : roomInfo.getArray("streams")) { - if ("video".equals(((JsonObject) stream).getString("type"))) { - isVideo = true; - break; + public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { + doc = MediaCCCParsingHelper.getLiveStreams(downloader, getExtractorLocalization()); + // find correct room + for (int c = 0; c < doc.size(); c++) { + final JsonObject conference = doc.getObject(c); + final JsonArray groups = conference.getArray("groups"); + for (int g = 0; g < groups.size(); g++) { + final String group = groups.getObject(g).getString("group"); + final JsonArray rooms = groups.getObject(g).getArray("rooms"); + for (int r = 0; r < rooms.size(); r++) { + final JsonObject room = rooms.getObject(r); + if (getId().equals(conference.getString("slug") + "/" + room.getString("slug"))) { + this.conference = conference; + this.group = group; + this.room = room; + return; + } + } } } - return isVideo ? StreamType.LIVE_STREAM : StreamType.AUDIO_LIVE_STREAM; + throw new ExtractionException("Could not find room matching id: '" + getId() + "'"); } + @Nonnull @Override - public boolean isAd() throws ParsingException { - return false; - } - - @Override - public long getDuration() throws ParsingException { - return 0; - } - - @Override - public long getViewCount() throws ParsingException { - return -1; - } - - @Override - public String getUploaderName() throws ParsingException { - return conferenceInfo.getString("conference"); - } - - @Override - public String getUploaderUrl() throws ParsingException { - return "https://media.ccc.de/c/" + conferenceInfo.getString("slug"); + public String getName() throws ParsingException { + return room.getString("display"); } @Nullable @@ -83,4 +71,230 @@ public class MediaCCCLiveStreamExtractor implements StreamInfoItemExtractor { public DateWrapper getUploadDate() throws ParsingException { return null; } + + @Nonnull + @Override + public String getThumbnailUrl() throws ParsingException { + return room.getString("thumb"); + } + + @Nonnull + @Override + public Description getDescription() throws ParsingException { + return new Description(conference.getString("description") + " - " + group, Description.PLAIN_TEXT); + } + + @Override + public int getAgeLimit() { + return 0; + } + + @Override + public long getLength() { + return 0; + } + + @Override + public long getTimeStamp() throws ParsingException { + return 0; + } + + @Override + public long getViewCount() { + return -1; + } + + @Override + public long getLikeCount() { + return -1; + } + + @Override + public long getDislikeCount() { + return -1; + } + + @Nonnull + @Override + public String getUploaderUrl() throws ParsingException { + return "https://streaming.media.ccc.de/" + conference.getString("slug"); + } + + @Nonnull + @Override + public String getUploaderName() throws ParsingException { + return conference.getString("conference"); + } + + @Nonnull + @Override + public String getUploaderAvatarUrl() { + return ""; + } + + @Nonnull + @Override + public String getSubChannelUrl() { + return ""; + } + + @Nonnull + @Override + public String getSubChannelName() { + return ""; + } + + @Nonnull + @Override + public String getSubChannelAvatarUrl() { + return ""; + } + + @Nonnull + @Override + public String getDashMpdUrl() throws ParsingException { + return ""; + } + + @Nonnull + @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. + 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"); + } + } + } + return ""; + } + + @Override + public List getAudioStreams() throws IOException, ExtractionException { + final List audioStreams = new ArrayList<>(); + for (int s = 0; s < room.getArray("streams").size(); s++) { + 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)); + } + } + } + return audioStreams; + } + + @Override + public List getVideoStreams() throws IOException, ExtractionException { + final List videoStreams = new ArrayList<>(); + 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); + for (final String type :stream.getObject("urls").keySet()) { + if (!type.equals("hls")) { + final JsonObject url = stream.getObject("urls").getObject(type); + videoStreams.add(new VideoStream( + url.getString("url"), + MediaFormat.getFromSuffix(type), + resolution)); + } + } + } + } + return videoStreams; + } + + @Override + public List getVideoOnlyStreams() throws IOException, ExtractionException { + return null; + } + + @Nonnull + @Override + public List getSubtitlesDefault(){ + return Collections.emptyList(); + } + + @Nonnull + @Override + public List getSubtitles(MediaFormat format) { + return Collections.emptyList(); + } + + @Override + public StreamType getStreamType() throws ParsingException { + return StreamType.LIVE_STREAM; // TODO: video and audio only streams are both available + } + + @Nullable + @Override + public StreamInfoItemsCollector getRelatedStreams() { + return null; + } + + @Override + public String getErrorMessage() { + return null; + } + + @Nonnull + @Override + public String getHost() throws ParsingException { + return null; + } + + @Nonnull + @Override + public String getPrivacy() { + return "Public"; + } + + @Nonnull + @Override + public String getCategory() { + return group; + } + + @Nonnull + @Override + public String getLicence() { + return ""; + } + + @Nullable + @Override + public Locale getLanguageInfo() { + return null; + } + + @Nonnull + @Override + public List getTags() { + return Collections.emptyList(); + } + + @Nonnull + @Override + public String getSupportInfo() { + return ""; + } + + @Nonnull + @Override + public List getStreamSegments() { + return Collections.emptyList(); + } + + @Nonnull + @Override + public List getMetaInfo() { + return Collections.emptyList(); + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKiosk.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKiosk.java index 5e6a9945f..cbaba6613 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKiosk.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKiosk.java @@ -26,1921 +26,7 @@ public class MediaCCCLiveStreamKiosk extends KioskExtractor { @Override public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { - String site = downloader.get("https://streaming.media.ccc.de/streams/v2.json", - getExtractorLocalization()).responseBody(); - // for testing, from - /*site = "[\n" + - " {\n" + - " \"conference\": \"32C3\",\n" + - " \"slug\": \"32c3\",\n" + - " \"author\": \"CCC\",\n" + - " \"description\": \"Live-Streaming vom 32C3\",\n" + - " \"keywords\": \"32C3, Hacking, Chaos Computer Club, Video, Music, Podcast, Media, Streaming, Hacker, Hamburg\",\n" + - " \"startsAt\": \"2015-12-27T05:00:00+0000\",\n" + - " \"endsAt\": \"2015-12-30T20:00:00+0000\",\n" + - " \"groups\": [\n" + - " {\n" + - " \"group\": \"Lecture Rooms\",\n" + - " \"rooms\": [\n" + - " {\n" + - " \"slug\": \"hall1\",\n" + - " \"schedulename\": \"Hall 1\",\n" + - " \"thumb\": \"https://static.media.ccc.de/media/conferences/archconf/2020/6390-hd.jpg\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/hall1?forceopen=yess\",\n" + - " \"display\": \"Hall 1\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"hd-native\",\n" + - " \"display\": \"Hall 1 FullHD Video\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s1_native_hd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s1_native_hd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"hd-translated\",\n" + - " \"display\": \"Hall 1 FullHD Video (Translation)\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s1_translated_hd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s1_translated_hd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"sd-native\",\n" + - " \"display\": \"Hall 1 SD Video\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s1_native_sd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s1_native_sd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"sd-translated\",\n" + - " \"display\": \"Hall 1 SD Video (Translation)\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s1_translated_sd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s1_translated_sd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"slides-native\",\n" + - " \"display\": \"Hall 1 Slides\",\n" + - " \"type\": \"slides\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s1_native_slides.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s1_native_slides.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"slides-translated\",\n" + - " \"display\": \"Hall 1 Slides (Translation)\",\n" + - " \"type\": \"slides\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s1_translated_slides.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s1_translated_slides.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"audio-native\",\n" + - " \"display\": \"Hall 1 Audio\",\n" + - " \"type\": \"audio\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s1_native.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s1_native.opus\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"audio-translated\",\n" + - " \"display\": \"Hall 1 Audio (Translation)\",\n" + - " \"type\": \"audio\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s1_translated.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s1_translated.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"slug\": \"hall2\",\n" + - " \"schedulename\": \"Hall 2\",\n" + - " \"thumb\": \"https://static.media.ccc.de/media/conferences/archconf/2020/6390-hd.jpg\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/hall2?forceopen=yess\",\n" + - " \"display\": \"Hall 2\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"hd-native\",\n" + - " \"display\": \"Hall 2 FullHD Video\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s2_native_hd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s2_native_hd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"hd-translated\",\n" + - " \"display\": \"Hall 2 FullHD Video (Translation)\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s2_translated_hd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s2_translated_hd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"sd-native\",\n" + - " \"display\": \"Hall 2 SD Video\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s2_native_sd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s2_native_sd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"sd-translated\",\n" + - " \"display\": \"Hall 2 SD Video (Translation)\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s2_translated_sd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s2_translated_sd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"slides-native\",\n" + - " \"display\": \"Hall 2 Slides\",\n" + - " \"type\": \"slides\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s2_native_slides.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s2_native_slides.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"slides-translated\",\n" + - " \"display\": \"Hall 2 Slides (Translation)\",\n" + - " \"type\": \"slides\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s2_translated_slides.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s2_translated_slides.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"audio-native\",\n" + - " \"display\": \"Hall 2 Audio\",\n" + - " \"type\": \"audio\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s2_native.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s2_native.opus\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"audio-translated\",\n" + - " \"display\": \"Hall 2 Audio (Translation)\",\n" + - " \"type\": \"audio\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s2_translated.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s2_translated.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"slug\": \"hallg\",\n" + - " \"schedulename\": \"Hall G\",\n" + - " \"thumb\": \"https://static.media.ccc.de/media/events/privacyweek/2020/368-hd.jpg\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/hallg?forceopen=yess\",\n" + - " \"display\": \"Hall G\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"hd-native\",\n" + - " \"display\": \"Hall G FullHD Video\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s3_native_hd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s3_native_hd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"hd-translated\",\n" + - " \"display\": \"Hall G FullHD Video (Translation)\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s3_translated_hd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s3_translated_hd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"sd-native\",\n" + - " \"display\": \"Hall G SD Video\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s3_native_sd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s3_native_sd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"sd-translated\",\n" + - " \"display\": \"Hall G SD Video (Translation)\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s3_translated_sd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s3_translated_sd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"slides-native\",\n" + - " \"display\": \"Hall G Slides\",\n" + - " \"type\": \"slides\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s3_native_slides.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s3_native_slides.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"slides-translated\",\n" + - " \"display\": \"Hall G Slides (Translation)\",\n" + - " \"type\": \"slides\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s3_translated_slides.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s3_translated_slides.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"audio-native\",\n" + - " \"display\": \"Hall G Audio\",\n" + - " \"type\": \"audio\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s3_native.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s3_native.opus\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"audio-translated\",\n" + - " \"display\": \"Hall G Audio (Translation)\",\n" + - " \"type\": \"audio\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s3_translated.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s3_translated.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"slug\": \"hall6\",\n" + - " \"schedulename\": \"Hall 6\",\n" + - " \"thumb\": \"https://static.media.ccc.de/media/conferences/archconf/2020/6307-hd.jpg\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/hall6?forceopen=yess\",\n" + - " \"display\": \"Hall 6\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"hd-native\",\n" + - " \"display\": \"Hall 6 FullHD Video\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s4_native_hd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s4_native_hd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"hd-translated\",\n" + - " \"display\": \"Hall 6 FullHD Video (Translation)\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s4_translated_hd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s4_translated_hd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"sd-native\",\n" + - " \"display\": \"Hall 6 SD Video\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s4_native_sd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s4_native_sd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"sd-translated\",\n" + - " \"display\": \"Hall 6 SD Video (Translation)\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s4_translated_sd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s4_translated_sd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"slides-native\",\n" + - " \"display\": \"Hall 6 Slides\",\n" + - " \"type\": \"slides\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s4_native_slides.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s4_native_slides.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"slides-translated\",\n" + - " \"display\": \"Hall 6 Slides (Translation)\",\n" + - " \"type\": \"slides\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s4_translated_slides.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s4_translated_slides.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"audio-native\",\n" + - " \"display\": \"Hall 6 Audio\",\n" + - " \"type\": \"audio\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s4_native.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s4_native.opus\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"audio-translated\",\n" + - " \"display\": \"Hall 6 Audio (Translation)\",\n" + - " \"type\": \"audio\",\n" + - " \"isTranslated\": true,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s4_translated.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s4_translated.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"group\": \"Live Music\",\n" + - " \"rooms\": [\n" + - " {\n" + - " \"slug\": \"lounge\",\n" + - " \"schedulename\": \"Lounge\",\n" + - " \"thumb\": \"https://static.media.ccc.de/media/events/BigBrotherAwards/2020/2-hd.jpg\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/lounge?forceopen=yess\",\n" + - " \"display\": \"Lounge\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"music-native\",\n" + - " \"display\": \"Lounge Radio\",\n" + - " \"type\": \"music\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 192 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/lounge.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/lounge.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"slug\": \"ambient\",\n" + - " \"schedulename\": \"Ambient\",\n" + - " \"thumb\": \"https://static.media.ccc.de/media/congress/2019/11175-hd.jpg\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/ambient?forceopen=yess\",\n" + - " \"display\": \"Ambient\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"music-native\",\n" + - " \"display\": \"Ambient Radio\",\n" + - " \"type\": \"music\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 192 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/ambient.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/ambient.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"slug\": \"dome\",\n" + - " \"schedulename\": \"Dome\",\n" + - " \"thumb\": \"https://static.media.ccc.de/media/regional/c4/openchaos/2011-hd.jpg\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/dome?forceopen=yess\",\n" + - " \"display\": \"Dome\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"music-native\",\n" + - " \"display\": \"Dome Radio\",\n" + - " \"type\": \"music\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 192 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/dome.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/dome.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"slug\": \"chaos-west\",\n" + - " \"schedulename\": \"Chaos-West\",\n" + - " \"thumb\": \"http://localhost:8000/streams/thumbs/chaos-west.png\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/chaos-west?forceopen=yess\",\n" + - " \"display\": \"Chaos-West\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"music-native\",\n" + - " \"display\": \"Chaos-West Radio\",\n" + - " \"type\": \"music\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 192 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/chaos-west.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/chaos-west.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"slug\": \"radio\",\n" + - " \"schedulename\": \"Radio Fairydust\",\n" + - " \"thumb\": \"http://localhost:8000/streams/thumbs/radio.png\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/radio?forceopen=yess\",\n" + - " \"display\": \"Radio Fairydust\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"music-native\",\n" + - " \"display\": \"Radio Fairydust Radio\",\n" + - " \"type\": \"music\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 192 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/radio.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/radio.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"group\": \"Live Podcasts\",\n" + - " \"rooms\": [\n" + - " {\n" + - " \"slug\": \"sendezentrum\",\n" + - " \"schedulename\": \"Bühne\",\n" + - " \"thumb\": \"http://localhost:8000/streams/thumbs/s5.png\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/sendezentrum?forceopen=yess\",\n" + - " \"display\": \"Sendezentrum\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"hd-native\",\n" + - " \"display\": \"Sendezentrum FullHD Video\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s5_native_hd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s5_native_hd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"sd-native\",\n" + - " \"display\": \"Sendezentrum SD Video\",\n" + - " \"type\": \"video\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ],\n" + - " \"urls\": {\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s5_native_sd.webm\"\n" + - " },\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/hls/s5_native_sd.m3u8\"\n" + - " }\n" + - " }\n" + - " },\n" + - " {\n" + - " \"slug\": \"audio-native\",\n" + - " \"display\": \"Sendezentrum Audio\",\n" + - " \"type\": \"audio\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s5_native.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/s5_native.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"slug\": \"podcastertisch\",\n" + - " \"schedulename\": \"Podcaster-Tisch\",\n" + - " \"thumb\": \"http://localhost:8000/streams/thumbs/podcastertisch.png\",\n" + - " \"link\": \"http://localhost:8000/streams/32c3/podcastertisch?forceopen=yess\",\n" + - " \"display\": \"Sendezentrum - Podcastertisch\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"slug\": \"music-native\",\n" + - " \"display\": \"Sendezentrum - Podcastertisch Radio\",\n" + - " \"type\": \"music\",\n" + - " \"isTranslated\": false,\n" + - " \"videoSize\": null,\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 192 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/podcastertisch.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 96 kBit/s\",\n" + - " \"url\": \"http://cdn.c3voc.de/podcastertisch.opus\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " }\n" + - " ]\n" + - " }\n" + - " ]\n" + - " }\n" + - "]";*/ - /*site = "[\n" + - " {\n" + - " \"author\": \"CCC\",\n" + - " \"conference\": \"33C3\",\n" + - " \"description\": \"Live-Streaming vom 33C3\",\n" + - " \"endsAt\": \"2016-12-30T20:00:00+0000\",\n" + - " \"groups\": [\n" + - " {\n" + - " \"group\": \"Live\",\n" + - " \"rooms\": [\n" + - " {\n" + - " \"display\": \"Saal 1\",\n" + - " \"link\": \"https://streaming.media.ccc.de/33c3/hall1\",\n" + - " \"schedulename\": \"Saal 1\",\n" + - " \"slug\": \"hall1\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"display\": \"Saal 1 FullHD Video\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"hd-native\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s1_native_hd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s1_native_hd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 1 FullHD Video (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"hd-translated\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s1_translated_hd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s1_translated_hd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 1 SD Video\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"sd-native\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s1_native_sd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s1_native_sd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 1 SD Video (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"sd-translated\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s1_translated_sd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s1_translated_sd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 1 Slides\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"slides-native\",\n" + - " \"type\": \"slides\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s1_native_slides.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s1_native_slides.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 1 Slides (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"slides-translated\",\n" + - " \"type\": \"slides\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s1_translated_slides.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s1_translated_slides.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 1 Audio\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"audio-native\",\n" + - " \"type\": \"audio\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s1_native.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s1_native.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 1 Audio (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"audio-translated\",\n" + - " \"type\": \"audio\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s1_translated.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s1_translated.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " }\n" + - " ],\n" + - " \"thumb\": \"https://streaming.media.ccc.de/thumbs/s1.png\"\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 2\",\n" + - " \"link\": \"https://streaming.media.ccc.de/33c3/hall2\",\n" + - " \"schedulename\": \"Saal 2\",\n" + - " \"slug\": \"hall2\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"display\": \"Saal 2 FullHD Video\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"hd-native\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s2_native_hd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s2_native_hd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 2 FullHD Video (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"hd-translated\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s2_translated_hd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s2_translated_hd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 2 SD Video\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"sd-native\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s2_native_sd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s2_native_sd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 2 SD Video (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"sd-translated\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s2_translated_sd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s2_translated_sd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 2 Slides\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"slides-native\",\n" + - " \"type\": \"slides\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s2_native_slides.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s2_native_slides.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 2 Slides (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"slides-translated\",\n" + - " \"type\": \"slides\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s2_translated_slides.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s2_translated_slides.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 2 Audio\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"audio-native\",\n" + - " \"type\": \"audio\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s2_native.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s2_native.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 2 Audio (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"audio-translated\",\n" + - " \"type\": \"audio\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s2_translated.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s2_translated.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " }\n" + - " ],\n" + - " \"thumb\": \"https://streaming.media.ccc.de/thumbs/s2.png\"\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal G\",\n" + - " \"link\": \"https://streaming.media.ccc.de/33c3/hallg\",\n" + - " \"schedulename\": \"Saal G\",\n" + - " \"slug\": \"hallg\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"display\": \"Saal G FullHD Video\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"hd-native\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s3_native_hd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s3_native_hd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal G FullHD Video (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"hd-translated\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s3_translated_hd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s3_translated_hd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal G SD Video\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"sd-native\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s3_native_sd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s3_native_sd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal G SD Video (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"sd-translated\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s3_translated_sd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s3_translated_sd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal G Slides\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"slides-native\",\n" + - " \"type\": \"slides\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s3_native_slides.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s3_native_slides.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal G Slides (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"slides-translated\",\n" + - " \"type\": \"slides\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s3_translated_slides.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s3_translated_slides.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal G Audio\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"audio-native\",\n" + - " \"type\": \"audio\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s3_native.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s3_native.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal G Audio (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"audio-translated\",\n" + - " \"type\": \"audio\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s3_translated.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s3_translated.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " }\n" + - " ],\n" + - " \"thumb\": \"https://streaming.media.ccc.de/thumbs/s3.png\"\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 6\",\n" + - " \"link\": \"https://streaming.media.ccc.de/33c3/hall6\",\n" + - " \"schedulename\": \"Saal 6\",\n" + - " \"slug\": \"hall6\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"display\": \"Saal 6 FullHD Video\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"hd-native\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s4_native_hd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s4_native_hd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 6 FullHD Video (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"hd-translated\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s4_translated_hd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s4_translated_hd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 6 SD Video\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"sd-native\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s4_native_sd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s4_native_sd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 6 SD Video (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"sd-translated\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s4_translated_sd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s4_translated_sd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 6 Slides\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"slides-native\",\n" + - " \"type\": \"slides\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s4_native_slides.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s4_native_slides.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 6 Slides (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"slides-translated\",\n" + - " \"type\": \"slides\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s4_translated_slides.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, XXX kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s4_translated_slides.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 6 Audio\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"audio-native\",\n" + - " \"type\": \"audio\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s4_native.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s4_native.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " },\n" + - " {\n" + - " \"display\": \"Saal 6 Audio (Translation)\",\n" + - " \"isTranslated\": true,\n" + - " \"slug\": \"audio-translated\",\n" + - " \"type\": \"audio\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s4_translated.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s4_translated.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " }\n" + - " ],\n" + - " \"thumb\": \"https://streaming.media.ccc.de/thumbs/s4.png\"\n" + - " },\n" + - " {\n" + - " \"display\": \"Sendezentrum\",\n" + - " \"link\": \"https://streaming.media.ccc.de/33c3/sendezentrum\",\n" + - " \"schedulename\": \"Sendezentrum\",\n" + - " \"slug\": \"sendezentrum\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"display\": \"Sendezentrum FullHD Video\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"hd-native\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s5_native_hd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s5_native_hd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1920,\n" + - " 1080\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Sendezentrum SD Video\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"sd-native\",\n" + - " \"type\": \"video\",\n" + - " \"urls\": {\n" + - " \"hls\": {\n" + - " \"display\": \"HLS\",\n" + - " \"tech\": \"1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/hls/s5_native_sd.m3u8\"\n" + - " },\n" + - " \"webm\": {\n" + - " \"display\": \"WebM\",\n" + - " \"tech\": \"1024x576, VP8+Vorbis in WebM, 800 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s5_native_sd.webm\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": [\n" + - " 1024,\n" + - " 576\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"display\": \"Sendezentrum Audio\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"audio-native\",\n" + - " \"type\": \"audio\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s5_native.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 64 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/s5_native.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " }\n" + - " ],\n" + - " \"thumb\": \"https://streaming.media.ccc.de/thumbs/s5.png\"\n" + - " }\n" + - " ]\n" + - " },\n" + - " {\n" + - " \"group\": \"Live Music\",\n" + - " \"rooms\": [\n" + - " {\n" + - " \"display\": \"Section 9\",\n" + - " \"link\": \"https://streaming.media.ccc.de/33c3/section-9\",\n" + - " \"schedulename\": \"Section 9\",\n" + - " \"slug\": \"section-9\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"display\": \"Section 9 Radio\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"music-native\",\n" + - " \"type\": \"music\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 192 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/ambient.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/ambient.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " }\n" + - " ],\n" + - " \"thumb\": \"https://streaming.media.ccc.de/thumbs/ambient.png\"\n" + - " },\n" + - " {\n" + - " \"display\": \"DisKo\",\n" + - " \"link\": \"https://streaming.media.ccc.de/33c3/disko\",\n" + - " \"schedulename\": \"DisKo\",\n" + - " \"slug\": \"disko\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"display\": \"DisKo Radio\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"music-native\",\n" + - " \"type\": \"music\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 192 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/lounge.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/lounge.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " }\n" + - " ],\n" + - " \"thumb\": \"https://streaming.media.ccc.de/thumbs/lounge.png\"\n" + - " },\n" + - " {\n" + - " \"display\": \"Schneekugel\",\n" + - " \"link\": \"https://streaming.media.ccc.de/33c3/schneekugel\",\n" + - " \"schedulename\": \"Schneekugel\",\n" + - " \"slug\": \"schneekugel\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"display\": \"Schneekugel Radio\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"music-native\",\n" + - " \"type\": \"music\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 192 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/dome.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/dome.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " }\n" + - " ],\n" + - " \"thumb\": \"https://streaming.media.ccc.de/thumbs/dome.png\"\n" + - " },\n" + - " {\n" + - " \"display\": \"Chaoswest\",\n" + - " \"link\": \"https://streaming.media.ccc.de/33c3/chaoswest\",\n" + - " \"schedulename\": \"Chaoswest\",\n" + - " \"slug\": \"chaoswest\",\n" + - " \"streams\": [\n" + - " {\n" + - " \"display\": \"Chaoswest Radio\",\n" + - " \"isTranslated\": false,\n" + - " \"slug\": \"music-native\",\n" + - " \"type\": \"music\",\n" + - " \"urls\": {\n" + - " \"mp3\": {\n" + - " \"display\": \"MP3\",\n" + - " \"tech\": \"MP3-Audio, 192 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/chaoswest_lounge.mp3\"\n" + - " },\n" + - " \"opus\": {\n" + - " \"display\": \"Opus\",\n" + - " \"tech\": \"Opus-Audio, 96 kBit/s\",\n" + - " \"url\": \"https://cdn.c3voc.de/chaoswest_lounge.opus\"\n" + - " }\n" + - " },\n" + - " \"videoSize\": null\n" + - " }\n" + - " ],\n" + - " \"thumb\": \"https://streaming.media.ccc.de/thumbs/chaoswest_lounge.png\"\n" + - " }\n" + - " ]\n" + - " }\n" + - " ],\n" + - " \"keywords\": \"33C3, Hacking, Chaos Computer Club, Video, Music, Podcast, Media, Streaming, Hacker, Hamburg, Works, For, Me, Chaos, Everywhere\",\n" + - " \"slug\": \"33c3\",\n" + - " \"startsAt\": \"2016-12-27T05:00:00+0000\"\n" + - " }\n" + - "]\n";*/ - try { - doc = JsonParser.array().from(site); - } catch (JsonParserException jpe) { - throw new ExtractionException("Could not parse json.", jpe); - } + doc = MediaCCCParsingHelper.getLiveStreams(downloader, getExtractorLocalization()); } @Nonnull @@ -1955,7 +41,7 @@ public class MediaCCCLiveStreamKiosk extends KioskExtractor { final JsonArray rooms = groups.getObject(g).getArray("rooms"); for (int r = 0; r < rooms.size(); r++) { final JsonObject room = rooms.getObject(r); - collector.commit(new MediaCCCLiveStreamExtractor(conference, group, room)); + collector.commit(new MediaCCCLiveStreamKioskExtractor(conference, group, room)); } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKioskExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKioskExtractor.java new file mode 100644 index 000000000..941528708 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKioskExtractor.java @@ -0,0 +1,87 @@ +package org.schabi.newpipe.extractor.services.media_ccc.extractors; + +import com.grack.nanojson.JsonObject; +import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.localization.DateWrapper; +import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; +import org.schabi.newpipe.extractor.stream.StreamType; + +import javax.annotation.Nullable; + +public class MediaCCCLiveStreamKioskExtractor implements StreamInfoItemExtractor { + + private final JsonObject conferenceInfo; + private final String group; + private final JsonObject roomInfo; + + public MediaCCCLiveStreamKioskExtractor(final JsonObject conferenceInfo, final String group, + final JsonObject roomInfo) { + this.conferenceInfo = conferenceInfo; + this.group = group; + this.roomInfo = roomInfo; + } + + @Override + public String getName() throws ParsingException { + return roomInfo.getString("schedulename"); + } + + @Override + public String getUrl() throws ParsingException { + return roomInfo.getString("link"); + } + + @Override + public String getThumbnailUrl() throws ParsingException { + return roomInfo.getString("thumb"); + } + + @Override + public StreamType getStreamType() throws ParsingException { + boolean isVideo = false; + for (Object stream : roomInfo.getArray("streams")) { + if ("video".equals(((JsonObject) stream).getString("type"))) { + isVideo = true; + break; + } + } + return isVideo ? StreamType.LIVE_STREAM : StreamType.AUDIO_LIVE_STREAM; + } + + @Override + public boolean isAd() throws ParsingException { + return false; + } + + @Override + public long getDuration() throws ParsingException { + return 0; + } + + @Override + public long getViewCount() throws ParsingException { + return -1; + } + + @Override + public String getUploaderName() throws ParsingException { + return conferenceInfo.getString("conference"); + } + + @Override + public String getUploaderUrl() throws ParsingException { + return "https://media.ccc.de/c/" + conferenceInfo.getString("slug"); + } + + @Nullable + @Override + public String getTextualUploadDate() throws ParsingException { + return null; + } + + @Nullable + @Override + public DateWrapper getUploadDate() throws ParsingException { + return null; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCParsingHelper.java index b6879fcdf..421482434 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCParsingHelper.java @@ -1,11 +1,23 @@ package org.schabi.newpipe.extractor.services.media_ccc.extractors; +import com.grack.nanojson.JsonArray; +import com.grack.nanojson.JsonObject; +import com.grack.nanojson.JsonParser; +import com.grack.nanojson.JsonParserException; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; +import org.schabi.newpipe.extractor.localization.Localization; +import java.io.IOException; import java.time.OffsetDateTime; import java.time.format.DateTimeParseException; +import java.util.regex.Pattern; public final class MediaCCCParsingHelper { + private static JsonArray liveStreams = null; + private MediaCCCParsingHelper() { } public static OffsetDateTime parseDateFrom(final String textualUploadDate) throws ParsingException { @@ -15,4 +27,24 @@ public final class MediaCCCParsingHelper { throw new ParsingException("Could not parse date: \"" + textualUploadDate + "\"", e); } } + + public static boolean isLiveStreamId(final String url) { + final String pattern = "\\w+/\\w+"; + return Pattern.matches(pattern, url); // {conference_slug}/{room_slug} + } + + public static JsonArray getLiveStreams(final Downloader downloader, final Localization localization) throws ExtractionException { + if (liveStreams == null) { + try { + final String site = downloader.get("https://streaming.media.ccc.de/streams/v2.json", + localization).responseBody(); + liveStreams = JsonParser.array().from(site); + } catch (IOException | ReCaptchaException e) { + throw new ExtractionException("Could not get live stream JSON.", e); + } catch (JsonParserException e) { + throw new ExtractionException("Could not parse JSON.", e); + } + } + return liveStreams; + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveStreamListLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveListLinkHandlerFactory.java similarity index 76% rename from extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveStreamListLinkHandlerFactory.java rename to extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveListLinkHandlerFactory.java index 3dc5c46ea..84009c2bf 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveStreamListLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveListLinkHandlerFactory.java @@ -6,8 +6,8 @@ import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; import java.util.List; import java.util.regex.Pattern; -public class MediaCCCLiveStreamListLinkHandlerFactory extends ListLinkHandlerFactory { - private static final String streamPattern = "^(https?://)?streaming.media.ccc.de$"; +public class MediaCCCLiveListLinkHandlerFactory extends ListLinkHandlerFactory { + private static final String streamPattern = "^(?:https?://)?media\\.ccc\\.de/live$"; @Override public String getId(String url) throws ParsingException { @@ -22,6 +22,6 @@ public class MediaCCCLiveStreamListLinkHandlerFactory extends ListLinkHandlerFac @Override public String getUrl(String id, List contentFilter, String sortFilter) throws ParsingException { // FIXME: wrong URL; should be https://streaming.media.ccc.de/{conference_slug}/{room_slug} - return "https://streaming.media.ccc.de/" + id; + return "https://media.ccc.de/live"; } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveStreamLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveStreamLinkHandlerFactory.java new file mode 100644 index 000000000..9c88e026f --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCLiveStreamLinkHandlerFactory.java @@ -0,0 +1,30 @@ +package org.schabi.newpipe.extractor.services.media_ccc.linkHandler; + +import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; +import org.schabi.newpipe.extractor.utils.Parser; + +public class MediaCCCLiveStreamLinkHandlerFactory extends LinkHandlerFactory { + public static final String VIDEO_API_ENDPOINT = "https://api.media.ccc.de/public/events/"; + private static final String VIDEO_PATH = "https://streaming.media.ccc.de/v/"; + private static final String ID_PATTERN = "(?:(?:(?:api\\.)?media\\.ccc\\.de/public/events/)|(?:media\\.ccc\\.de/v/))([^/?&#]*)"; + + @Override + public String getId(final String url) throws ParsingException { + return Parser.matchGroup1(ID_PATTERN, url); + } + + @Override + public String getUrl(final String id) throws ParsingException { + return VIDEO_PATH + id; + } + + @Override + public boolean onAcceptUrl(final String url) { + try { + return getId(url) != null; + } catch (ParsingException e) { + return false; + } + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCStreamLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCStreamLinkHandlerFactory.java index fa9ac4829..cb2f72fc9 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCStreamLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/linkHandler/MediaCCCStreamLinkHandlerFactory.java @@ -2,20 +2,36 @@ package org.schabi.newpipe.extractor.services.media_ccc.linkHandler; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; +import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper; import org.schabi.newpipe.extractor.utils.Parser; public class MediaCCCStreamLinkHandlerFactory extends LinkHandlerFactory { public static final String VIDEO_API_ENDPOINT = "https://api.media.ccc.de/public/events/"; private static final String VIDEO_PATH = "https://media.ccc.de/v/"; - private static final String ID_PATTERN = "(?:(?:(?:api\\.)?media\\.ccc\\.de/public/events/)|(?:media\\.ccc\\.de/v/))([^/?&#]*)"; + private static final String RECORDING_ID_PATTERN = "(?:(?:(?:api\\.)?media\\.ccc\\.de/public/events/)|(?:media\\.ccc\\.de/v/))([^/?&#]*)"; + private static final String LIVE_STREAM_API_ENDPOINT = "https://streaming.media.ccc.de/streams/v2.json"; + private static final String LIVE_STREAM_PATH = "https://streaming.media.ccc.de/"; + private static final String LIVE_STREAM_ID_PATTERN = "streaming\\.media\\.ccc\\.de\\/(\\w+\\/\\w+)"; @Override public String getId(final String url) throws ParsingException { - return Parser.matchGroup1(ID_PATTERN, url); + String streamId = null; + try { + streamId = Parser.matchGroup1(LIVE_STREAM_ID_PATTERN, url); + } catch (Parser.RegexException ignored) { + + } + if (streamId == null) { + return Parser.matchGroup1(RECORDING_ID_PATTERN, url); + } + return streamId; } @Override public String getUrl(final String id) throws ParsingException { + if (MediaCCCParsingHelper.isLiveStreamId(id)) { + return LIVE_STREAM_PATH + id; + } return VIDEO_PATH + id; }