mirror of
https://github.com/TeamNewPipe/NewPipeExtractor.git
synced 2025-04-28 07:50:34 +05:30
[Soundcloud] Remove DRM-protected and downloadable formats extraction
DRM-protected streams have been added to some tracks, mostly from major music companies. We do not support DRM streams in the extractor, so they shouldn't be extracted and so waste time, energy and resources. Extracting downloadable format requires login for a pretty long time, so there is no point again to do requests to extract this stream to get an unauthorized response. Also send the track_authorization property returned in the track info, like the website does and allow duplicate MP3 formats in progressive and HLS delivery methods to be returned.
This commit is contained in:
parent
3a33cefbc0
commit
7607688cb0
@ -6,7 +6,6 @@ import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsing
|
||||
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper.getAllImagesFromTrackObject;
|
||||
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper.getAvatarUrl;
|
||||
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper.parseDateFrom;
|
||||
import static org.schabi.newpipe.extractor.stream.AudioStream.UNKNOWN_BITRATE;
|
||||
import static org.schabi.newpipe.extractor.stream.Stream.ID_UNKNOWN;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
|
||||
@ -170,14 +169,12 @@ public class SoundcloudStreamExtractor extends StreamExtractor {
|
||||
}
|
||||
|
||||
try {
|
||||
final JsonArray transcodings = track.getObject("media").getArray("transcodings");
|
||||
final JsonArray transcodings = track.getObject("media")
|
||||
.getArray("transcodings");
|
||||
if (!isNullOrEmpty(transcodings)) {
|
||||
// Get information about what stream formats are available
|
||||
extractAudioStreams(transcodings, checkMp3ProgressivePresence(transcodings),
|
||||
audioStreams);
|
||||
extractAudioStreams(transcodings, audioStreams);
|
||||
}
|
||||
|
||||
extractDownloadableFileIfAvailable(audioStreams);
|
||||
} catch (final NullPointerException e) {
|
||||
throw new ExtractionException("Could not get audio streams", e);
|
||||
}
|
||||
@ -185,19 +182,16 @@ public class SoundcloudStreamExtractor extends StreamExtractor {
|
||||
return audioStreams;
|
||||
}
|
||||
|
||||
private static boolean checkMp3ProgressivePresence(@Nonnull final JsonArray transcodings) {
|
||||
return transcodings.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.anyMatch(transcodingJsonObject -> transcodingJsonObject.getString("preset")
|
||||
.contains("mp3") && transcodingJsonObject.getObject("format")
|
||||
.getString("protocol").equals("progressive"));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private String getTranscodingUrl(final String endpointUrl)
|
||||
throws IOException, ExtractionException {
|
||||
final String apiStreamUrl = endpointUrl + "?client_id=" + clientId();
|
||||
String apiStreamUrl = endpointUrl + "?client_id=" + clientId();
|
||||
|
||||
final String trackAuthorization = track.getString("track_authorization");
|
||||
if (!isNullOrEmpty(trackAuthorization)) {
|
||||
apiStreamUrl += "&track_authorization=" + trackAuthorization;
|
||||
}
|
||||
|
||||
final String response = NewPipe.getDownloader().get(apiStreamUrl).responseBody();
|
||||
final JsonObject urlObject;
|
||||
try {
|
||||
@ -209,27 +203,7 @@ public class SoundcloudStreamExtractor extends StreamExtractor {
|
||||
return urlObject.getString("url");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getDownloadUrl(@Nonnull final String trackId)
|
||||
throws IOException, ExtractionException {
|
||||
final String response = NewPipe.getDownloader().get(SOUNDCLOUD_API_V2_URL + "tracks/"
|
||||
+ trackId + "/download" + "?client_id=" + clientId()).responseBody();
|
||||
|
||||
final JsonObject downloadJsonObject;
|
||||
try {
|
||||
downloadJsonObject = JsonParser.object().from(response);
|
||||
} catch (final JsonParserException e) {
|
||||
throw new ParsingException("Could not parse download URL", e);
|
||||
}
|
||||
final String redirectUri = downloadJsonObject.getString("redirectUri");
|
||||
if (!isNullOrEmpty(redirectUri)) {
|
||||
return redirectUri;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void extractAudioStreams(@Nonnull final JsonArray transcodings,
|
||||
final boolean mp3ProgressiveInStreams,
|
||||
final List<AudioStream> audioStreams) {
|
||||
transcodings.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
@ -244,23 +218,23 @@ public class SoundcloudStreamExtractor extends StreamExtractor {
|
||||
final String preset = transcoding.getString("preset", ID_UNKNOWN);
|
||||
final String protocol = transcoding.getObject("format")
|
||||
.getString("protocol");
|
||||
|
||||
if (protocol.contains("encrypted")) {
|
||||
// Skip DRM-protected streams, which have encrypted in their protocol
|
||||
// name
|
||||
return;
|
||||
}
|
||||
|
||||
final AudioStream.Builder builder = new AudioStream.Builder()
|
||||
.setId(preset);
|
||||
|
||||
final boolean isHls = protocol.equals("hls");
|
||||
if (isHls) {
|
||||
if (protocol.equals("hls")) {
|
||||
builder.setDeliveryMethod(DeliveryMethod.HLS);
|
||||
}
|
||||
|
||||
builder.setContent(getTranscodingUrl(url), true);
|
||||
|
||||
if (preset.contains("mp3")) {
|
||||
// Don't add the MP3 HLS stream if there is a progressive stream
|
||||
// present because both have the same bitrate
|
||||
if (mp3ProgressiveInStreams && isHls) {
|
||||
return;
|
||||
}
|
||||
|
||||
builder.setMediaFormat(MediaFormat.MP3);
|
||||
builder.setAverageBitrate(128);
|
||||
} else if (preset.contains("opus")) {
|
||||
@ -283,39 +257,6 @@ public class SoundcloudStreamExtractor extends StreamExtractor {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the downloadable format if it is available.
|
||||
*
|
||||
* <p>
|
||||
* A track can have the {@code downloadable} boolean set to {@code true}, but it doesn't mean
|
||||
* we can download it.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If the value of the {@code has_download_left} boolean is {@code true}, the track can be
|
||||
* downloaded, and not otherwise.
|
||||
* </p>
|
||||
*
|
||||
* @param audioStreams the audio streams to which the downloadable file is added
|
||||
*/
|
||||
public void extractDownloadableFileIfAvailable(final List<AudioStream> audioStreams) {
|
||||
if (track.getBoolean("downloadable") && track.getBoolean("has_downloads_left")) {
|
||||
try {
|
||||
final String downloadUrl = getDownloadUrl(getId());
|
||||
if (!isNullOrEmpty(downloadUrl)) {
|
||||
audioStreams.add(new AudioStream.Builder()
|
||||
.setId("original-format")
|
||||
.setContent(downloadUrl, true)
|
||||
.setAverageBitrate(UNKNOWN_BITRATE)
|
||||
.build());
|
||||
}
|
||||
} catch (final Exception ignored) {
|
||||
// If something went wrong when trying to get the download URL, ignore the
|
||||
// exception throw because this "stream" is not necessary to play the track
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VideoStream> getVideoStreams() {
|
||||
return Collections.emptyList();
|
||||
|
Loading…
x
Reference in New Issue
Block a user