Build a simple Music Player with AWS Amplify and React

Build a simple Music Player with AWS Amplify and React

Introduction

Hello everyone, I finally finished my mini project and this is also my first post - a fledgling developer from Vietnam.

In this article, I would like to share the process of learning and building a simple music player using AWS Amplify and ReactJS.

Technology

  • AWS Amplify
  • AWS AppSync
  • AWS S3
  • AWS DynamoDB
  • AWS Cognito
  • React JS
  • GraphQL
  • Material UI

Project initialization

Create React app

Yeah, I'm a backend developer and it's my first time trying it.

npx create-react-app musicplayer
cd musicplayer
npm start

Everything is very good, the whole project structure is instantiated.

Amplify configure

First we need to install amplify-cli to facilitate the setup related to Amplify on our computer. Let's use the command:

npm i -g @aws-amplify/cli

At the project directory (musicplayer), run the command:

amplify configure

Follow the instructions on the command line to set up access to your AWS account, these include:

  • Choose region
  • Set username for the new IAM user
  • Redirect to AWS console to check and set permissions, get Access key ID and secret access key

And after creating a new IAM user, you will use that account to develop applications with different defaults from Amplify when you run the amplify init command. At this point, you should be able to view your application when accessing the AWS Amplify service as shown below:

music_player_init.png

Add create account, sign in, sign out

Execute the command below to add authentication functions to the application:

amplify add auth

At this step, I choose email as the way for users to register for an account. Other ways can be selected and easily changed by updating them on your AWS console. After every Amplify-related change or update, you need to run the command amplify push to save them in the cloud.

AWS Amplify automatically generates the amplify directory and the aws-exports.js file containing the config information that the application needs to use.

Install the necessary packages:

npm i aws-amplify @aws-amplify/ui-react

In file App.js:

import { Amplify, API, graphqlOperation, Storage } from 'aws-amplify';
import { withAuthenticator } from '@aws-amplify/ui-react';
import configure from "./aws-exports";
Amplify.configure(configure);
function App({ signOut, user }) {
//...
return (
    //...
    )
}
//...
export default withAuthenticator(App);

With the help of AWS Amplify, adding authentication capabilities to your application is really fast.

music_player_create_account.png

music_player_sign_in.png

Use DynamoDB and GraphQL for API

Run the command:

amplify add api

In this step, I choose to use the GraphQL API with the schema template being a single object with fields and the default authorization type for the API is Amazon Anonymous User Pools. And below is the schema sample generated by Amplify:

type Todo @model {
  id: ID!
  name: String!
  description: String
}

With my needs for this application, I want the schema to save the information for a song, so I modified the model as follows:

type Song @model {
  id: ID!
  name: String!
  description: String!
  filePath: String!
  heart: Int!
  author: String!
}

After finishing editing the model, I pushed my changes to AWS and accepted when asked if I wanted to generate code for the newly created GraphQL API. That way, AWS Amplify creates for me a graphql directory in the src folder containing mutations, queries, and subscriptions. I can use these APIs right away without any modification.

Function to get a list of songs:

import { API, graphqlOperation } from 'aws-amplify';
import { listSongs } from "./graphql/queries";
//...
const [songs, setSongs] = useState([]);
const getSongs = async () => {
    try {
      const songData = await API.graphql(graphqlOperation(listSongs));
      setSongs(songData.data.listSongs.items)
    } catch (error) {
      console.error('error on get songs: ', error);
    }
  }

Increase the number of favorites when the user clicks on the heart icons:

import { updateSong } from "./graphql/mutations";
//...
const increaseHeart = async index => {
    try {
      const song = songs[index];
      song.heart += 1;
      delete song.createdAt;
      delete song.updatedAt;

      const songData = await API.graphql(graphqlOperation(updateSong, { input: song }));

      const songList = [...songs];
      songList[index] = songData.data.updateSong;
      setSongs([...songs]);
    } catch (error) {
      console.error('error on increase heart: ', error);
    }
  }

Try adding some records to DynamoDB and start the application to see the results of the functions.

music_player_add_data_dynamodb.png

I use Material UI for faster front-end development. The image source I get is random from Unsplash with the category being music with the id of each song to limit getting duplicate images.

const image = `https://source.unsplash.com/random/200x200/?music&id=${song.id}`

My application at the moment:

music_player_ui.png

Storage audio on S3

To use S3 for storing the application's audio, we run the command:

amplify add storage

then choose the content type to store, set the bucket name, who can access it, the permissions of the auth users, and whether to use a lambda trigger... finally run amplify push to finish set up.

Implement music play/pause functionality, using AWS Amplify's Storage class to get access URLs of songs.

import { Storage } from 'aws-amplify';
//...
const [songPlaying, setSongPlaying] = useState('');
const [audioURL, setAudioURL] = useState('');

const toggleSong = async index => {
    if (songPlaying === index) {
      setSongPlaying('')
      return
    }

    const songFilePath = songs[index].filePath;
    try {
      const fileAccessURL = await Storage.get(songFilePath, { expires: 60 })
      setSongPlaying(index);
      setAudioURL(fileAccessURL);
      return;
    } catch (error) {
      console.error('error accessing the file from S3: ', error);
      setAudioURL('');
      setSongPlaying('');
    }
}

Upload audio files to S3 and update filePath fields in records in DynamoDB.

music_player_upload_file_s3.png

music_player_update_db_dynamodb.png

The product is complete, now we can play and stop the tracks, and drop the heart for our favourite music.

music_player_play_pause_audio.png

Deploy and host app

You may eventually want to deploy and host your application. You can follow the instructions in the link below:

This is my first post, I hope to receive your support and suggestions.

Link GitHub repository:

Yes, it's done. This is just a simple demo application for applying AWS Amplify to building a web application with ReactJS, all the work is done very quickly and easily. You can improve based on my app, some of the things that can be thought of are allowing users to share songs they like with others, adding comments, chatting... Of course, the knowledge in this article is very limited, and AWS Amplify does much more than that.

Resources