/    Sign up×
Community /Pin to ProfileBookmark

Protect (from direct download) and play sound files

Hi,
I wish to serve (using PHP) sound files off the server as I believe that is a good way to do so. However I also wish to protect the sound files and want to put them above the server root. On the client side the process is set rolling by a button press and then some n different sound files have to play and I need them to be served off the server. Is this possible ? If so how can it be accomplished?

If not then how to play sounds client side and protect the sound files on the server from direct download ?
Thanks loads !

to post a comment
JavaScript

14 Comments(s)

Copy linkTweet thisAlerts:
@NogDogOct 09.2019 — I would just make a PHP file-server script that would take a GET argument for the file identifier, sanitize it (e.g. to prevent any sort of directory injection), then use readfile() to output the file if it exists, else return a 404. (You'd also want to set applicable HTTP headers before doing the readfile().)
Copy linkTweet thisAlerts:
@ajooauthorOct 09.2019 — Hi, Thanks ! You said you would use the readfile() to output the file ? output where ? And what exactly does the readfile() contain ? The sound file -- like some.mp3 ? And finally how would the readfile() play the sound ? Maybe you can demonstrate with a basic example.

Thanks !
Copy linkTweet thisAlerts:
@NogDogOct 09.2019 — The PHP would just be to serve up the file to the browser from the web server (the same as the web server serves up the HTML, JavaScript, CSS, and image files. Instead of having your relevant HTML attribute point directly at the file, e.g. src="/static/audio/fubar.mp3", it might instead be something like `src="/static/audio/file.php?name=fubar.mp3". Then the "file.php" script would confirm the user is logged in, or whatever other criteria you want to use (http referer?) to allow access to the file.
<i>
</i>&lt;?php
session_start();
if(empty($_SESSION['user_id']) {
// throw some sort of "not allowed" error, e.g.:
header('HTTP/1.0 403 Forbidden');
exit;
}
if(!empty($_GET['file'])) {
$file = basename($_GET['file']);
$dir = '/full/or/relative/file_system/path/to/audio/';
if(file_exists($dir.$file)) {
header('Content-Type: audio/mpeg');
header('Content-Length: ' . filesize($dir.$file));
readfile($dir.$file);
exit;
}
}
header('HTTP/1.0 404 Not Found');
Copy linkTweet thisAlerts:
@ajooauthorOct 09.2019 — Thanks ! I'll give it a go and revert.

Just one thing though, would the code above sound a file as it is or would something need to be done with the readfile($dir.$file); to actually play / sound the file?

Thanks again.
Copy linkTweet thisAlerts:
@NogDogOct 09.2019 — @ajoo#1609927

Oh, as far as playing it, that would be on the browser side -- which is not my area of expertise. You would presumably use some javascript audio player component, and wherever you specify the URL for the sound file in that component, you would use the relevant URL to that PHP file.
Copy linkTweet thisAlerts:
@ajooauthorOct 09.2019 — Hi ! Thanks for that insight. May I request someone with that expertise to kindly demonstrate how to use the readfile() received from php to play the sound file dynamically such that more than one sound file may be programmatically played on the client side. For example if I have an array of sounds like [a.mp3, b.mp3, c.mp3, d.mp3], how can i play these one after the other using files provided by php readfile as shown by NogDog
Copy linkTweet thisAlerts:
@NogDogOct 09.2019 — Maybe start with https://www.w3schools.com/html/html5_audio.asp ? (HTML5 audio player)
Copy linkTweet thisAlerts:
@SempervivumOct 09.2019 — Yes, I tested it: You can play such file like any audio file by the HTML5 audio element. In order to play one audio after another you will need to attach an event listener to the "ended" event of ths player and set the source to the next one in the array.
&lt;audio src="get-hidden-audio.php?file=track1.mp3" controls&gt;&lt;/audio&gt;
Copy linkTweet thisAlerts:
@ajooauthorOct 09.2019 — Hi

@Nogdog Thanks for the link. I have already checked it out. I was hoping to do it without using an embedded player. you know, dynamically, using JS as below:-

audio = new Audio(data);<br/>
audio.type = "audio/mpeg";<br/>
audio.play();


where data would be the sound object retrieved from $readfile(filename) from php. I have tried this using a $.post request. While I get the data ( sound file), the $.post being ajax and thus asynchronous, the program gets lost without errors and without any sound.

@Sempervivum#1609937 Thanks very much for chipping in. In your example I see that track1.mp3 is hard coded. If I use an event listener, how would I change the name of the next file to play? Basically the src = "" needs to be dynamic and I need to keep changing it. How would I achieve that ? Would you be kind enough to provide a small example?

Thanks loads !!
Copy linkTweet thisAlerts:
@SempervivumOct 09.2019 — Regarding the audio object: You can use this as well.

Regarding setting the src:
var idx = 0;
audio = new Audio(data);
audio.addEventListener('ended', function() {
if (idx &lt; your_array.length) idx++;
else idx = 0;
audio.src = your_array[idx];
audio.play();
});
audio.type = "audio/mpeg";
audio.src = your_array[0];
audio.play();

Untested. What I'm not shure about: There is also an event "canplay". Maybe one has to wait for this event before playing the audio by calling play().
Copy linkTweet thisAlerts:
@ajooauthorOct 10.2019 — Hi !

Pursuing the above I have come across something strange.

I have a fiddle [here](https://jsfiddle.net/ajoo/a2wryqL0/) that plays a sound.

However when i put the same code in an HTML file and try and play it off my local server, it gives an error.

> Uncaught (in promise) DOMException

Here's the html file with the same code.

&lt;html&gt;<br/>
&lt;head&gt;<br/>
&lt;title&gt;My Sound&lt;/title&gt;<br/>
&lt;/head&gt;<br/>
&lt;body&gt;<br/>
&lt;script type="text/javascript" src="<URL url="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js%22%3E%3C/script">https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script</URL>&gt;<br/>
&lt;script&gt;

$(document).ready(function(){

<i> </i><CODE>var url = "https://hpr.dogphilosophy.net/test/wav.wav";
<i> </i>var audio = new Audio(url);
<i> </i>audio.type = 'audio/wav';
<i> </i>audio.load();

<i> </i>audio.addEventListener("loadeddata", function() {
<i> </i> audio.play();
<i> </i>}, true);</CODE>
})

&lt;/script&gt;<br/>
&lt;/body&gt;<br/>
&lt;/html&gt;


Hopefully someone can point out what the issue is. Once the sounds get playing correctly then the url can be modified to get the data from readfile().

Thanks !


Copy linkTweet thisAlerts:
@vaillandt6Jan 28.2022 — I think what is described above may not really help, since we do not know the very structure of the author's code
Copy linkTweet thisAlerts:
@SempervivumJan 28.2022 — @vaillandt6#1641989 No benefit in resurrecting a two year old thread. Closing.
Copy linkTweet thisAlerts:
@SempervivumJan 28.2022 — {"locked":true}
×

Success!

Help @ajoo spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 4.25,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,

tipper: @Samric24,
tipped: article
amount: 1000 SATS,
)...