Turn on JavaScript
Pritish Vaidya

How to make realtime SoundCloud Waveforms in React Native

📅️ January 12, 2019

SoundCloud is a music and podcast streaming platform for listening to millions of authentic tracks. They have a really interactive interface for playing / listening to the tracks. The most important feature in their interface is showing the progress of the track based on its frequency waveform. This helps the users to identify the nature of it. They also have a blog post which describes how to use the waveform based on its image. It is hard to use the same techniques to generate the waveform in a React Native app. Their Waveform.js SDK translates a waveform into floating points to render on an HTML5 canvas and is currently no longer operational. In this article we’ll discuss how to use the same waveform for our React Native apps.

Why Should I use SoundCloud’s Waveforms?

soundcloud_1

  • The SoundCloud’s waveform looks more impressive than the old boring way of showing the progress bar.
  • The pre-loaded waveform will give the user an idea of the different frequencies present in the song.
  • It is also much easier to show the buffered track percentage on a waveform rather than showing it on a blank progress bar.

Let’s learn more about SoundCloud’s Waveforms

soundcloud_2

The SoundCloud provides a waveform_url in its tracks API.

  • Each track has its own unique waveform_url .
  • The waveform_url contains a link to the image hoisted over the cloud.

Example — https://w1.sndcdn.com/PP3Eb34ToNki_m.png

soundcloud_3

As of now, every argument is static hence it is unusable in this current state. Therefore we need to re-create the waveform based on it using React Native’s *containers* in order to have access to the touch events, styles etc.

Getting Started

Here is a list of stuff that you will need:

First, we need the sampling of the waveform. The trick is to replace .png with .json for the waveform_url . A GET call to it would give us a response object that contains

  • width (Width of the waveform)
  • height (Height of the waveform)
  • samples (Array)

For more info, you can try out the following link https://w1.sndcdn.com/PP3Eb34ToNki_m.json.

Dive into the code

Add a Custom SoundCloudWave Component

soundcloud_code_1

It would be better to create a custom SoundCloudWave component that can be used in multiple places as required. Here are the required props:

  • waveformUrl — The URL object to the waveform (accessible through the Tracks API)
  • height — Height of the waveform
  • width — Width of the waveform component
  • percentPlayable — The duration of the track buffered in seconds
  • percentPlayed — The duration of the track played in seconds
  • **setTime — **The callback handler to change the current track time.

Get the samples

soundcloud_code_2

Get the samples by using a simple GET API call and store the result in the state.

Create a Waveform Component

soundcloud_code_3

The Waveform Component works as follows:

  • The Chunks split the samples object based on the width that the user wants to render on the screen.
  • The Chunks are then mapped into a Touchable event. The styles as width:2 and height: scaleLinearHeight(mean(chunk)). This generates the mean from the d3-array.
  • The backgroundColor is being passed as a method with different parameters to the getColor method. This will then determine the color to return based on the conditions set.
  • The Touchable onPress event will call the custom handler passed into it, to set the new seek time of the track.

Now this stateless component can be rendered to your child component as:

soundcloud_code_4

Here one of the waveform component is original and one inverted as in the SoundCloud’s player.

soundcloud_4

Conclusion

Here are the links to the react-native-soundcloud-waveform

I’ve also made an app in react-native — MetalCloud for Metal Music fans where you can see the above component at work.

Here are the links:

Thanks for reading. If you liked this article, show your support by clapping to share with other people on Medium.

More of the cool stuff can be found on my StackOverflow and GitHub profiles.

Follow me on LinkedIn, Medium, Twitter for further update new articles.