Create a Simple Music Streaming App with Flask
The final product of this tutorial is a simple music streaming and downloading application.
In this application, the user will be able to do the following:
- Upload music themselves and Play the music uploaded by the user
- Download the music via HTTP and streaming it with HTML5 audio.
Introduction
Let’s Get Started!
The first thing to do is to install Flask. To do this, simply run the command
|
1 |
$ pip install Flask |
You can refer the official Flask documentation to install Flask correctly.
To verify whether Flask is installed correctly in your system, go to the command prompt/Terminal and enter into Python shell and then type the command
|
1 2 |
>> import flask >> |
If the command raises no error, then you are good to go.
Now open up your favorite text editor( we recommend Sublime Text 2) and create the main root folder and name it as musicstream and then create a python package inside the root folder and name it as app .
Python package can be created by creating a new python file called __init__.py inside the folder to mark it as a python package.
Learn more about Python packages from the official Python docs.
Create another two folders static and templates inside the app directory and another folder inside static called uploads and css and one python file called run.py inside your root folder. Now your directory structure should look like this.
It’s the best practice to use a package instead of a module for larger applications in Flask instead of a single python file.
Initializing the application
Now inside your __init__.py file add the following bunch of code.
|
1 2 3 4 5 6 7 8 |
import os from flask import Flask app = Flask(__name__) APP_ROOT = os.path.dirname(os.path.abspath(__file__)) UPLOAD_FOLDER = os.path.join(APP_ROOT, 'static/uploads') app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER |
So what did that code do?
We just imported the Flask class and then creating an instance of Flask class and created an object of it and If you are using a single module (as in this example), you should use __name__ with the class.
Next we have the UPLOAD_FOLDER this is where we will store the uploaded files and then in the final line we are configuring the app variable with our UPLOAD_FOLDER.
Save it and then create a new file inside the app package called as views.py this file will hold all our views.
Since our stubs are in place we can start developing the related code.
lets open views.py and then import some more methods
|
1 2 3 4 |
import os from flask import render_template, request, send_from_directory from werkzeug.utils import secure_filename from app import app |
We have imported the app object from the app package along with some other imports.
Now add the index method
|
1 2 3 |
@app.route('/') def index(): return render_template('index.html') |
We have decorated the route for the index and when it’s called the index.html will be called but we haven’t yet created it, so lets create that first and then come back here.
In your templates directory, create layout.html file which will serve as the base template for our file and we will inherit from this base file.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!DOCTYPE html> <html> <head> <title>Audio Streaming App</title> <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.css') }}"/> <link rel="stylesheet" href="{{ url_for('static', filename='css/custom.css') }}"/> </head> <body> <div class="container"> <div class="page-header"> <h1>Flask Audio Streaming App</h1> </div> {% block content %} {% endblock %} <hr/> <div class="modal-footer"> <h4>© pypix</h4> </div> </div> </body> </html> |
It’s just the normal html , its self-explanatory, we are using inbuilt Flask method url_for to call the style-sheets from our static directory, url_for generates a URL to the given endpoint with the method provided.
Download Bootstrap and include only bootstrap.css file inside css folder along with custom.css as the other files are not needed for our application.
include this css into custom.css file
|
1 2 3 4 5 6 7 8 9 10 11 12 |
.audio { width: 100%; } .modal-footer { text-align: center; } .form-audio { margin-left: 350px; } .page-header { text-align: center; } |
Now we have {% block content %} and {% end block%} these are jinja2 blocks, in jinja2 the decision-making stuffs are enclosed inside {% %} and the variables to display into the browser are enclosed into {{ }} . the purpose of the block tag does is to tell the template engine that a child template may override those portions of the template and that’s how we can achieve the inheritance in templates and we can have common portions of the entire site into one place without writing the code all over again in all the pages.
Next create index.html and inherit the layout.html and fill out the block contents like this
|
1 2 3 4 5 6 7 |
{% extends 'layout.html' %} {% block content %} <h1>Hello</h1> {% endblock %} |
now, the h1 content will be the injected into the layout.html in the position where we have declared the block tags.
( You can verify this by seeing the source of the web page by pressing ctrl + U )
Now in run.py include this lines of code
|
1 2 |
from app import app app.run(debug=True) |
This is pretty simple and straightforward.
Now if you run this command
|
1 |
$ python run.py |
you will get an error because you havent yet linked the views with your app object, to do so include this line at the bottom in __init__.py.
|
1 |
from app import views |
Now run the app and you will get the pretty welcome message, it everything worked well, you will see something like this.
Uploading Songs
For uploading file, we will create two route, one for uploading and the another for displaying the uploaded content.
Add this lines below the index method in view.py
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@app.route('/upload', methods=['GET','POST']) def upload_file(): if request.method == 'POST': file = request.files['file'] if file.filename: filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) return render_template('index.html', filename=filename) return render_template('index.html') @app.route('/uploads/') def uploaded_file(filename): return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True) |
lets see line by line, first we declared the route for upload and it accepts only GET and POST request to that method i.e you can only get and post on this url http://localhost:5000/upload and then we are checking if the method is post , get the file from the user and if it has a filename save it to our uploaded folder which we declared before else if the request is get, render the index.html template.
next method takes the filename of the file we uploaded as an argument and returns the file from the directory with the same filename to be rendered by the template to view in the browser. These methods are pretty straight forward too. isn’t it ?
Now we have our views in place lets modify our index.html to upload the file and stream the audio.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
{% extends 'layout.html' %} {% block content %} {% if filename %} <div> <h2>Song : {{ filename }}</h2> <div class="hero-unit"> <audio class="audio" controls> <source src="uploads/{{ filename }}" type="audio/mpeg"> </audio><hr/> <p> <a href="{{ url_for('index') }}" class="btn btn-primary">Home</a> <a href="/uploads/{{ filename }}" class="btn btn-info">Download</a> <a href="{{ url_for('upload_file') }} " class="btn btn-danger">Upload Another</a> </p> </div> </div> {% else %} <div class="form-audio"> <h2>Upload Song</h2> <form action="{{ url_for('upload_file') }}" method="post" enctype="multipart/form-data"> <input type="file" name="file" class="button" multiple> <br/><br/> <input type="submit" value="Upload" class="btn btn-danger"> </form> </div> {% endif %} {% endblock %} |
The code is plain html except the url_for tags in between, the url_for takes the method of the function to call as the argument and it renders the anchor tags for us.
We are using the single file to upload the file as well as to display the uploaded file.
Conclusion
With this we have completed our Mini Application using Flask.
For those of you who are Python experts, I’m sure that you can find a way to optimize this application even more. In addition, it would be great to share any optimizations that you make in the comments section so that readers can get even more out of this tutorial.
-
Raphael Marra
-
ajkumar25
-
Kousik Kumar
-
ajkumar25
-
-
-
-
Yaya
-
ajkumar25
-
etng
-
-
spilrdt
-
ajkumar25
-
spilrdt
-
ajkumar25
-
spilrdt
-
spilrdt
-
ajkumar25
-
Kerbobotat
-
ajkumar25
-
ajkumar25
-
mapleray
-
-
BruceLi
-
-
-
-
Neeraj
-
ajkumar25
-
Neeraj
-
CSMajor
-
-
Mayank Chaudhary
-
-
jerome
-
Tushar Rajput
-
Shaun Koo





