How to: Use JWPlayer + Cloudfront to stream audio and prevent downloading.
I've been, for the last couple of months, implementing audio playback via streaming on my website. The task was fairly simple to achieve using JWPlayer and Amazon Cloudfront. There are several guides here and asking always works!
However, I still had the problem that the files were public, so anyone could download them. After asking in different places, I've been able to implement a solution that I think could help other people.
2) Streaming MP3 files
3) Using RTMP
4) Amazon Cloudfront
5) The files are in a playlist.
So the question is, how to stream the files and prevent people from downloading the MP3's? Well, here there's a solution.
1) Download and install Cloudberry Explorer (CE) S3.
2) Set up all the necessary connections. There are lots of guides all over the internet on how to do this, so I'll skip that explanation.
3) Once CE is configured, create a bucket. Name it whatever you want. For my example I'll use playlists.mydomain.com as the name of the bucket, this is useful if you want to use a CNAME.
4) Make all its contents public (Right click + ACL, Make public and include all subfolders and files).
4.1 Optionally, you can create a CNAME for your bucket. Go to your hosting's CPanel, advanced DNS Settings, and create the CNAME:
TTL: 1400 (this is up to you actually)
After doing this you can put any file inside the bucket and try to open it using: http://playlists.mydomain.com/myfile.html
The DNS can take some time to expand, but you can check it by opening a command window (Run--cmd), and do:
If it doesn't receive any response just wait and try again later.
5) Go back to CE and create another bucket, here is where your MP3's will live. I will name this one mp3s.mydomain.com. It doesn't really matter the name though.
6) Using CE create a RTMP Cloudfront distribution for that bucket. Three things are important here:
a) Following the wizard, you must activate "Enable Private Content Distribution"
b) Copy the key besides "S3 Canonical User ID".
c) Leave "Add myself as a truster signer" UN-checked!.
6.1 You can also create a CNAME here, if you know what CNAME you will use you can insert it on the first screen of the wizard.
6.2 Go to Amazon's Console, Cloudfront, and copy the address of the distribution. Go back to CPanel and create the CNAME for that distribution.
7) Go back to CE. Right-click on the bucket/distribution you've just created and select "Bucket Policy".
7.1 Under Policy Designer, Click on "New Statement"
7.2 Select Action: S3: Get Object
7.3 To: Select "Add" and paste the Canonical User ID you copied from the wizard.
7.4 In: arn:aws:s3:::mp3s.mydomain.com/* || This is is the name of the bucket where all the MP3's live. Note the /*, which means "access to all the contents inside the bucket".
7.5 Go to Policy Script and where it says:
Replace it for:
7.6 Click Apply and OK.
8) Right click on the bucket and select ACL Settings, and make sure that "Cloudfront Origin Access" has read access and that you apply it to all subfolders and files. Do not make public the files though, just Cloudfront access!
Congratulations! You've completed the configuration!
Not we just have to create our playlist and embed the player.
What we did during the configuration was to grant access to all MP3's inside the bucket mp3s.mydomain.com to Cloudfront. However, if someone tries to load the file via Http, s/he will not get access to the files. Only via RTMP, through Coudfront.
On the other hand, we have our playlists in another bucket, therefore if someone downloads the playlist, it has no way to either to know the location of the MP3 files nor to access them. Only via streaming.
The playlist file can look something like this (Assuming you're using a CNAME for the Cloudfront distribution):
bc.. <rss version="2.0" xmlns:jwplayer="http://developer.longtailvideo.com/">
...... Repeat for as many songs as you want....
So, the playlist is telling you that the files are under:
and these can be accessed via rtmp://mp3s.mydomain.com/cfx/st
But the actual bucket doesn't need have the same name, and as I said before, even if someone has the name it won't be able to access the files directly via http.
I'm currently using the following code generated by the Embed Wizard here at Longtail:
bc.. <div id="player1">Loading...</div>
'repeat' : 'list',
And that's it.
With this you can stream private files and prevent people from downloading them. Of course always someone can try to get hold of your RTMP streaming, but how many people will actually do that? If they are patient enough as to do it, then just consider that they deserve having them, as a price for their effort. However, normal people will not be able to download the MP3's, even if they download the playlist.xml. That file is useless for everybody but the player.
I hope this helps someone.
I want to thank "Cloudberry Labs" support for helping me with this solution. The whole configuration part was possible thanks to their help.
And thank you Longtail for this wonderful, free, player.