An ad-free, lightweight music player that lets you play music from your local library on your mobile device.
MonoBox is a free music application designed to be easy to operate, intuitive to the user and has fast performance.
Its main purpose is to play the music files you have on your computer, and to allow you to create and customize playlists according to your personal taste.
Users will be able to run their own servers with their own songs. The server itself is implemented in Python and the mobile application in React Native.
- An article explaining how I created MonoBox: Introducing MonoBox
- An article that provided guidelines for building MonoBox: Build Your Own Spotify
- Simple & Easy to use music player
- Listen from your local library
- Create and customize your own playlists
- Open-Source code
- Dark / Light themes
- No ads
- React Native 📱
- JavaScript & TypeScript
- Code formatted with Prettier 🎀
- React Native Track Player - An audio module for music apps 🎵
- React Query - A powerful library containing hooks for fetching, caching and updating asynchronous data
- Python 🐍
- FastAPI - A modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints
- SQLModel - A library for interacting with SQL databases from Python code, with Python objects
- pre-commit, black, mypy and isort are integrated to make sure the code looks good and clean
- Database 📄
- SQLite
First and foremost, make sure your mobile device and PC are using the same wireless network,
otherwise the application will not be able to communicate with the server running on the computer.
Then, in the root of the project, create 2 folders:
songs
contains all the songs in the app library.covers
contains all the artworks of the songs in thesongs
folder.
Now you can copy all the songs you want to display in the app into the songs
folder.
The SQLite backend needs to be running for the API to use for state.
You can use the included Taskfile to configure much of this project. This Makefile alternative will assume the ignored ./venv
path for storage of local binaries and Python libraries.
First ensure task is installed to your PATH somewhere.
After this, the following tasks can be used to build the virtual environment and API backend via the task
command.
# Configure virtual environment and pull down requirements
task backend:install
# Start up the backend services in the background
task backend:start &
NOTE: You can force re-run tasks anytime with the
-f
option. Example:task backend:install -f
.
From the root, you need to navigate to the backend
folder. from your terminal:
cd backend
The requirements.txt
file lists all the Python libraries that the music player depends on, and they can be installed from your terminal using:
pip install -r requirements.txt
Then, in the main.py
file, you have this block of code, where you need to insert your PC's IP address (notice the comment):
host_ip = "0.0.0.0" # Change to your PC's IP
host_port = 5000
music_folder_url = "../songs"
cover_folder_url = "../covers"
The default port is 5000, but you can also change it if you want the server to listen to a different port,
although it is required to change this in the Frontend as well.
Finally, run the following command from your terminal to set up your server and create your database:
python main.py
Visit the service url with /redocs
or /docs
to interactively browse the API docs. Example: http://127.0.0.1:5001/docs
If you run into issues running the backend you may need to reconfigure python after having installed the local sqlite3 development libraries (sudo apt install libsqlite3-dev
for Ubuntu based systems.).
The included taskfile definition includes asdf-vm install and configuration tasks that can be used to bootstrap the Python and Nodejs environments if required.
After setting up the Backend, open a new terminal for the Frontend.
The package.json
file lists all the React / React Native libraries that the music player depends on, so let's install them from the terminal using:
npm install
In order for the application to communicate with the server in the Backend, we need to insert the PC's IP address to the Frontend as well.
So now we need to navigate to the mobile/utils
folder from the root of the project, and then to the BaseAPI.tsx
file.
Inside BaseAPI.tsx
you have the following block of code, where you need to insert the same IP address as you did in the Backend (notice the comment):
export const BASE_API_URL = '0.0.0.0' // Change to your PC's IP
export const BASE_API_PORT = 5000
If you decided to change the default port in main.py
, this is the place to change it as well.
Now you're all set!
You are welcome to try the application yourself or continue to the next section to learn about its features and how to use it.
Upon initializtion, in your Homescreen, you'll notice you have a playlist called Liked Songs which does not contain any songs at the moment. Don't worry, we'll get to that later. ↩️
On the top right corner you'll also notice a ➕ sign button, with which you can create a new playlist and give it a name!
If you followed the instructions on the Installation section and copied all the songs to the designated folder, you should be able to see all of them on your Library screen. 📚
In order to add a song to a playlist, press the button that appears to the right of each song, and choose one of your playlists. Pretty easy so far, huh? ✌️
So in order for you to remove a song from a playlist - simply press a song in a playlist and hold it for 2 seconds, and the song will be removed.
The same goes for the entire playlist - press its name and hold for 2 seconds, and it will be deleted along with its songs.
What music app would it be without a Songs Carousel, right?
For you to get to the Songs Carousel, just press on any song in a playlist, on any screen you'd like (e.g. Choosing a song from the Library screen will create a queue of all the songs from the Library for you).
So the Songs Carousel is quite intuitive and familiar to use.
To skip to the next or previous song - click on
You also have the 🔁 button which determines whether the list of songs that is currently playing:
- will repeat itself endlessly ♾️
- will repeat once 🔂
- will not repeat itself at all
Above the Slider, the current running time of the song (on the left) and the time remaining until the end of the song (on the right) are indicated.
Did you like a certain part of the song? The Slider itself allows you to move forward and backward in the song.
Pressing the ❤️ button will add the song you selected to the Liked Songs playlist that appears on the Homescreen and the Liked Songs screen (in the navigation drawer).
You will notice that if a song from a playlist is playing in the background, a new tab will appear at the bottom of the screen, indicating which song is being played, which also (similar to the Songs Carousel) allows you to move forward and backward in the song with the Slider and skip to the next or previous song.
As mentioned before, you can switch themes between dark mode and light mode, using the moon icon that appears at the top right corner of the navigation drawer.
Oh, and one more thing!
In case you were wondering how adding/deleting songs works behind the scenes:
Every 30 seconds, the server simultaneously checks for compatibility between the song lists in the songs
folder and the database, and for each song one of the following actions is performed:
- If the song exists only in
songs
and not in the database ➡️ adds the song to the database. - If the song exists only in the database and not in
songs
➡️ deletes the song from the database. - If the song exists both in the database and in the folder ➡️ does nothing.
Or in a more "Pythonic" way, if you'd like:
if songs in songs_folder:
if song in database:
continue
else:
database.add(song)
elif song in database:
database.remove(song)
The product is still in its initial stages, so we would really appreciate feedback and donations 😄
And don't forget to star us — it motivates us a lot! ⭐
If you see an error message or run into an issue, or maybe you have an idea, or you're missing a capability that would make development easier and more robust, please create a bug report or submit a feature request.
If a similar feature request already exists, don't forget to leave a "+1".
If you add some more information such as your thoughts and vision about the feature, your comments will be embraced warmly 😃