2929import java .util .Collections ;
3030import java .util .List ;
3131import java .util .Locale ;
32- import java .util .regex .Matcher ;
33- import java .util .regex .Pattern ;
3432
35- import static org .schabi .newpipe .extractor .utils .Utils .HTTPS ;
3633import static org .schabi .newpipe .extractor .utils .Utils .*;
3734
3835public class SoundcloudStreamExtractor extends StreamExtractor {
@@ -198,7 +195,7 @@ public List<AudioStream> getAudioStreams() throws ExtractionException {
198195 final JsonArray transcodings = track .getObject ("media" ).getArray ("transcodings" );
199196 if (transcodings != null ) {
200197 // Get information about what stream formats are available
201- setUpAudioStreams (transcodings , checkMp3ProgressivePresence (transcodings ),
198+ extractAudioStreams (transcodings , checkMp3ProgressivePresence (transcodings ),
202199 audioStreams );
203200 }
204201 } catch (final NullPointerException e ) {
@@ -238,59 +235,61 @@ private static String getTranscodingUrl(final String endpointUrl, final String p
238235 if (protocol .equals ("progressive" )) {
239236 return urlString ;
240237 } else if (protocol .equals ("hls" )) {
241- return getSingleUrlFromHlsManifest (urlString );
238+ try {
239+ return getSingleUrlFromHlsManifest (urlString );
240+ } catch (final ParsingException ignored ) {
241+ }
242242 }
243243 // else, unknown protocol
244244 return "" ;
245245 }
246246
247- private static void setUpAudioStreams (final JsonArray transcodings ,
248- final boolean mp3ProgressiveInStreams ,
249- final List <AudioStream > audioStreams ) {
247+ private static void extractAudioStreams (final JsonArray transcodings ,
248+ final boolean mp3ProgressiveInStreams ,
249+ final List <AudioStream > audioStreams ) {
250250 for (final Object transcoding : transcodings ) {
251251 final JsonObject transcodingJsonObject = (JsonObject ) transcoding ;
252+ final String url = transcodingJsonObject .getString ("url" );
253+ if (isNullOrEmpty (url )) {
254+ continue ;
255+ }
252256 final String mediaUrl ;
253257 final String preset = transcodingJsonObject .getString ("preset" );
254258 final String protocol = transcodingJsonObject .getObject ("format" ).getString ("protocol" );
255- final String url = transcodingJsonObject .getString ("url" );
256- final MediaFormat mediaFormat ;
257- final int bitrate ;
258-
259- if (!isNullOrEmpty (url )) {
260- if (preset .contains ("mp3" )) {
261- // Don't add the MP3 HLS stream if there is a progressive stream present
262- // because the two have the same bitrate
263- if (mp3ProgressiveInStreams && protocol .equals ("hls" )) {
264- continue ;
265- }
266- mediaFormat = MediaFormat .MP3 ;
267- bitrate = 128 ;
268- } else if (preset .contains ("opus" )) {
269- mediaFormat = MediaFormat .OPUS ;
270- bitrate = 64 ;
271- } else {
272- // Unknown format
259+ MediaFormat mediaFormat = null ;
260+ int bitrate = 0 ;
261+ if (preset .contains ("mp3" )) {
262+ // Don't add the MP3 HLS stream if there is a progressive stream present
263+ // because the two have the same bitrate
264+ if (mp3ProgressiveInStreams && protocol .equals ("hls" )) {
273265 continue ;
274266 }
267+ mediaFormat = MediaFormat .MP3 ;
268+ bitrate = 128 ;
269+ } else if (preset .contains ("opus" )) {
270+ mediaFormat = MediaFormat .OPUS ;
271+ bitrate = 64 ;
272+ }
275273
274+ if (mediaFormat != null ) {
276275 try {
277276 mediaUrl = getTranscodingUrl (url , protocol );
278- } catch (final Exception e ) {
279- // something went wrong when parsing this transcoding
280- continue ;
277+ if (!mediaUrl .isEmpty ()) {
278+ audioStreams .add (new AudioStream (mediaUrl , mediaFormat , bitrate ));
279+ }
280+ } catch (final Exception ignored ) {
281+ // something went wrong when parsing this transcoding, don't add it to
282+ // audioStreams
281283 }
282- audioStreams .add (new AudioStream (mediaUrl , mediaFormat , bitrate ));
283284 }
284285 }
285286 }
286287
287- private final static Pattern PATTERN_HTTPS_URLS_IN_HLS_MANIFESTS = Pattern .compile ("((https?):((//)|(\\ \\ ))+[\\ w\\ d:#@%/;$()~_?+-=\\ \\ .&]*)" );
288-
289288 /** Parses a SoundCloud HLS manifest to get a single URL of HLS streams.
290289 * <p>
291- * This method downloads the provided manifest URL, find all web occurrences using a regex, get
292- * the last segment URL, changes its segment range to {@code 0/track-length} and return this
293- * string.
290+ * This method downloads the provided manifest URL, find all web occurrences in the manifest,
291+ * get the last segment URL, changes its segment range to {@code 0/track-length} and return
292+ * this string.
294293 * @param hlsManifestUrl the URL of the manifest to be parsed
295294 * @return a single URL that contains a range equal to the length of the track
296295 */
@@ -304,20 +303,17 @@ private static String getSingleUrlFromHlsManifest(final String hlsManifestUrl) t
304303 throw new ParsingException ("Could not get SoundCloud HLS manifest" );
305304 }
306305
307- final List <String > hlsRangesList = new ArrayList <>();
308- final Matcher pattern_matches = PATTERN_HTTPS_URLS_IN_HLS_MANIFESTS
309- .matcher (hlsManifestResponse );
310-
311- while (pattern_matches .find ()) {
312- hlsRangesList .add (hlsManifestResponse .substring (pattern_matches .start (0 ),
313- pattern_matches .end (0 )));
306+ final String [] lines = hlsManifestResponse .split ("\\ r?\\ n" );
307+ for (int l = lines .length - 1 ; l >= 0 ; l --) {
308+ final String line = lines [l ];
309+ // get the last URL from manifest, because it contains the range of the stream
310+ if (line .trim ().length () != 0 && !line .startsWith ("#" ) && line .startsWith ("https" )) {
311+ final String [] hlsLastRangeUrlArray = line .split ("/" );
312+ return HTTPS + hlsLastRangeUrlArray [2 ] + "/media/0/" + hlsLastRangeUrlArray [5 ] + "/"
313+ + hlsLastRangeUrlArray [6 ];
314+ }
314315 }
315-
316- final String hlsLastRangeUrl = hlsRangesList .get (hlsRangesList .size () - 1 );
317- final String [] hlsLastRangeUrlArray = hlsLastRangeUrl .split ("/" );
318-
319- return HTTPS + hlsLastRangeUrlArray [2 ] + "/media/0/" + hlsLastRangeUrlArray [5 ] + "/"
320- + hlsLastRangeUrlArray [6 ];
316+ throw new ParsingException ("Could not get any URL from HLS manifest" );
321317 }
322318
323319 private static String urlEncode (final String value ) {
0 commit comments