Question

I read about this SoundCloud's API bug that returns a 404 error while trying to stream a track even if the "streamable" property was set to true.

I found some other questions about the topic (see "Tracks for “The Hives” are not streaming via the api" or "Soundcloud API SC.stream (track not loading)"), but what I would like to know is how to detect the error, and how to workaround it. I tried with some try {} catch() {} but it seems that I can't detect the problem.

Here is some background information:

I have a php returning a JSON array with a list of tracks to play. My script reads the array one-by-one, and then tries to play the current one. Everything works fine, but when a 404 error is returned the script ends, without jumping to the next track. It seems that I am unable to detect that kind of problem.

Here is the JavaScript method that manages the stream:

playTrack = function() {
        // console.log('playTrack');
        SC.get(
            "/tracks/" + playlist[ now_playing ].sndc_id,
            function(track, error) {
                if (error) { 
                    sendErrorReport(playlist[ now_playing ].id);
                    loadNext();
                } else {
                    try {
                        SC.stream(
                            "/tracks/" + playlist[ now_playing ].sndc_id,
                            function(sound, error) {
                                sound_object = sound;
                                if (error || !sound_object) {
                                    sendErrorReport(playlist[ now_playing ].id);
                                    loadNext();
                                } else {
                                    sound_object.play(
                                        {
                                            'from': parseInt(current_position),
                                            'onfinish': function() {
                                                current_position = 0;
                                                updateCounter();
                                                $('#radio-waveform-position').css( { 'opacity': '0', 'width' : '0%' } );
                                                loadNext();
                                            },
                                            'onplay': function() {
                                                $('#radio-like').removeClass('liked');
                                                playing = true;
                                                updateInfo();
                                            },
                                            'whileplaying': function() {
                                                current_position = this.position;
                                                $('#radio-waveform-position').css( { 'opacity': '1', 'width' : (100 * current_position / this.duration).toFixed(3) + '%'  } );
                                            },
                                            'ondataerror': function() {
                                                sendErrorReport(playlist[ now_playing ].id);
                                                loadNext();
                                            }
                                        }
                                    );
                                    if ($('html').hasClass('touch') || !autoplay) $('#radio-play-pause').click();
                                }
                            }
                        );
                    } catch (err) {
                        sendErrorReport(playlist[ now_playing ].id);
                        loadNext();
                    }
                }
            }
        );
    }

It seems that both the SC.get and SC.stream "error" return parameters are always empty for this kind of "faulty" tracks. As you can see, I tried to wrap everything in a try() {} catch() {} but without success. Also, the sound_object.play() ondataerror method is completely ignored.

The script can be seen in action here: http://foggetabout.it/

I read that someone found a workaround for that, but there was no explanation. Has anyone any idea on how to solve it?

Was it helpful?

Solution

Run into something similar. Not sure if it is connected but it appears some tracks are only streamable with flash so the GET method states they’re streamable but the stream can fail if flash is not available.

One way to get around it is to check when SoundManager has loaded the track using the onload & readyState, which (from docs: http://www.schillmania.com/projects/soundmanager2/doc/) has 4 states:

  • 0 = uninitialised
  • 1 = loading
  • 2 = failed/error
  • 3 = loaded/success

So:

sound_object.play({
    // Exisiting…
    onload: function() {
      if (this.readyState == 2) {
        // Handle error
      }
    });

There are some caveats on when the state changes so if this becomes a problem you could also try using durationEstimate as it returns null for the failed tracks I’m coming across.

OTHER TIPS

For a lot of songs streamable is set to true and its stream_url is defined, but the resource itself is not there.

Using curl, hitting the i1 endpoint with your desired track_id and a registered API_KEY is the first step to checking for the actual resources on a SoundCloud hosted track. (Warning: the i1 endpoint is not officially documented in SoundCloud's HTTP API Reference)

curl https://api.soundcloud.com/i1/tracks/{{track_id}}/streams?client_id={{API_KEY}}

This will return a JSON object that looks something like:

{
    "http_mp3_128_url": "{some_url}",
    "preview_mp3_128_url": "{some_url}"
}

If the http_mp3_128_url key-value pair exists, then that track has an accessible HTTP resource and would be streamable.

More info here - https://github.com/francismakes/i1-soundcloud

Building off of roj's answer, I used a bit of code like this to first get into handling 404s on the SC track streaming:

sound.play({
            onload: function () {
              if (this.readyState === 2){
                alert('error');
              }

            },
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top