diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Downloader.java b/extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Downloader.java index 75d0bbf80..18017ded2 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Downloader.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Downloader.java @@ -4,12 +4,13 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import org.schabi.newpipe.extractor.localization.Localization; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.io.IOException; import java.util.List; import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * A base for downloader implementations that NewPipe will use * to download needed resources during extraction. @@ -148,8 +149,27 @@ public abstract class Downloader { /** * Do a request using the specified {@link Request} object. * + * @param request The request to process * @return the result of the request */ public abstract Response execute(@Nonnull Request request) throws IOException, ReCaptchaException; + + /** + * Get the size of the content that the url is pointing by firing a HEAD request. + * + * @param url an url pointing to the content + * @return the size of the content, in bytes or -1 if unknown + */ + public long getContentLength(final String url) { + try { + final String contentLengthHeader = head(url).getHeader("Content-Length"); + if (contentLengthHeader == null) { + return -1; + } + return Long.parseLong(contentLengthHeader); + } catch (final Exception e) { + return -1; + } + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/dashmanifestcreator/AbstractYoutubeDashManifestCreator.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/dashmanifestcreator/AbstractYoutubeDashManifestCreator.java index f8c2cc9a2..2b55e2e87 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/dashmanifestcreator/AbstractYoutubeDashManifestCreator.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/dashmanifestcreator/AbstractYoutubeDashManifestCreator.java @@ -102,6 +102,11 @@ public abstract class AbstractYoutubeDashManifestCreator implements DashManifest this.durationSecondsFallback = durationSecondsFallback; } + @Override + public long getExpectedContentLength(final Downloader downloader) { + return downloader.getContentLength(itagInfo.getStreamUrl()); + } + protected boolean isLiveDelivery() { return false; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java index b88a27506..f3b45b6e6 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java @@ -29,8 +29,8 @@ import javax.annotation.Nullable; * Info object for previews of unopened videos, eg search results, related videos */ public class StreamInfoItem extends InfoItem { - private final boolean audioOnly; private final boolean live; + private final boolean audioOnly; private String uploaderName; private String shortDescription; @@ -47,11 +47,11 @@ public class StreamInfoItem extends InfoItem { public StreamInfoItem(final int serviceId, final String url, final String name, - final boolean audioOnly, - final boolean live) { + final boolean live, + final boolean audioOnly) { super(InfoType.STREAM, serviceId, url, name); - this.audioOnly = audioOnly; this.live = live; + this.audioOnly = audioOnly; } public boolean isAudioOnly() { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java index d2d1b527a..c294e18b7 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java @@ -48,8 +48,8 @@ public class StreamInfoItemsCollector getServiceId(), extractor.getUrl(), extractor.getName(), - extractor.isAudioOnly(), - extractor.isLive()); + extractor.isLive(), + extractor.isAudioOnly()); // optional information try { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/DASHManifestDeliveryData.java b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/DASHManifestDeliveryData.java index 412a51276..56acf8e98 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/DASHManifestDeliveryData.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/DASHManifestDeliveryData.java @@ -1,5 +1,6 @@ package org.schabi.newpipe.extractor.streamdata.delivery; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.streamdata.delivery.dashmanifestcreator.DashManifestCreator; import javax.annotation.Nonnull; @@ -9,4 +10,9 @@ public interface DASHManifestDeliveryData extends DASHDeliveryData { DashManifestCreator dashManifestCreator(); String getCachedDashManifestAsString(); + + @Override + default long getExpectedContentLength(final Downloader downloader) { + return dashManifestCreator().getExpectedContentLength(downloader); + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/DeliveryData.java b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/DeliveryData.java index 9149d7794..1c861a6d8 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/DeliveryData.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/DeliveryData.java @@ -1,5 +1,13 @@ package org.schabi.newpipe.extractor.streamdata.delivery; +import org.schabi.newpipe.extractor.downloader.Downloader; + public interface DeliveryData { - // Only a marker so far + /** + * Returns the expected content length/size of the data. + * + * @param downloader The downloader that may be used for fetching (HTTP HEAD). + * @return the expected size/content length or -1 if unknown + */ + long getExpectedContentLength(Downloader downloader); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/UrlBasedDeliveryData.java b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/UrlBasedDeliveryData.java index a0df54f91..1b7e56ecd 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/UrlBasedDeliveryData.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/UrlBasedDeliveryData.java @@ -1,8 +1,15 @@ package org.schabi.newpipe.extractor.streamdata.delivery; +import org.schabi.newpipe.extractor.downloader.Downloader; + import javax.annotation.Nonnull; public interface UrlBasedDeliveryData extends DeliveryData { @Nonnull String url(); + + @Override + default long getExpectedContentLength(final Downloader downloader) { + return downloader.getContentLength(url()); + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/dashmanifestcreator/DashManifestCreator.java b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/dashmanifestcreator/DashManifestCreator.java index 66cd2d860..0195f25ce 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/dashmanifestcreator/DashManifestCreator.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/delivery/dashmanifestcreator/DashManifestCreator.java @@ -1,14 +1,23 @@ package org.schabi.newpipe.extractor.streamdata.delivery.dashmanifestcreator; +import org.schabi.newpipe.extractor.downloader.Downloader; + import javax.annotation.Nonnull; public interface DashManifestCreator { /** * Generates the DASH manifest. + * * @return The dash manifest as string. * @throws DashManifestCreationException May throw a CreationException */ @Nonnull String generateManifest(); + + /** + * See + * {@link org.schabi.newpipe.extractor.streamdata.delivery.DeliveryData#getExpectedContentLength(Downloader)} + */ + long getExpectedContentLength(Downloader downloader); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/SubtitleStream.java b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/SubtitleStream.java index 98ceb9287..47aedce7d 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/SubtitleStream.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/SubtitleStream.java @@ -39,5 +39,10 @@ public interface SubtitleStream extends Stream { * * @return the {@link Locale locale} of the subtitles */ + @Nonnull Locale locale(); + + default String getDisplayLanguageName() { + return locale().getDisplayName(locale()); + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/VideoStream.java b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/VideoStream.java index a5c32d249..115d4bbd1 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/VideoStream.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/VideoStream.java @@ -10,5 +10,5 @@ import javax.annotation.Nonnull; */ public interface VideoStream extends Stream { @Nonnull - VideoQualityData videoQualityData(); + VideoQualityData qualityData(); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/simpleimpl/SimpleVideoAudioStreamImpl.java b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/simpleimpl/SimpleVideoAudioStreamImpl.java index 68d03a090..7dd0e266d 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/simpleimpl/SimpleVideoAudioStreamImpl.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/simpleimpl/SimpleVideoAudioStreamImpl.java @@ -38,7 +38,7 @@ public class SimpleVideoAudioStreamImpl extends AbstractStreamImpl