Playing local HTML5 audio from an external server on desktop - html

My problem corresponds with the following hypothetical situation:
I have a website with a blog, which stores a playlist of music (just the filenames). I can edit this playlist remotely, for example from my phone when I am on the move. The content of the website is stored in a database on the server (MySQL), which cannot be accessed remotely.
When I get home and I am writing on my blog, I want to play the files in the list, on the same website, by using HTML5 audio. The files are located on my local computer at home. Hence I want to access these local files through my website.
An example of how I am addressing a local file is file:///M:/music.mp3.
The whole set-up works if I work from localhost, so I don't think it is a coding issue.
The problem is that both Firefox and Chrome, my favourite browsers, do not allow third party websites to access my local files without my active input.
It makes sense that the construction above is prevented by user agents due to security issues. I was hoping to find a solution in the fact that I use browser integrated HTML5 audio; IMO, there would be no security issue since the files that are loaded by HTML5 audio cannot be accessed via DOM, so some proper coding of the browsers would have left some breathing room here.
Some extra conditions:
I am looking for the blog and the music player to remain integrated.
I don't want to store my music files remotely.
I don't want to set up a local server.
Perhaps there is a way to add a security exception for my website to my browser, but this seems no longer the case for Firefox.
Any suggestion is most welcome!

I would suggest taking a look at the File System API. It's a very new API that's currently only working with chrome unfortunately :/
What you can basically do is request for access to the local filesystem using window.requestFileSystem() or window.webkitRequestFileSystem(), which has a success callback with a FileSystem object. Using this objects root (a Directory Entry object) you can look up the file using root.getFile(). This has a callback with a FileEntry object. You can then use this file entry to get the actual File object using fileEntry.file() and pass that into a FileReader object to get the data url. Untested example below, probably not perfect and you probably have to tweak with webkit prefixes.
// when file system loads
function onFs(fs){
// locate file
fs.root.getFile('M:/music.mp3', {/*options*/}, function(fileEntry){
// get file / blob
fileEntry.file(function(file) {
// read file
var reader = new FileReader();
reader.onload = function(event) {
var dataUrl = event.target.result;
// create new audio object with data url
// e.g. <audio src="dataUrl" />
};
reader.readAsDataURL(file);
// handle error
} , onError);
// handle error
}, onError);
}
// Opening a file system with temporary storage
window.requestFileSystem(TEMPORARY, 1024*1024 /*1MB*/, onFS, onError);
(I'd like to also mention, I've never used the File System API, but it seems promising)

Related

Best approach to monitor download progress with OneDrive API on WP8.1?

I have a WP8.1 app using the new OneDrive API. I use the C# SDK provided, I get therefore something like this:
var dlStream = await Connection.DownloadStreamForItemAsync(mNode.ItemReference(),
StreamDownloadOptions.Default);
file = await folder.CreateFileAsync(fileName,
CreationCollisionOption.ReplaceExisting).AsTask();
fileStream = (await file.OpenAsync(FileAccessMode.ReadWrite)).AsStream();
var v=dlStream.CopyToAsync(tn.FileStream);
I have not tried it yet, but it seems to be the right way to do it. My concern now is "how to monitor the transfer progress and status?"
Knowing that the DownloadStreamForItemAsync method does something like this:
response = await GetHttpResponseAsync(request);
var responseStream = await response.GetResponseStreamAsync();
I have thought about using a timer, and each second check the stream length, but
I don't know if it is the right approach of if there is an alternative way
I don't know if this may not create some cross-thread errors for the stream
How to detect a transfer failure ?
I guess one of the approaches would be to re-write partially the OneDrive SDK portable project, target only WinRT projects and use Windows.Web objects instead of System.Net, but it seems to be some work for an unsure result.
Any help? :)
You can use the LiveConnectClient class inside the Live SDK instead of downloading the file as a stream and saving it to a file.
Use the BackgroundDownloadAsync(string path, Uri downloadLocation) method to download a file
Begins downloading a file from Microsoft OneDrive to a Windows Phone
isolated storage. [Windows Phone only]
The file download should continue even if the app that starts the file
download quits or is suspended.
Subscribe to the BackgroundDownloadProgressChanged event
Raised at indeterminate times while a file is downloading from Microsoft OneDrive to Windows Phone isolated storage. [Windows Phone only]
Hope it helps!

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.

Storing local audio file data across page loads in HTML5

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.

Crossdomain policy behaviour on 302 redirects in AS3

I have crawled the web quite a lot these days, but couldn't get any accurate information on how crossdomain.xml files behave in case of 302 redirects; especially with the sandboxes having changed significantly over the last versions!
I am relatively new to flash... so any advice is more than appreciated!
I have been working on a project lately that uses audio streams with some sort of CDN distribution! what happens is that a common url is triggered, and then the user is dynamically redirected to the next best server available. In my case, i have no access at the server side of things (at least not anytime soon). And the only path providing an appropriate crossdomain.xml is the one performing the redirect. All the other dynamic paths provide exclusively content!
http://resource.domain.com (valid crossdomain.xml)
302 => http://dyn1.domain.com/...
302 => http://dyn2.domain.com/...
302 => http://dyn3.domain.com/...
I noticed that flash doesn't care much if i try to load the audio stream with something like...
var req :URLRequest = new URLRequest("http://resource.domain.com");
var sound :Sound = new Sound(req); // ie. effectively playing http://dyn3.domain.com
sound.play();
It gets both redirecting, and streaming done well! and doesn't bother for any crossdomain file and starts playing!
Although when i try something different, like setting up some custom headers to the request and loading the file with URLStream instead, everything gets messy! Well, the redirect gets done, as expected but all of a sudden i need another crossdomain file in the redirected location!
Is there any explanation to whats happening and eventually ways to resolve this?!
Thanks for your time!
It comes as a site question : i noticed everything to work flawlessly while being in the local-trusted sandbox and errors happening mainly if not exclusively in the remote sandbox. is it possible that the local-trusted sandbox doesn't care about crossdomain policy files at all!?
Summary
Add crossdomain.xml to each CDN host or adopt to limited Sound functionality.
Details
SWF files that are assigned to the local-trusted sandbox can interact with any other SWF files and can load data from anywhere (remote or local).
Sound can load stuff from other domains that don't allow access using cross-domain policy with certain restrictions:
Certain operations dealing with sound are restricted. The data in a
loaded sound cannot be accessed by a file in a different domain unless
you implement a cross-domain policy file. Sound-related APIs that fall
under this restriction are Sound.id3, SoundMixer.computeSpectrum(),
SoundMixer.bufferTime, and the SoundTransform class.
Flash in general has pretty complex cross-domain policies but in your case the bottom line is that you'll need to have proper crossdmain.xml on each host except the one that serves the SWF:
3.1. If your file is served from http://resource.domain.com it's not required to have http://resource.domain.com/crossdomain.xml but it's really good to have one.
3.2. You will need to have proper http://dyn2.domain.com/crossdomain.xml explicitly allowing your SWF to access dyn2.domain.com to be able to use URLLoader and other APIs that provide access to raw loaded data.
3.3. There's a reason for these restrictions - cookies (and other ambient user credentials). If Flash would not require proper cross-domains after a redirect, one could access any domain with user cookies attached by simply loading his own redirector first. This means accessing all user cookie-protected data (e.g. mail.google.com) from any SWF on the internet that's running in your browser.

Can you locally create a HTML form that outputs a .txt file to be saved?

Can you create a html form that can be housed on a USB flash drive and opened up in a browser that allows someone to enter info and then allows them to save what they entered as a .txt file back to the same USB? Any ideas or resources you can point me to?
Not a full solution, but maybe it gets you on the right track:
Generate a usual HTML page with a form to enter all information necessary.
Then use JavaScript to build a string containing all data you want to store inside the textfile.
Create a Blob() object out of it (MDN docu) - the type application\octet-stream is important to force a download later on:
var myBlob = new Blob( content, { "type" : "application\/octet-stream" });
Convert that blob to a DataURL using window.URL.createObjectURL (MDN docu):
var dataUrl = window.URL.createObjectURL( myBlob );
Update the location of your browser tab using window.location and set it to your data url:
window.location = dataUrl;
The user will then have the usual "Save file as ..." dialog for your generated textfile. Note, however, that this way you are not able to set the name of the textfile!
Not directly. Since this type of form processing has to occur server-side, you need a web server.
Now, it is entirely possible to run Apache or something similar from that flash drive, and have PHP or something do your file writing. This isn't as straightforward as you are looking for, but is possible. Keep in mind that not everyone has autorun enabled, that folks use different OSes, and that firewalls are often picky about new applications opening up ports.