How to Create a Music Player App with Angular and SoundCloud API

In this tutorial, we will create a music player app using Angular and the SoundCloud API. The app will allow users to search for songs, play them, and create playlists. We will also include features like playing, pausing, and skipping songs.

To get started, make sure you have Angular CLI installed on your machine. If not, you can install it by running the following command:

npm install -g @angular/cli

Setting up the Angular Project

Let’s create a new Angular project using the Angular CLI. Open your terminal and run the following command:

ng new music-player-app

Once the project is created, navigate to the project folder:

cd music-player-app

Next, open the project in your favorite text editor.

Installing Dependencies

We need to install a few dependencies to work with the SoundCloud API and handle audio playback. Run the following command in your terminal:

npm install soundcloud soundmanager2 --save

The soundcloud library will help us interact with the SoundCloud API, and soundmanager2 will be used for audio playback management.

Creating the Music Player Component

Let’s create a new component that will serve as the main music player. Run the following command in your terminal:

ng generate component music-player

This will generate a new folder named “music-player” with all the necessary files for the component. Next, open the newly generated component file music-player.component.ts and replace the code with the following:

import { Component, OnInit } from '@angular/core';
import * as SC from 'soundcloud';
import * as soundManager from 'soundmanager2';

@Component({
  selector: 'app-music-player',
  templateUrl: './music-player.component.html',
  styleUrls: ['./music-player.component.css']
})
export class MusicPlayerComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
    SC.initialize({
      client_id: 'YOUR_SOUNDCLOUD_CLIENT_ID'
    });

    soundManager.setup({
      url: 'path/to/soundmanager2/swf',
      debugMode: false
    });
  }

}

In the above code, we import the necessary libraries and initialize the SoundCloud API with our client ID. We also configure the soundManager library.

Next, open the music-player.component.html file and replace its content with the following code:

<div>
  <h1>Music Player</h1>
</div>

This is a simple starting point for our music player. Feel free to add more HTML markup and styling to enhance the look and feel of your app.

Implementing the Search Functionality

Let’s add a search input and button to our music player component to allow users to search for songs on SoundCloud. Open the music-player.component.html file and replace its content with the following code:

<div>
  <h1>Music Player</h1>
  <div>
    <input type="text" [(ngModel)]="searchQuery" placeholder="Search for songs">
    <button (click)="search()">Search</button>
  </div>
</div>

In the above code, we add an input field and a button. The ngModel directive is used to bind the input value to the searchQuery property in our component. The button is bound to the search() method which we will implement next.

Open the music-player.component.ts file and update it with the following code:

import { Component, OnInit } from '@angular/core';
import * as SC from 'soundcloud';
import * as soundManager from 'soundmanager2';

@Component({
  selector: 'app-music-player',
  templateUrl: './music-player.component.html',
  styleUrls: ['./music-player.component.css']
})
export class MusicPlayerComponent implements OnInit {
  searchQuery: string;

  constructor() { }

  ngOnInit(): void {
    SC.initialize({
      client_id: 'YOUR_SOUNDCLOUD_CLIENT_ID'
    });

    soundManager.setup({
      url: 'path/to/soundmanager2/swf',
      debugMode: false
    });
  }

  search(): void {
    SC.get('/tracks', {
      q: this.searchQuery
    }).then(function(tracks) {
      console.log(tracks);
    });
  }
}

In the updated code, we create a property searchQuery to store the user’s search input. The search() method uses the SC.get() function from the SoundCloud library to search for tracks based on the user’s query. We log the tracks to the console for now, but we will update this in the next step.

Displaying Search Results

Let’s update our music player component to display the search results to the user. Open the music-player.component.html file and replace its content with the following code:

<div>
  <h1>Music Player</h1>
  <div>
    <input type="text" [(ngModel)]="searchQuery" placeholder="Search for songs">
    <button (click)="search()">Search</button>
  </div>
  <div *ngIf="searchResults.length > 0">
    <h2>Search Results</h2>
    <ul>
      <li *ngFor="let track of searchResults">
        <h3>{{ track.title }}</h3>
        <p>Artist: {{ track.user.username }}</p>
        <p>Duration: {{ track.duration / 1000 }} seconds</p>
        <img src="{{ track.artwork_url }}" alt="Track Artwork">
        <button (click)="play(track)">Play</button>
      </li>
    </ul>
  </div>
</div>

In the above code, we use the *ngIf directive to conditionally render the search results section only if there are results to display. We iterate over each track in the searchResults array using the *ngFor directive and display its title, artist, duration, and artwork. We also add a “Play” button for each track, bound to the play() method which we will implement shortly.

Open the music-player.component.ts file and update it with the following code:

import { Component, OnInit } from '@angular/core';
import * as SC from 'soundcloud';
import * as soundManager from 'soundmanager2';

@Component({
  selector: 'app-music-player',
  templateUrl: './music-player.component.html',
  styleUrls: ['./music-player.component.css']
})
export class MusicPlayerComponent implements OnInit {
  searchQuery: string;
  searchResults: any[] = [];

  constructor() { }

  ngOnInit(): void {
    SC.initialize({
      client_id: 'YOUR_SOUNDCLOUD_CLIENT_ID'
    });

    soundManager.setup({
      url: 'path/to/soundmanager2/swf',
      debugMode: false
    });
  }

  search(): void {
    SC.get('/tracks', {
      q: this.searchQuery
    }).then((tracks: any[]) => {
      this.searchResults = tracks;
    });
  }

  play(track: any): void {
    const trackUrl = `${track.stream_url}?client_id=YOUR_SOUNDCLOUD_CLIENT_ID`;
    soundManager.createSound({
      url: trackUrl
    }).play();
  }
}

In the updated code, we create an array searchResults to store the search results. The updated search() method assigns the fetched tracks to this array. The play() method creates a new sound using the SoundManager library and plays the track by concatenating the stream_url with our client ID.

Adding Audio Controls

Let’s enhance our music player component by adding audio controls like play, pause, and skip. Open the music-player.component.html file and replace its content with the following code:

<div>
  <h1>Music Player</h1>
  <div>
    <input type="text" [(ngModel)]="searchQuery" placeholder="Search for songs">
    <button (click)="search()">Search</button>
  </div>
  <div *ngIf="searchResults.length > 0">
    <h2>Search Results</h2>
    <ul>
      <li *ngFor="let track of searchResults">
        <h3>{{ track.title }}</h3>
        <p>Artist: {{ track.user.username }}</p>
        <p>Duration: {{ track.duration / 1000 }} seconds</p>
        <img src="{{ track.artwork_url }}" alt="Track Artwork">
        <button (click)="play(track)">Play</button>
      </li>
    </ul>
  </div>
  <div *ngIf="currentTrack">
    <h2>Now Playing</h2>
    <h3>{{ currentTrack.title }}</h3>
    <p>Artist: {{ currentTrack.user.username }}</p>
    <p>Duration: {{ currentTrack.duration / 1000 }} seconds</p>
    <img src="{{ currentTrack.artwork_url }}" alt="Track Artwork">
    <button (click)="pause()">Pause</button>
    <button (click)="skip()">Skip</button>
  </div>
</div>

In the above code, we add another section to display the currently playing track. We display its title, artist, duration, and artwork. We also add “Pause” and “Skip” buttons, bound to the pause() and skip() methods respectively.

Open the music-player.component.ts file and update it with the following code:

import { Component, OnInit } from '@angular/core';
import * as SC from 'soundcloud';
import * as soundManager from 'soundmanager2';

@Component({
  selector: 'app-music-player',
  templateUrl: './music-player.component.html',
  styleUrls: ['./music-player.component.css']
})
export class MusicPlayerComponent implements OnInit {
  searchQuery: string;
  searchResults: any[] = [];
  currentTrack: any;

  constructor() { }

  ngOnInit(): void {
    SC.initialize({
      client_id: 'YOUR_SOUNDCLOUD_CLIENT_ID'
    });

    soundManager.setup({
      url: 'path/to/soundmanager2/swf',
      debugMode: false
    });
  }

  search(): void {
    SC.get('/tracks', {
      q: this.searchQuery
    }).then((tracks: any[]) => {
      this.searchResults = tracks;
    });
  }

  play(track: any): void {
    const trackUrl = `${track.stream_url}?client_id=YOUR_SOUNDCLOUD_CLIENT_ID`;
    const sound = soundManager.createSound({
      url: trackUrl
    });
    sound.play();
    this.currentTrack = track;
  }

  pause(): void {
    soundManager.pauseAll();
  }

  skip(): void {
    soundManager.stopAll();
    this.currentTrack = null;
  }
}

In the updated code, we create a property currentTrack to keep track of the currently playing track. The play() method assigns the clicked track to currentTrack and plays it. The pause() method pauses audio playback using the SoundManager library. The skip() method stops all audio playback and sets currentTrack to null.

Conclusion

In this tutorial, we learned how to create a music player app using Angular and the SoundCloud API. We implemented features like searching for songs, displaying search results, playing and pausing songs, and skipping tracks. You can further enhance this app by adding features like playlists, shuffle mode, and volume control. Explore the SoundCloud API and the Angular framework to add more functionalities to your music player app.

Feel free to play around with the code and customize the look and feel of the app according to your preferences. Happy coding!

Related Post