Fully preload html5 video from CDN in Safari - javascript

I'm looking for a solution to fully preload an html5 video so that I can play it through and seek to different times without any risk of buffering. I've seen solutions that involve using xhr to download the video file as a 'blob' type and subsequently construct a url to that blob using the createObjectURL method. This is the code example in the solution I mentioned above:
var r = new XMLHttpRequest();
r.onload = function() {
myVid.src = URL.createObjectURL(r.response);
myVid.play();
};
if (myVid.canPlayType('video/mp4;codecs="avc1.42E01E, mp4a.40.2"')) {
r.open("GET", "slide.mp4");
}
else {
r.open("GET", "slide.webm");
}
r.responseType = "blob";
r.send();
This works for me in Chrome and Firefox, but not in Safari when using a video hosted on a CDN. This solution does work in Safari if I use a video hosted on the same server. I found this Safari bug, although I'm not sure if the bug is still valid. There's no mention of the Safari bug on the page with the above solution. I've seen another method which essentially pauses the video and waits for it to buffer to 100%, but Chrome doesn't seem to ever fully buffer the video.
I looked into PreloadJS, which apparently supports video preloading, but I couldn't find any working examples. I also looked into html5Preloader, but again I couldn't figure out what to do once the finish event was fired.
I'm not sure if it makes any difference, but I'm using Videogular to play my video, which needs to be fed a video url. I suppose if I use some preloader library such as PreloadJS or html5Preloader, which I'm guessing would in turn use xhr for video, I would need access to a new blob url in my finished handler.
Has anyone come up with a video preloading solution that works in Safari? Thanks in advance.

It turns out the problem was being caused by the content type response header on the videos coming from Amazon S3. They were set to octet-stream, which Chrome and Firefox were able to handle, but Safari threw a media error 4. Changing the content type in the Amazon S3 admin site to 'video/mp4' solved the problem for me.
More info about Safari and octet-stream here in the 'Known issues' tab: http://caniuse.com/#feat=bloburls

Related

Force Buffering in whole video while Paused

I want to make the JWPlayer to buffer whole video while in "paused" state.
I used this according to JWPlayer API Reference:
playerInstance.getState("paused", function() {
playerInstance.getBuffer("100");
});
I also tried:
if (playerInstance.getState("paused")) {
playerInstance.getBuffer("100");
}
and lately:
playerInstance.on("bufferChange", function(callback) {
console.log(callback.buffer);
console.log(playerInstance.getBuffer());
});
This last one works with small mp4 video files, but not with large ones.*And of course, I'm including JQuery library into my code.
They aren't all working! I'm running it on Chrome, and the video files are large, I know about Chrome issues in download large video files, but come on, isn't there any workaround to bypass it?! I'll appreciate the support, thanks.
I'll try to answer this since I cannot comment but having the same desire to force load/buffer the entire video so I can create a simulated highlight reel. From this post it looks like some hacks are needed since Chrome tries to pre-load as little as possible (presumably to save bandwidth usage). Basically use an ajax call to download the file to the browser then play that downloaded file.

Trouble with playing sounds from JavaScript [duplicate]

I'm trying to get sound working on my iPhone game using the Web Audio API. The problem is that this app is entirely client side. I want to store my mp3s in a local folder (and without being user input driven) so I can't use XMLHttpRequest to read the data. I was looking into using FileSystem but Safari doesn't support it.
Is there any alternative?
Edit: Thanks for the below responses. Unfortunately the Audio API is horribly slow for games. I had this working and the latency just makes the user experience unacceptable. To clarify, what I need is sounething like -
var request = new XMLHttpRequest();
request.open('GET', 'file:///./../sounds/beep-1.mp3', true);
request.responseType = 'arraybuffer';
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer = buffer;
}, onError);
}
request.send();
But this gives me the errors -
XMLHttpRequest cannot load file:///sounds/beep-1.mp3. Cross origin requests are only supported for HTTP.
Uncaught Error: NETWORK_ERR: XMLHttpRequest Exception 101
I understand the security risks with reading local files but surely within your own domain should be ok?
I had the same problem and I found this very simple solution.
audio_file.onchange = function(){
var files = this.files;
var file = URL.createObjectURL(files[0]);
audio_player.src = file;
audio_player.play();
};
<input id="audio_file" type="file" accept="audio/*" />
<audio id="audio_player" />
You can test here:
http://jsfiddle.net/Tv8Cm/
Ok, it's taken me two days of prototyping different solutions and I've finally figured out how I can do this without storing my resources on a server. There's a few blogs that detail this but I couldn't find the full solution in one place so I'm adding it here. This may be considered a bit hacky by seasoned programmers but it's the only way I can see this working, so if anyone has a more elegent solution I'd love to hear it.
The solution was to store my sound files as a Base64 encoded string. The sound files are relatively small (less than 30kb) so I'm hoping performance won't be too much of an issue. Note that I put 'xxx' in front of some of the hyperlinks as my n00b status means I can't post more than two links.
Step 1: create Base 64 sound font
First I need to convert my mp3 to a Base64 encoded string and store it as JSON. I found a website that does this conversion for me here - xxxhttp://www.mobilefish.com/services/base64/base64.php
You may need to remove return characters using a text editor but for anyone that needs an example I found some piano tones here - xxxhttps://raw.github.com/mudcube/MIDI.js/master/soundfont/acoustic_grand_piano-mp3.js
Note that in order to work with my example you're need to remove the header part data:audio/mpeg;base64,
Step 2: decode sound font to ArrayBuffer
You could implement this yourself but I found an API that does this perfectly (why re-invent the wheel, right?) - https://github.com/danguer/blog-examples/blob/master/js/base64-binary.js
Resource taken from - here
Step 3: Adding the rest of the code
Fairly straightforward
var cNote = acoustic_grand_piano.C2;
var byteArray = Base64Binary.decodeArrayBuffer(cNote);
var context = new webkitAudioContext();
context.decodeAudioData(byteArray, function(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer;
source.connect(context.destination); // connect the source to the context's destination (the speakers)
source.noteOn(0);
}, function(err) { console.log("err(decodeAudioData): "+err); });
And that's it! I have this working through my desktop version of Chrome and also running on mobile Safari (iOS 6 only of course as Web Audio is not supported in older versions). It takes a couple of seconds to load on mobile Safari (Vs less than 1 second on desktop Chrome) but this might be due to the fact that it spends time downloading the sound fonts. It might also be the fact that iOS prevents any sound playing until a user interaction event has occured. I need to do more work looking at how it performs.
Hope this saves someone else the grief I went through.
Because ios apps are sandboxed, the web view (basically safari wrapped in phonegap) allows you to store your mp3 file locally. I.e, there is no "cross domain" security issue.
This is as of ios6 as previous ios versions didn't support web audio api
Use HTML5 Audio tag for playing audio file in browser.
Ajax request works with http protocol so when you try to get audio file using file://, browser mark this request as cross domain request. Set following code in request header -
header('Access-Control-Allow-Origin: *');

Web Audio API filter not working in Safari

I am in the process of developing an HTML5 canvas interactive piece that uses Createjs and the Web Audio API. I've managed to get audio working in Chrome/Firefox/Safari despite the deprecation of webkitAudioContext by Chrome and FF but not Safari. However, filters for some reason are not working in Safari, but sound still plays. Filters DO work in Chrome/FF.
I have my filters set up like this:
var sound = new Audio();
sound.src = './sounds/sound.mp3';
sound.autoplay = false;
sound.loop = true;
soundSource = context.createMediaElementSource(sound);
var soundFilter = context.createBiquadFilter();
soundFilter.type = "lowpass";
soundFilter.frequency.value = 500;
soundSource.connect(soundFilter);
soundFilter.connect(context.destination);
Am I unknowingly using a deprecated term or something? Live project can be found here. Cheers.
UPDATE: This has been recognised as a genuine bug by the WebKit team, and will be patched. Full details here
Apparently Safari doesn't implement createMediaElementSource correctly. So instead of redirecting the sound through your Web Audio nodes, it still just plays the sound directly to the audio device.
Is there any particular reason why you can't use a BufferSourceNode? It makes you jump through extra hoops to get the sound file and decode it, but it should work.

FF can play mp3, but not using the javascript Audio API

I have this javascript audio player which plays mp3 files. On FF v23.0.1 (Mac) it doesn't work (the reason for this is explained everywhere and here)
What I don't understand is, if I point the URL directly to the mp3 file FF shows its own player and the song plays just fine. But when using the javascript Audio API
var audio = new Audio('/my-song.mp3') ; // --> HTTP “Content-Type” van “audio/mpeg” not supported
audio.autoplay = true ;
it doesn't work. Can someone explain to me why this is ?
Thnx
The error is (note that I've translated it to english): HTTP “Content-Type” of “audio/mpeg” is not supported.
Your Firefox build does not seem to support MP3 yet.
The player that is shown when directly browsing the .mp3 might be just some plugin handling the Content-Type, such as QuickTime, VLC, etc... That won't fly when using that file in an <audio> element, though.
See the "Media formats supported..." article for information on what codecs are supported by what version of Firefox on what platform.

Javascript audio not working in Firefox (x-unknown/unknown)

The following JavaScript running in canvas should play audio fine:
var audio = new Audio('tune.wav');
audio.play();
Most of the time it does work, the wav is 24bit 14100kbps and plays fine on several machines, but on my laptop (Win7, using Firefox 22.0) I get the error:
HTTP "Content-Type" of "x-unknown/unknown" is not supported. Load of media resource file:///C:/code/sound/tune.wav failed.
I'm aware that there are other libraries to play sound, but I want to keep this pure JavaScript and since it works fine on other machines it might be a hardware problem.
But I am able to play other audio files fine, so I'm not sure what's going wrong here. Any ideas?
Hmm. Based upon my experience with the JS Audio elements, you're missing a line.
var audio = new Audio('tune.wav');
audio.load();
audio.play();
I don't think that's causing the error though. Based upon the responses to this question:
Firefox won't play .WAV files using the HTML5 <audio> tag?
and the back-and-forth in this forum: https://bugzilla.mozilla.org/show_bug.cgi?id=524109 (comment 7)
It looks like Firefox simply doesn't support 24-bit WAVE files. 16-bit is probably a safer option.

Categories