- Published on
How to embed a simple javascript audio player with Django - code tutorial.
- Authors
- Name
- Adam Piskorek
- @hvitis_
Share your content, pictures on other people's pages
You can click PLAY and listen to it π. This is an audioplayer that actually is not on this page. The hvitis.dev is a pure static page. You can of course βΊοΈ record your own thought in seconds but probably - for now - you just want to read how it's done.
The coolest thing about it is that you can embed anything! You have a badge? Audio player? Video player? A GAME? Awesome. Let's do it.
How it is done
It's super simple: iframes
It's a way of embedding content from other pages on other pages. You have seen it maybe already on some pages. YouTube?
Exactly. It is important to know that the attributes you have there can be of course set by yourself by changing the link content but they are verified on the server.
If you have opened the iframes link then you have seen that we get tons of attributes there including such as: allowpaymentrequest, allowfullscreen and others. They are very important security measurements because after all - it's another page on your page. You do not know what does it do, what source code it has etc.
We read that this is embeded browser context and we know some basics already but I told you that we are going to do our own, right?
Django - let's start! π
We don't want to just show any content, let's make this tutorial slightly above beginner level and change the content dynamically. From now on you need basic django knowledge. I assume you know how to start a project and install new application (e.g. podcasts), add templates.
We need to:
- Make an audio model.
- Make a view (Pass some url kwargs).
- Make the HTML template to return.
- Return an HTML template.
- Use JavaScript to display what we want.
I will make a super simple model with podcast title and file:
# podcasts/models.py
from django.db import models
class Podcast(models.Model):
audio_file = models.FileField(
upload_to='podcasts/', null=True, blank=True)
title = models.CharField(
max_length=255, blank=True, null=True)
def __str__(self):
return self.title
Now let's register this model in admin to later be able to test the functionality by uploading test file.
# podcasts/admin.py
from django.contrib import admin
from .models import Podcast
admin.site.register(Podcast)
And let's make url with dynamic parameter that will help us query Podcasts. Don't forget to add it to main urls.ps.
# podcasts/urls.py
from django.urls import path
from .views import RenderHTMLPlayer # We are about to make this view in next step.
urlpatterns = [
# This is our URL int id attribute we later get with KWARGS.
path("/<int:id>", RenderHTMLPlayer.as_view(), name="podcasts-player"),
# id is automatically generated on created new Podcast so if you have
# uploaded your first file via admin you should have one podcast with id=1
]
Then we run short steps (again - I am assuming here basic Django knowledge as stated before):
- run migrations
- create admin user
- add one track (via admin panel using admin user)
- we create view.
# podcasts/views.py
from django.views.generic import TemplateView
from django.shortcuts import render
from .models import Podcast
class RenderHTMLPlayer(TemplateView):
pass
Now let's add template (we haven't made it yet!). Remember that templates are by default in templates folder and have default naming convention. I am calling it podcasts_player.html to be more verbose.
#...
class RenderHTMLPlayer(TemplateView):
template_name = "podcasts_player.html"
model = Podcast
Now we just need to get a track and return it's MEDIA_URL to the rendered view.
#...
def get(self, request, *args, **kwargs):
# Let's get our id from URL
id = self.kwargs.get('id')
# then we use this id to find corresponding podcast
podcast = Podcast.objects.filter(id=id).first()
# We obtain URL for saved media file.
podcast_uri = '/media' + \
request.build_absolute_uri(podcast.file.url).split('media')[1]
# We finally return the track URL in the context.
# It's needed to load audio via audio player.
context = {'track_url': track_uri}
return render(request, self.template_name, context)
That's almost it! Remember when I told you that there is a lot of attributes in iframes and they are there for a reason ?
βοΈβοΈ Those security attributes can be verified and added by Django and by server you are running it on (e.g. NGINx). If you want to serve your page as an iframe for others you must know more about Django middleware. That's Out of Scope for this tutorial.
Alright! What are we missing?
podcasts_player.html of course.
JavaScript - We are comming! π
We need to build a small audio player now!
In order to make it as lightweight as possible I am using pure-css module and font-awesome icons (that's maybe an overkill).
<link
rel="stylesheet"
href="https://unpkg.com/purecss@2.0.3/build/pure-min.css"
integrity="sha384-cg6SkqEOCV1NbJoCu11+bm0NvBRc8IYLRGXkmNrqUBfTjmMYwNKPWBTIKyw9mHNJ"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css"
/>
Playing audio and visualization will be done by wavesurfer.js that we add as a script to the end of the body (and actually before other script that actually run the wavesurfer).
<script src="https://cdnjs.cloudflare.com/ajax/libs/wavesurfer.js/1.0.53/wavesurfer.min.js"></script>
What is wavesurfer? It's a simple javascript audio player library. It's free and I prefer it over howler.js or amplitude.js. You get javascript audio player with waveform that is plug and play! You also have progress bar and it can be made to look like soundcloud one! (that's a good idea for the next post!). From my experience I had quality streaming (it preloads media files automatically).
You can make this tutorial with simple audio html5 audio player. Just use
<audio></audio>
in case you don't want to use any library. In this case just pass the link in the src but.. it's boring and not pretty. Follow this tutorial to have a better player.
The other script (with actual logic) we will see soon. For now let's make some simple skeleton with what we have right now:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Custom Podcasts in your blog." />
<title>Your Podcasts</title>
<link
rel="stylesheet"
href="https://unpkg.com/purecss@2.0.3/build/pure-min.css"
/>
<link
rel="stylesheet"
href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css"
/>
<style>
/* Here we can change the look and feel */
</style>
</head>
<body>
<div id="waveform"></div>
<button
id="play"
class="pure-button pure-button-secondary"
onclick="startRecording()"
>
<i class="fa fa-play-circle"></i> Play
</button>
<button
id="pause"
class="pure-button pure-button-secondary"
onclick="pauseRecording()"
>
<i class="fa fa-pause"></i> Pause
</button>
<button
id="stop"
class="pure-button pure-button-primary"
onclick="stopRecording()"
>
<i class="fa fa-stop"></i> Stop
</button>
<script>
// Uhh.. nothing fancy so far.. starts boring but here it goes - the core script!
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/wavesurfer.js/1.0.53/wavesurfer.min.js"></script>
</body>
</html>
So now we just need the last piece - the core, the heart of the operation - player and playing logic! let's see how our custom script will look like:
<script>
// Uhh.. nothing fancy so far.. starts boring but here it goes - the core script!
</script>
Let's start by getting the track_url from the context that we have on that page (we got in from Django views). You can think about the following as a simple javascript audio player tutorial.
// The content of the script tags is more interesting!
// That's how we get a value from Django context in our JS script
let trackUrl = '{{ track_url|safe }}'
Before starting those buttons let's initiate the audioplayer we got from previous script.
var wavesurfer = WaveSurfer.create({
container: '#waveform',
// Here you can use wavesurfer docs on configuration
// to customize your player!
})
We load the music using the MEDIA_URL we got for the track and passed to this script right..?
wavesurfer.load(trackUrl)
Now the only thing that is left is to play it! Let's get those buttons working by creating functions we assigned to their onclick events:
// We play, pause and stop our audio file with instanciated wavesurfer.js
function startRecording() {
wavesurfer.play()
}
function pauseRecording() {
wavesurfer.pause()
}
function stopRecording() {
wavesurfer.stop()
}
You can use now some tool to compress the written JavaScript - now the 5 bytes won't make a difference but with bigger files it's a good practice.
Now! How do we play that?
Well, assuming that:
- you made all that in a podcasts app (folder)
- your urls.py are exactly the same as the one I wrote here,
- you submitted 1 .mp3 file to podcast.
- you are running the server on port 8000.
then we should have a url like that:
http://localhost:8000/podcasts/1
You should be able to see something like this in your browser:
Now if you have more podcasts, you will have corresponding urls ending with 2, 3 etc. All you need to do now is to attach the URL in your iframe:
<iframe src="http://localhost:3000/player/zh"></iframe>
You are of course limited by nothing but your imagination! I made audio player with playlist for websites as you can see on the beginning of this post. You could do javascript audio player on mac (the safari browser may have some hiccups with this one)
and...
DEPLOY!
Thank you for reading!
Did you make any mistakes when using embedding or you've seen one here? Tell me about your insights. Leave a comment with You are most welcome to see more posts of this type just go to home page