Add stream segments to StreamInfo
This commit is contained in:
parent
b3835bd616
commit
d3eea4f4be
|
@ -16,6 +16,7 @@ import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||||
import org.schabi.newpipe.extractor.stream.Description;
|
import org.schabi.newpipe.extractor.stream.Description;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamSegment;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
|
@ -294,4 +295,10 @@ public class MediaCCCStreamExtractor extends StreamExtractor {
|
||||||
public String getSupportInfo() {
|
public String getSupportInfo() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<StreamSegment> getStreamSegments() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.schabi.newpipe.extractor.stream.Description;
|
||||||
import org.schabi.newpipe.extractor.stream.Stream;
|
import org.schabi.newpipe.extractor.stream.Stream;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamSegment;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
|
@ -302,6 +303,12 @@ public class PeertubeStreamExtractor extends StreamExtractor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<StreamSegment> getStreamSegments() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
private String getRelatedStreamsUrl(final List<String> tags) throws UnsupportedEncodingException {
|
private String getRelatedStreamsUrl(final List<String> tags) throws UnsupportedEncodingException {
|
||||||
final String url = baseUrl + PeertubeSearchQueryHandlerFactory.SEARCH_ENDPOINT;
|
final String url = baseUrl + PeertubeSearchQueryHandlerFactory.SEARCH_ENDPOINT;
|
||||||
final StringBuilder params = new StringBuilder();
|
final StringBuilder params = new StringBuilder();
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||||
import org.schabi.newpipe.extractor.stream.Description;
|
import org.schabi.newpipe.extractor.stream.Description;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamSegment;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
|
@ -320,4 +321,10 @@ public class SoundcloudStreamExtractor extends StreamExtractor {
|
||||||
public String getSupportInfo() {
|
public String getSupportInfo() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<StreamSegment> getStreamSegments() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.schabi.newpipe.extractor.stream.Stream;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamSegment;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
|
@ -1061,4 +1062,58 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
public String getSupportInfo() {
|
public String getSupportInfo() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<StreamSegment> getStreamSegments() throws ParsingException {
|
||||||
|
final ArrayList<StreamSegment> segments = new ArrayList<>();
|
||||||
|
if (initialData.has("engagementPanels")) {
|
||||||
|
final JsonArray panels = initialData.getArray("engagementPanels");
|
||||||
|
JsonArray segmentsArray = null;
|
||||||
|
|
||||||
|
// Search for correct panel containing the data
|
||||||
|
for (int i = 0; i < panels.size(); i++) {
|
||||||
|
if (panels.getObject(i).getObject("engagementPanelSectionListRenderer")
|
||||||
|
.getString("panelIdentifier").equals("engagement-panel-macro-markers")) {
|
||||||
|
segmentsArray = panels.getObject(i).getObject("engagementPanelSectionListRenderer")
|
||||||
|
.getObject("content").getObject("macroMarkersListRenderer").getArray("contents");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segmentsArray != null) {
|
||||||
|
final long duration = getLength();
|
||||||
|
for (final Object object : segmentsArray) {
|
||||||
|
final JsonObject segmentJson = ((JsonObject) object).getObject("macroMarkersListItemRenderer");
|
||||||
|
|
||||||
|
final int startTimeSeconds = segmentJson.getObject("onTap").getObject("watchEndpoint")
|
||||||
|
.getInt("startTimeSeconds", -1);
|
||||||
|
|
||||||
|
if (startTimeSeconds == -1) {
|
||||||
|
throw new ParsingException("Could not get stream segment start time.");
|
||||||
|
}
|
||||||
|
if (startTimeSeconds > duration) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String title = getTextFromObject(segmentJson.getObject("title"));
|
||||||
|
if (isNullOrEmpty(title)) {
|
||||||
|
throw new ParsingException("Could not get stream segment title.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final StreamSegment segment = new StreamSegment(title, startTimeSeconds);
|
||||||
|
segment.setUrl(getUrl() + "?t=" + startTimeSeconds);
|
||||||
|
if (segmentJson.has("thumbnail")) {
|
||||||
|
final JsonArray previewsArray = segmentJson.getObject("thumbnail").getArray("thumbnails");
|
||||||
|
if (!previewsArray.isEmpty()) {
|
||||||
|
// Assume that the thumbnail with the highest resolution is at the last position
|
||||||
|
segment.setPreviewUrl(previewsArray.getObject(previewsArray.size() - 1).getString("url"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
segments.add(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return segments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,4 +476,14 @@ public abstract class StreamExtractor extends Extractor {
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public abstract String getSupportInfo() throws ParsingException;
|
public abstract String getSupportInfo() throws ParsingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of stream segments by timestamps for the stream.
|
||||||
|
* If the segment list is not available you can simply return an empty list.
|
||||||
|
*
|
||||||
|
* @return The list of segments of the stream or an empty list.
|
||||||
|
* @throws ParsingException
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
public abstract List<StreamSegment> getStreamSegments() throws ParsingException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,6 +324,11 @@ public class StreamInfo extends Info {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
streamInfo.addError(e);
|
streamInfo.addError(e);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
streamInfo.setStreamSegments(extractor.getStreamSegments());
|
||||||
|
} catch (Exception e) {
|
||||||
|
streamInfo.addError(e);
|
||||||
|
}
|
||||||
|
|
||||||
streamInfo.setRelatedStreams(ExtractorHelper.getRelatedVideosOrLogError(streamInfo, extractor));
|
streamInfo.setRelatedStreams(ExtractorHelper.getRelatedVideosOrLogError(streamInfo, extractor));
|
||||||
|
|
||||||
|
@ -373,6 +378,7 @@ public class StreamInfo extends Info {
|
||||||
private String support = "";
|
private String support = "";
|
||||||
private Locale language = null;
|
private Locale language = null;
|
||||||
private List<String> tags = new ArrayList<>();
|
private List<String> tags = new ArrayList<>();
|
||||||
|
private List<StreamSegment> streamSegments = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the stream type
|
* Get the stream type
|
||||||
|
@ -670,4 +676,12 @@ public class StreamInfo extends Info {
|
||||||
public String getSupportInfo() {
|
public String getSupportInfo() {
|
||||||
return this.support;
|
return this.support;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<StreamSegment> getStreamSegments() {
|
||||||
|
return streamSegments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStreamSegments(List<StreamSegment> streamSegments) {
|
||||||
|
this.streamSegments = streamSegments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.schabi.newpipe.extractor.stream;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class StreamSegment implements Serializable {
|
||||||
|
/**
|
||||||
|
* Title of this segment
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp of the starting point in seconds
|
||||||
|
*/
|
||||||
|
private int startTimeSeconds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Direct url to this segment. This can be null if the service doesn't provide such function.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preview url for this segment. This can be null if the service doesn't provide such function
|
||||||
|
* or there is no resource found.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private String previewUrl = null;
|
||||||
|
|
||||||
|
public StreamSegment(String title, int startTimeSeconds) {
|
||||||
|
this.title = title;
|
||||||
|
this.startTimeSeconds = startTimeSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(final String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStartTimeSeconds() {
|
||||||
|
return startTimeSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartTimeSeconds(final int startTimeSeconds) {
|
||||||
|
this.startTimeSeconds = startTimeSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(@Nullable final String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getPreviewUrl() {
|
||||||
|
return previewUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreviewUrl(@Nullable final String previewUrl) {
|
||||||
|
this.previewUrl = previewUrl.replaceAll("\\u0026", "&");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue