Storing local audio file data across page loads in HTML5 - html

I am trying to make a webapp that will load a page from a remote server, but allow the user to play audio from files that are on their local drive (not downloaded from the remote server). I am able to get this to work, but I also need it to save what the user has done for subsequent visits. For example: the user loads a page, clicks a "choose file" button, selects an mp3, and plays it. The user then closes the browser, opens it again, returns to the page, and is able to play the same audio without having to select it again.
I understand that the audio playback is separate from the saving of the user's selection, but in this case one seems to dictate the other.
I am able to get the select-and-play functionality to work with this:
<html><body>
<script type='text/javascript'>
function handleFiles(files){
var file = window.URL.createObjectURL(files[0]);
document.getElementById('audioPlayer').src = file;
}
</script>
<audio id='audioPlayer' controls ></audio>
<input type='file' id='selectedFile'
onchange='handleFiles(this.files)' />
</body></html>
...but I do not know how to store the selected file data in a way that I can automatically load it on the next visit. What can I use to store that file location (or even the whole file itself if it comes to it) so that I can still play the audio without the user selecting the file again?
I kind of suspect that saving the local file url somehow may not be possible for security reasons, since auto-playing a file from the local file system without user interaction could be bad news.

File handles from File open dialog are not recycleable across different page load sessions.
The best you can do this that you copy audio data to a HTML5 localStorage and play it from there. Or upload the data to your server and play it from there.
http://docs.webplatform.org/wiki/apis/web-storage/Storage/localStorage
localStorage is limited to few megabytes depending on the browser.

At this time, Mikko's answer is the correct answer for my question, but I thought I'd share a possible alternative for anyone else who comes across this thread:
The FileSystem API looks like it would perfectly suit my needs in this case, but at the time of this writing, it is only supported in Chrome. If audio playback is a minor add-on feature to your webapp though, this might be an option to give Chrome users a better experience and other users would just be unaware that they're missing out.
In this HTML5 Rocks article, the author shows how to use it, including how to copy user-selected files into a local disk sandbox and how to get a url (needed in my case to audio playback) to those files.

Related

How do you change source in a web audio context

I'm making a game that changes some of it's object depending on what music is playing. After each song has ended I want my audio context to load in a new source and analyze that. However whenever I tried to do that I've gotten the error that an audio object or buffer can't be called twice.
After some researching I learned that ctx.createMediaElementSource(MyHTML5AudioEl) lets you create a sourceNode that takes the source from a HTML5 object. With this I was able to loop through different song.
However for my game I need to play/analyze a 30 seconds "remote url" that comes out of the Spotify API. I might be wrong but ctx.createMediaElementSource(MyHTML5AudioEl)does not allow you to analyze a source that is on a remote site.
Also the game needs to work on Mobile Chrome, which createMediaElementSource(MyHTML5AudioEl) does not seem to work on.
I might be on the completely wrong path here but my main question is:
How can I switch remote songs urls in web audio api. With it being compatible with mobile chrome.
Thanks!
First, as you found out, you can't set the buffer again for an AudioBufferSource. The solution is to create a new one. AudioBufferSources are intended to be light-weight objects that you can easily create and use.
Second, in Chrome 42 and newer, createMediaElementSource requires appropriate CORS access so you have to make sure the remote url sends the appropriate headers and you set the crossOrigin attribute appropriately.
Finally, Mobile Chrome currently does not pass the data from an audio element through createMediaElementSource.

HTML5 read files from path

Well, using HTML5 file handlining api we can read files with the collaboration of inpty type file. What about ready files with pat like
/images/myimage.png
etc??
Any kind of help is appreciated
Yes, if it is chrome! Play with the filesytem you will be able to do that.
The simple answer is; no. When your HTML/CSS/images/JavaScript is downloaded to the client's end you are breaking loose of the server.
Simplistic Flowchart
User requests URL in Browser (for example; www.mydomain.com/index.html)
Server reads and fetches the required file (www.mydomain.com/index.html)
index.html and it's linked resources will be downloaded to the user's browser
The user's Browser will render the HTML page
The user's Browser will only fetch the files that came with the request (images/someimages.png and stuff like scripts/jquery.js)
Explanation
The problem you are facing here is that when HTML is being rendered locally it has no link with the server anymore, thus requesting what /images/ contains file-wise is not logically comparable as it resides on the server.
Work-around
What you can do, but this will neglect the reason of the question, is to make a server-side script in JSP/PHP/ASP/etc. This script will then traverse through the directory you want. In PHP you can do this by using opendir() (http://php.net/opendir).
With a XHR/AJAX call you could request the PHP page to return the directory listing. Easiest way to do this is by using jQuery's $.post() function in combination with JSON.
Caution!
You need to keep in mind that if you use the work-around you will store a link to be visible for everyone to see what's in your online directory you request (for example http://www.mydomain.com/my_image_dirlist.php would then return a stringified list of everything (or less based on certain rules in the server-side script) inside http://www.mydomain.com/images/.
Notes
http://www.html5rocks.com/en/tutorials/file/filesystem/ (seems to work only in Chrome, but would still not be exactly what you want)
If you don't need all files from a folder, but only those files that have been downloaded to your browser's cache in the URL request; you could try to search online for accessing browser cache (downloaded files) of the currently loaded page. Or make something like a DOM-walker and CSS reader (regex?) to see where all file-relations are.

Audio tag security in html5

Long version:
I use html5 audio tag to play mp3 files on my website. With Flash I can stream mp3's and secure it for 95%.
With html5 it is easy to find out the mp3 location and just download it from there. Even if I secure it with unique hashes it is not hard to inspect the network tab in chrome and see the mp3 url with hashes.
I was wondering if there are other ways to secure the mp3 from being ripped and if it is worth the time. For example bandcamp does generate unique hashes but it is still very easy to download the mp3. For youtube you got download websites that can proces the flv stream and rip the audio and save it for the user as mp3 format.
The first layer of security I can think of is change the extension of mp3 files to .txt or another common format.
95% of the users don't spot the extension because it is hidden by default on windows and apple. This will prevent the first 95% of the users to spot and play the mp3 file.
Short Version
Any suggestions to prevent users from stealing mp3 files while using html5 audio tag.
Short Answer
No.
Renaming the audio file to .txt is not going to do anything to help the security of your mp3 audio file. If anything, it is going to cause you even more issues, because now, your mp3 audio file is going to be sent with the incorrect MIME type, which may cause issues with the browser's built in audio player.
The best suggestions that I can provide you is:
Make sure that your checking the REFERER http header, make sure that it is coming from the page that has the mp3 player on it.
Protect the mp3 file with a unique hash.
Don't allow the same hash to be downloaded twice*
*Note that even doing this could cause issues, for example, what happens if the user reopens a tab from cache, plays the file again, and the mp3 file is not cached?
And finally, at the end even after your mp3 file is the most protected mp3 file in the history of IIS and Apache -- what is stopping me from just opening up Adobe Audition, and recordinging the audio stream?
Although you are correct about Bandcamp's MP3 audio stream, the mp3 is not as high quality then just a normal download after purchasing an album.
The fact that even Google does not really have any decent protections on it's video streams should say something. A company that generates billions of dollars from video views on YouTube can't even make (or better put -- has not bothered to put in place) any viable methods for protecting their videos.
Kind of.
Grooveshark send a POST request to a server-side script for the MP3 that is being streamed which makes it very difficult to just access and spoof without dynamically creating a POST request yourself - especially seeing as you would have to then attempt to store the audio file that is collected. But you can use the new AudioContext to help solve this for most modern platforms...
I used a great example from HTML5Rocks.com to alter the headers used as follows:
var dogBarkingBuffer = null;
// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
function loadDogSound(url) {
var request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer = buffer;
}, onError);
}
//this is the encryption key
request.send("key=98753897358975387943");
}
Related
As you can see I am also sending a key value which could possibly be part of a public/private pair too. This should put anyone off attempting to intervene - other than simply recording the MP3 as it's playing, of course, but what could possibly stop that in any environment inside or out of a computer?
You could make the MP3s themselves unattractive. Some ideas:
Don't include album art, album info, etc. in your files (id3 tags). Even better, fill out all id3 tag fields with something like "This file is from myMusicSite.com".
Split your files into several smaller pieces, and then play them in sequence in the browser. Having to download all the individual pieces will make your files much less attractive. You may have problems with gapless playback, not sure how well that's supported though.
Encode and play them as a video, maybe with your logo or something as the video stream. The resulting files won't be much larger, esp. if you use a static image. This will mean that users can't play your files on mp3 players, phones, etc. easily.
Whisper your domain name or website name in the recordings a few times, as mentioned in the comments.

HTML5 window.applicationCache - user decides to download

In HTML caching, my understanding is that when the manifest file is updated on the server, the browser downloads the latest files and swaps the cache.
Is there a way to stop the browser doing this until the user gives the go-ahead?
For example, displaying a notification to the user saying something like "there is a new version available. Do you want to download it? Y/N". If the user says "No", then the browser should keep the old files around.
Handle the updateready event and then conditionally call swapCache().

Downloading files

Right now I have FILE to allow users to download a file. I don't like that because it forces them to leave the current page and have to reload it (which takes a few seconds) when they want to go back
What is the easiest way to have users download a file?
Have the server send a Content-Disposition: attachment header for the resource in question. It'll then be presented to the user (if they have a sane browser) as a file to "save", rather than as a new page.
For certain types of resources this may mean you write a proxy script in PHP, or perhaps you can configure your webserver to do it.
Use this method:
FILE
The most reliable way to force a download without a server-side solution is to ZIP the file and then link to this archive. Provided that there aren't any limitations on using ZIP files almost every web browser I've encountered will download the file to the user's computer.
If you don't have server-side support, which I am just assuming because you're asking about the HTML and not a scripting language, you cannot always make a file download form the browser. This is because not every web browser is configured the same and the default application on the user's computer may also be set to something you can't predict.
Also, you should use the linking method that #craig1231 suggested so that the file download request is happening in a new window.
FILE
This will cut down on some of the time needed to refresh pages and, in most cases, when the web browser encounters a ZIP file as the URL of the window it will close the window once the file starts to download.