Extract stream duration as a Java 8 Duration
This commit is contained in:
parent
592f1596e6
commit
0261e637d3
|
@ -11,7 +11,7 @@ import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.BASE_URL;
|
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.BASE_URL;
|
||||||
|
@ -26,13 +26,14 @@ public class BandcampRadioInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
show = radioShow;
|
show = radioShow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() {
|
public Duration getDurationObject() {
|
||||||
/* Duration is only present in the more detailed information that has to be queried
|
/* Duration is only present in the more detailed information that has to be queried
|
||||||
separately. Therefore, over 300 queries would be needed every time the kiosk is opened if we
|
separately. Therefore, over 300 queries would be needed every time the kiosk is opened if we
|
||||||
were to display the real value. */
|
were to display the real value. */
|
||||||
//return query(show.getInt("id")).getLong("audio_duration");
|
//return Duration.ofSeconds(query(show.getInt("id")).getLong("audio_duration"));
|
||||||
return 0;
|
return Duration.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
|
@ -43,9 +43,4 @@ public class BandcampDiscographStreamInfoItemExtractor extends BandcampStreamInf
|
||||||
public List<Image> getThumbnails() throws ParsingException {
|
public List<Image> getThumbnails() throws ParsingException {
|
||||||
return getImagesFromImageId(discograph.getLong("art_id"), true);
|
return getImagesFromImageId(discograph.getLong("art_id"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDuration() {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -46,9 +47,10 @@ public class BandcampPlaylistStreamInfoItemExtractor extends BandcampStreamInfoI
|
||||||
return getUploaderUrl() + track.getString("title_link");
|
return getUploaderUrl() + track.getString("title_link");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() {
|
public Duration getDurationObject() {
|
||||||
return track.getLong("duration");
|
return Duration.ofSeconds(track.getLong("duration"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -47,9 +47,4 @@ public class BandcampSearchStreamInfoItemExtractor extends BandcampStreamInfoIte
|
||||||
public List<Image> getThumbnails() throws ParsingException {
|
public List<Image> getThumbnails() throws ParsingException {
|
||||||
return getImagesFromSearchResult(searchResult);
|
return getImagesFromSearchResult(searchResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDuration() {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,11 +60,6 @@ public class MediaCCCLiveStreamKioskExtractor implements StreamInfoItemExtractor
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDuration() throws ParsingException {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getViewCount() throws ParsingException {
|
public long getViewCount() throws ParsingException {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class MediaCCCRecentKiosk extends KioskExtractor<StreamInfoItem> {
|
||||||
.map(JsonObject.class::cast)
|
.map(JsonObject.class::cast)
|
||||||
.map(MediaCCCRecentKioskExtractor::new)
|
.map(MediaCCCRecentKioskExtractor::new)
|
||||||
// #813 / voc/voctoweb#609 -> returns faulty data -> filter it out
|
// #813 / voc/voctoweb#609 -> returns faulty data -> filter it out
|
||||||
.filter(extractor -> extractor.getDuration() > 0)
|
.filter(extractor -> !extractor.getDurationObject().isZero())
|
||||||
.forEach(collector::commit);
|
.forEach(collector::commit);
|
||||||
|
|
||||||
return new InfoItemsPage<>(collector, null);
|
return new InfoItemsPage<>(collector, null);
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConfe
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -53,10 +54,11 @@ public class MediaCCCRecentKioskExtractor implements StreamInfoItemExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() {
|
@Nonnull
|
||||||
|
public Duration getDurationObject() {
|
||||||
// duration and length have the same value, see
|
// duration and length have the same value, see
|
||||||
// https://github.com/voc/voctoweb/blob/master/app/views/public/shared/_event.json.jbuilder
|
// https://github.com/voc/voctoweb/blob/master/app/views/public/shared/_event.json.jbuilder
|
||||||
return event.getInt("duration");
|
return Duration.ofSeconds(event.getLong("duration"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper.getThumbnailsFromStreamItem;
|
import static org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper.getThumbnailsFromStreamItem;
|
||||||
|
@ -32,8 +33,9 @@ public class MediaCCCStreamInfoItemExtractor implements StreamInfoItemExtractor
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() {
|
@Nonnull
|
||||||
return event.getInt("length");
|
public Duration getDurationObject() {
|
||||||
|
return Duration.ofSeconds(event.getLong("length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import org.schabi.newpipe.extractor.utils.JsonUtils;
|
import org.schabi.newpipe.extractor.utils.JsonUtils;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.getAvatarsFromOwnerAccountOrVideoChannelObject;
|
import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.getAvatarsFromOwnerAccountOrVideoChannelObject;
|
||||||
|
@ -100,8 +101,9 @@ public class PeertubeStreamInfoItemExtractor implements StreamInfoItemExtractor
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() {
|
@Nonnull
|
||||||
return item.getLong("duration");
|
public Duration getDurationObject() {
|
||||||
|
return Duration.ofSeconds(item.getLong("duration"));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setBaseUrl(final String baseUrl) {
|
protected void setBaseUrl(final String baseUrl) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper.getAllImagesFromArtworkOrAvatarUrl;
|
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper.getAllImagesFromArtworkOrAvatarUrl;
|
||||||
|
@ -35,8 +36,9 @@ public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtracto
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() {
|
@Nonnull
|
||||||
return itemObject.getLong("duration") / 1000L;
|
public Duration getDurationObject() {
|
||||||
|
return Duration.ofMillis(itemObject.getLong("duration"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -32,8 +32,8 @@ import com.grack.nanojson.JsonObject;
|
||||||
import com.grack.nanojson.JsonParser;
|
import com.grack.nanojson.JsonParser;
|
||||||
import com.grack.nanojson.JsonParserException;
|
import com.grack.nanojson.JsonParserException;
|
||||||
import com.grack.nanojson.JsonWriter;
|
import com.grack.nanojson.JsonWriter;
|
||||||
|
|
||||||
import org.jsoup.nodes.Entities;
|
import org.jsoup.nodes.Entities;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.Image;
|
import org.schabi.newpipe.extractor.Image;
|
||||||
import org.schabi.newpipe.extractor.Image.ResolutionLevel;
|
import org.schabi.newpipe.extractor.Image.ResolutionLevel;
|
||||||
import org.schabi.newpipe.extractor.downloader.Response;
|
import org.schabi.newpipe.extractor.downloader.Response;
|
||||||
|
@ -56,10 +56,12 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -310,21 +312,22 @@ public final class YoutubeParsingHelper {
|
||||||
* @return the duration in seconds
|
* @return the duration in seconds
|
||||||
* @throws ParsingException when more than 3 separators are found
|
* @throws ParsingException when more than 3 separators are found
|
||||||
*/
|
*/
|
||||||
public static int parseDurationString(@Nonnull final String input)
|
public static Duration parseDurationString(@Nonnull final String input)
|
||||||
throws ParsingException, NumberFormatException {
|
throws ParsingException {
|
||||||
// If time separator : is not detected, try . instead
|
// If time separator : is not detected, try . instead
|
||||||
final String[] splitInput = input.contains(":")
|
final String[] splitInput = input.contains(":")
|
||||||
? input.split(":")
|
? input.split(":")
|
||||||
: input.split("\\.");
|
: input.split("\\.");
|
||||||
|
|
||||||
final int[] units = {24, 60, 60, 1};
|
final var units = List.of(ChronoUnit.DAYS, ChronoUnit.HOURS, ChronoUnit.MINUTES,
|
||||||
final int offset = units.length - splitInput.length;
|
ChronoUnit.SECONDS);
|
||||||
|
final int offset = units.size() - splitInput.length;
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
throw new ParsingException("Error duration string with unknown format: " + input);
|
throw new ParsingException("Error duration string with unknown format: " + input);
|
||||||
}
|
}
|
||||||
int duration = 0;
|
Duration duration = Duration.ZERO;
|
||||||
for (int i = 0; i < splitInput.length; i++) {
|
for (int i = 0; i < splitInput.length; i++) {
|
||||||
duration = units[i + offset] * (duration + convertDurationToInt(splitInput[i]));
|
duration = duration.plus(convertDurationToInt(splitInput[i]), units.get(i + offset));
|
||||||
}
|
}
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
|
@ -341,11 +344,7 @@ public final class YoutubeParsingHelper {
|
||||||
* @return The converted integer or 0 if the conversion failed.
|
* @return The converted integer or 0 if the conversion failed.
|
||||||
*/
|
*/
|
||||||
private static int convertDurationToInt(final String input) {
|
private static int convertDurationToInt(final String input) {
|
||||||
if (input == null || input.isEmpty()) {
|
final String clearedInput = input != null ? Utils.removeNonDigitCharacters(input) : "";
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String clearedInput = Utils.removeNonDigitCharacters(input);
|
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(clearedInput);
|
return Integer.parseInt(clearedInput);
|
||||||
} catch (final NumberFormatException ex) {
|
} catch (final NumberFormatException ex) {
|
||||||
|
|
|
@ -33,12 +33,6 @@ public class YoutubeFeedInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDuration() {
|
|
||||||
// Not available when fetching through the feed endpoint.
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getViewCount() {
|
public long getViewCount() {
|
||||||
return Long.parseLong(entryElement.getElementsByTag("media:statistics").first()
|
return Long.parseLong(entryElement.getElementsByTag("media:statistics").first()
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.schabi.newpipe.extractor.utils.Parser;
|
||||||
import org.schabi.newpipe.extractor.utils.Utils;
|
import org.schabi.newpipe.extractor.utils.Utils;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
|
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
|
||||||
|
@ -67,7 +68,8 @@ public class YoutubeMusicSongOrVideoInfoItemExtractor implements StreamInfoItemE
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() throws ParsingException {
|
@Nonnull
|
||||||
|
public Duration getDurationObject() throws ParsingException {
|
||||||
final String duration = descriptionElements.getObject(descriptionElements.size() - 1)
|
final String duration = descriptionElements.getObject(descriptionElements.size() - 1)
|
||||||
.getString("text");
|
.getString("text");
|
||||||
if (!isNullOrEmpty(duration)) {
|
if (!isNullOrEmpty(duration)) {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper
|
||||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||||
|
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.Image;
|
import org.schabi.newpipe.extractor.Image;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
import org.schabi.newpipe.extractor.localization.DateWrapper;
|
import org.schabi.newpipe.extractor.localization.DateWrapper;
|
||||||
|
@ -90,11 +89,6 @@ public class YoutubeReelInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDuration() throws ParsingException {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUploaderName() throws ParsingException {
|
public String getUploaderName() throws ParsingException {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -41,7 +41,7 @@ import org.schabi.newpipe.extractor.utils.Utils;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
@ -136,10 +136,11 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
throw new ParsingException("Could not get name");
|
throw new ParsingException("Could not get name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() throws ParsingException {
|
public Duration getDurationObject() throws ParsingException {
|
||||||
if (getStreamType() == StreamType.LIVE_STREAM) {
|
if (getStreamType() == StreamType.LIVE_STREAM) {
|
||||||
return -1;
|
return Duration.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
String duration = getTextFromObject(videoInfo.getObject("lengthText"));
|
String duration = getTextFromObject(videoInfo.getObject("lengthText"));
|
||||||
|
@ -169,7 +170,7 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
if (isPremiere()) {
|
if (isPremiere()) {
|
||||||
// Premieres can be livestreams, so the duration is not available in this
|
// Premieres can be livestreams, so the duration is not available in this
|
||||||
// case
|
// case
|
||||||
return -1;
|
return Duration.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ParsingException("Could not get duration");
|
throw new ParsingException("Could not get duration");
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.schabi.newpipe.extractor.localization.DateWrapper;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +41,8 @@ public class StreamInfoItem extends InfoItem {
|
||||||
@Nullable
|
@Nullable
|
||||||
private DateWrapper uploadDate;
|
private DateWrapper uploadDate;
|
||||||
private long viewCount = -1;
|
private long viewCount = -1;
|
||||||
private long duration = -1;
|
@Nonnull
|
||||||
|
private Duration duration = Duration.ZERO;
|
||||||
|
|
||||||
private String uploaderUrl = null;
|
private String uploaderUrl = null;
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -76,12 +78,21 @@ public class StreamInfoItem extends InfoItem {
|
||||||
this.viewCount = viewCount;
|
this.viewCount = viewCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getDuration() {
|
@Nonnull
|
||||||
|
public Duration getDurationObject() {
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDurationObject(@Nonnull final Duration durationObject) {
|
||||||
|
this.duration = durationObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDuration() {
|
||||||
|
return duration.toSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
public void setDuration(final long duration) {
|
public void setDuration(final long duration) {
|
||||||
this.duration = duration;
|
this.duration = Duration.ofSeconds(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUploaderUrl() {
|
public String getUploaderUrl() {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.schabi.newpipe.extractor.localization.DateWrapper;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface StreamInfoItemExtractor extends InfoItemExtractor {
|
public interface StreamInfoItemExtractor extends InfoItemExtractor {
|
||||||
|
@ -48,12 +49,25 @@ public interface StreamInfoItemExtractor extends InfoItemExtractor {
|
||||||
boolean isAd() throws ParsingException;
|
boolean isAd() throws ParsingException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the stream duration in seconds
|
* Get the stream duration as a {@link Duration}.
|
||||||
*
|
*
|
||||||
* @return the stream duration in seconds or -1 if no duration is available
|
* @return the stream duration in seconds or {@link Duration#ZERO} if no duration is available
|
||||||
* @throws ParsingException if there is an error in the extraction
|
* @throws ParsingException if there is an error in the extraction
|
||||||
*/
|
*/
|
||||||
long getDuration() throws ParsingException;
|
@Nonnull
|
||||||
|
default Duration getDurationObject() throws ParsingException {
|
||||||
|
return Duration.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the stream duration in seconds.
|
||||||
|
*
|
||||||
|
* @return the stream duration in seconds or 0 if no duration is available
|
||||||
|
* @throws ParsingException if there is an error in the extraction
|
||||||
|
*/
|
||||||
|
default long getDuration() throws ParsingException {
|
||||||
|
return getDurationObject().toSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the number of views
|
* Parses the number of views
|
||||||
|
|
|
@ -44,12 +44,12 @@ public class StreamInfoItemsCollector
|
||||||
throw new FoundAdException("Found ad");
|
throw new FoundAdException("Found ad");
|
||||||
}
|
}
|
||||||
|
|
||||||
final StreamInfoItem resultItem = new StreamInfoItem(
|
final var resultItem = new StreamInfoItem(getServiceId(), extractor.getUrl(),
|
||||||
getServiceId(), extractor.getUrl(), extractor.getName(), extractor.getStreamType());
|
extractor.getName(), extractor.getStreamType());
|
||||||
|
|
||||||
// optional information
|
// optional information
|
||||||
try {
|
try {
|
||||||
resultItem.setDuration(extractor.getDuration());
|
resultItem.setDurationObject(extractor.getDurationObject());
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
addError(e);
|
addError(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -99,12 +100,9 @@ public class ExtractorAsserts {
|
||||||
assertGreater(expected, actual, actual + " is not > " + expected);
|
assertGreater(expected, actual, actual + " is not > " + expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertGreater(
|
public static <T extends Comparable<T>> void assertGreater(final T expected, final T actual,
|
||||||
final long expected,
|
final String message) {
|
||||||
final long actual,
|
assertTrue(actual.compareTo(expected) > 0, message);
|
||||||
final String message
|
|
||||||
) {
|
|
||||||
assertTrue(actual > expected, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertGreaterOrEqual(final long expected, final long actual) {
|
public static void assertGreaterOrEqual(final long expected, final long actual) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
|
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@ -41,9 +42,9 @@ public class MediaCCCRecentListExtractorTest {
|
||||||
isNullOrEmpty(item.getName()),
|
isNullOrEmpty(item.getName()),
|
||||||
"Name=[" + item.getName() + "] of " + item + " is empty or null"
|
"Name=[" + item.getName() + "] of " + item + " is empty or null"
|
||||||
),
|
),
|
||||||
() -> assertGreater(0,
|
() -> assertGreater(Duration.ZERO,
|
||||||
item.getDuration(),
|
item.getDurationObject(),
|
||||||
"Duration[=" + item.getDuration() + "] of " + item + " is <= 0"
|
"Duration[=" + item.getDurationObject() + "] of " + item + " is <= 0"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
import org.schabi.newpipe.extractor.stream.AudioTrackType;
|
import org.schabi.newpipe.extractor.stream.AudioTrackType;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
@ -38,9 +39,12 @@ public class YoutubeParsingHelperTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParseDurationString() throws ParsingException {
|
void testParseDurationString() throws ParsingException {
|
||||||
assertEquals(1162567, YoutubeParsingHelper.parseDurationString("12:34:56:07"));
|
assertEquals(Duration.ofDays(12).plusHours(34).plusMinutes(56).plusSeconds(7),
|
||||||
assertEquals(4445767, YoutubeParsingHelper.parseDurationString("1,234:56:07"));
|
YoutubeParsingHelper.parseDurationString("12:34:56:07"));
|
||||||
assertEquals(754, YoutubeParsingHelper.parseDurationString("12:34 "));
|
assertEquals(Duration.ofHours(1234).plusMinutes(56).plusSeconds(7),
|
||||||
|
YoutubeParsingHelper.parseDurationString("1,234:56:07"));
|
||||||
|
assertEquals(Duration.ofMinutes(12).plusSeconds(34),
|
||||||
|
YoutubeParsingHelper.parseDurationString("12:34 "));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue