Build a simple Music Player with AWS Amplify and React
Published: 2022-10-01 09:42:31

## 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.

```js
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:

```js
npm i -g @aws-amplify/cli
```

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

```js
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:


![AWS Amplify init](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qfl6g7c2cbppguhv8gpm.png)

## Add create account, sign in, sign out

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

```js
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:
 ```js
npm i aws-amplify @aws-amplify/ui-react
```

In file App.js:

```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.



![Create account screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mn21mwin62cuwxgg69a9.png)


![Sign in screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rvc1rqd8i4i3cnwk2c7.png)

## Use DynamoDB and GraphQL for API

Run the command:
```js
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:

```graphql
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:

```graphql
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:

```js
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:
```js
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.


![Add data to DynamoDB](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/po7wbflcd1bfh2ml20jg.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.

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

My application at the moment:


![Music player UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7obmv5ce71bu24yyq1rm.png)

## Storage audio on S3

To use S3 for storing the application's audio, we run the command:
```js
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.

```js
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.


![Upload file to S3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q9nkgoofg81pynxqiv02.png)

![Update data in DynamoDB](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tfqv6oic6f2zbed7as5v.png)

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


![Music player completed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i6ohot8ljpkassgp7edn.png)

## Deploy and host app

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

https://aws.amazon.com/getting-started/guides/deploy-webapp-amplify/module-three/

**Here are 2 access links to my deployed app:**
https://master.d2knwrz36tm5yc.amplifyapp.com/
https://d2wvly4638hbyf.cloudfront.net/

Link GitHub repository:
https://github.com/nguyentruongtoan1309/musicplayer

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

> 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
- [AWS Amplify](https://aws.amazon.com/amplify/)
- [Complete Coding / Sam Williams](https://www.youtube.com/c/CompleteCoding)
- [Material UI](https://mui.com/material-ui/)
- [ReactJS](https://reactjs.org/)
- [Amplify Documentation](https://docs.amplify.aws/)

## See original post [here](https://toannguyentruong.hashnode.dev/build-a-simple-music-player-with-aws-amplify-and-react)


If the article is interesting and useful to you, you can give me a cup of coffee. Thanks for reading.

[![Buy Me A Coffee](https://cdn.buymeacoffee.com/buttons/default-black.png)](https://www.buymeacoffee.com/toannt1309)