How did Scirra get HTML5 audio so perfect in Construct 2? - html

Check out this space shooter demo.
The HTML5 audio is perfect on Chrome 18 and Firefox 10. There is no lag in playing sounds and each sample plays perfectly. The last time I tried to play sounds using HTML5 audio and JavaScript I couldn't get a sound to play more than once.
What sorcery is Scirra doing to make this so perfect?

I'm the developer of Construct 2, so I hope I'm sufficiently qualified to answer your question :)
HTML5 audio is indeed a mess, so I've gone to considerable lengths to try and make it bulletproof in Construct 2. Here's an outline of what I've done:
Use the Web Audio API
HTML5 audio appears designed for streaming music, so a HTML5 Audio object is kind of a heavyweight object. Playing 10 sounds a second with it like Space Blaster does can easily seize up the browser. On the other hand, the Web Audio API is a high-performance audio engine with routing, effects, and lightweight sound playback. It's perfect for games. Audio buffers and audio playback are separated, so you can have one data buffer and efficiently play it many times simultaneously, whereas some browsers are so buggy if you play a HTML5 sound a few times it re-downloads it each time! Since it was actually designed for games and such, you can happily play back tonnes of sound for ages and it will still hum along nicely. It can also use HTML5 audio as a sound source, although I only use HTML5 audio for things the user has designated as music tracks (since that's where you'd prefer to have streaming - typically everything else in the Web Audio API is fully downloaded before playing).
The Web Audio API is supported in Chrome, has also made it in to iOS 6+ (although it's muted until you try to play some audio in a touch event), Firefox are working on support, and it should be coming soon to Chrome for Android. So on these platforms audio will be significantly more reliable.
More info on HTML5Rocks and the proposed spec - you'll have to use the spec as the documentation for now, there's not much else out there.
Other browsers: implement an audio recycling system
The Web Audio API isn't yet supported everywhere, notably IE, which means you still need to crowbar HTML5 audio in to something that might work for games for backwards compatibility. The way to do this is to recycle audio objects.
The player's laser in Space Blaster fires 10 times a second - and that's not including any other sound effects! As I mentioned earlier, Audio is kind of a heavyweight object, so if you're doing new Audio() 10+ times a second, lo and behold, the browser eventually dies and audio starts glitching up. However, you can drastically reduce the number of Audio objects created by recycling them.
Basically, for each sound effect, keep a cache of every Audio object you've created with that sound as a source. Then, when playing a new sound, search the cache for any sound effects which have finished playing (the ended property will be true). If you find one, rewind it back to the beginning (currentTime = 0) and play() again. Otherwise, create a new Audio() object in the cache.
Since the player's laser sound effect is short, instead of creating 600 Audio objects a minute, there will just be 3 or 4 that it keeps cycling round. Some browsers unfortunately will still download it 4 times (Safari did this last I checked!) or have high latency the first time each sound buffer is played, but eventually the browser catches up since the same buffers are always being reused. So basically sound might be a bit weird for a few moments, then it clears up. We also use the HTML5 app cache so next time you play everything loads from disk, so subsequent plays should perform well immediately.
That's basically it. It's still a little dodgy on the first play with HTML5 audio, but every time after that should be fairly solid providing the browser has a sane audio implementation. There are a number of ways to try to clone Audio objects, but I've found that rewinding existing Audios works best.
There's no SoundManager or any Flash/plugin-based fallbacks at all since we make a point of being pure HTML5.
We also support audio APIs provided by PhoneGap and appMobi for mobile, since HTML5 audio on mobile isn't even worth trying. That makes a total of four audio APIs our audio engine wraps, and yes, it does look like a frankenstein mess, but it works.
That's it. I suppose our competitors will read this, but who cares when there's SO rep to be had???!!!1111

Related

Determining current rendition for HTML5 HLS streams

I've got an HTML5 <video> element whose source is a .m3u8 (HLS stream)
I have an M3U8 with three different renditions: 640x360, 960x540, and 1280x720
On Desktops I have a Flash Player for playing the video, so the HTML5 fallback is only intended for mobile (iOS and Android) - I am doing all of my testing on an iPad and, once it's working, I will try it out on Android and hope everything works the same.
My goal is to, at any point in time, figure out what rendition the video element is playing. The rendition is subject to change as the user's bandwidth changes.
I tried using the .videoHeight property, but it always returns 480 regardless of the rendition being downloaded - which is particularly odd because 480 isn't even an option.
Does anyone know how I can figure out the rendition being downloaded?
Cleaning up some old questions that never received answers:
Unfortunately this one is just not possible. The HTMl5 video spec and HTML5 video implementations in most browsers are intended to abstract away all of the underlying magic involved in playing videos. You give it a source, it plays. Everything else is completely hidden and you have no access. No access to metadata channels, no access to audio channels, no access to bitrate and resolution information,...
At best I developed a solution to guess which resolution was playing. Every 10 seconds a 1 MB file was loaded over AJAX. I measured the speed at which this downloaded to guess at their current bandwidth. I know that QuickTime will only play a rendition if you have double the required bandwidth. So if the 960x540 rendition requires 1400 kbit/s then it won't play unless you have 2800 kbit/s bandwidth.
It's not very good (and wastes 6 MB of bandwidth per minute) but it's better than nothing.

HTML5 buffer video one by one and play seamlessly

On iOS, and I think Safari, we have Apples HTTP Live streaming, which can take a playlist of video files in a certain format, buffer them one by one, and play them seamlessly back to back.
Is there any way to achieve this in other browsers? I can of course detect the video finishing, and then start buffering and playing the next one, but I want to remove the buffering by downloading subsequent videos as each earlier video finishes. I do not want to hack this by stacking up video elements and switching between them. There are various serious consequences to this method.
Perhaps if there is a way to use javascript to download the files into in-memory buffers and somehow point the video element to play from these buffers?
I've seen swapping in video elements for each segment tried, and it's never smooth.
There is an HTML spec in the works that defines exactly the process you're describing, concatenating media segments into a buffer that can be fed into a media element.
http://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html
This isn't available in browsers today but is working its way into Chrome/Safari. Even when it is, it will take a good amount of work to implement this process.
Your best bet if you need it now would be to use a Flash player that can handle HLS, like OSMF, JWplayer, and soon Video.js.
In html5, you can preload videos, preload the meta information, or not preload at all. The only problem, of course, will be with Internet Explorer which will download everything or nothing at all (and not even show the controls).
This is all controllable with javascript, too. If you want to play them back-to-back automatically, though, this would need to be done with javascript or some third-party tool. Reading where the file is playing is accessible through the API.

Web Audio API: seek, play-/buffer-progress

When you play audio using the audio element in Chrome you get annoying clicks and cracks. At least under my 64bit Linux installation, even after I formatted and installed a new Fedora version. (Firefox and Opera are fine, even IE9 in a VirtualBox Windows 7.)
But demos using the Web Audio API instead of the audio element have perfect sound. So I was wondering if I could use the Web Audio API like the audio element? But there are some things you seem not to be able to do with this API. Or am I missing something? The things I couldn't find where:
starting to play a file before it is completely loaded
getting buffer progress updates (depends on the previous point)
getting play progress updates
seeking
Is there a way to do this with the Web Audio API?
This is where I would use it: http://tinyurl.com/magnatune-player
I think you should still use <audio> for streaming at the very least. You can treat it as a MediaElementAudioSourceNode in web audio if you'd like:
var mediaSourceNode = context.createMediaElementSource(audioElement);
AFAIK, there is no way to stream web audio directly. In fact, the web audio api suggests that you don't:
4.9. The AudioBuffer Interface
This interface represents a memory-resident audio asset (for one-shot sounds and other short audio clips). Its format is non-interleaved IEEE 32-bit linear PCM with a nominal range of -1 -> +1. It can contain one or more channels. Typically, it would be expected that the length of the PCM data would be fairly short (usually somewhat less than a minute). For longer sounds, such as music soundtracks, streaming should be used with the audio element and MediaElementAudioSourceNode.
Unless you used a MediaElementAudioSourceNode (which I would assume suffer from the same issues you're having since it's just using an <audio> tag) AFAIK the answers to your questions are:
starting to play a file before it is completely loaded: No.
getting buffer progress updates (depends on the previous point): Possibly (You could check for progress events on the XHR)
getting play progress updates: No.
seeking: No.
In the meantime Chrome fixed the audio playback issues. So I don't need any workarounds anymore.

Does HTML5 support HTTP Psuedostreaming of video?

Can I click on some time and eventhough the video is not downlaoded till that time and the video starts playing from the time I clicked?
If yes, what would be a better option for viewing streamed video- HTML5 or flash player like JW player? WHich one will have less lag?
HTML5 browsers generally don't support this, however I believe the video tag in Safari will work with the Apple HTTP Streaming format for this functionality. For something that works across all browsers, Flash Player can do it using either RTMP streaming or HTTP Streaming (either with our without OSMF to support this). Probably the easiest place to start is with OSMF, which supports both RTMP and HTTP streaming of video.
I have tested this with Firefox and Firebug and while you can "seek" to a point in the video without having to watch video preceding the point you wish to seek, this still causes the entire video file to download.
Indeed, each time you seek in Firefox 4, the entire video downloads.
This may change and improve as HTML 5 video implementations become more mature and may differ based on the actual browser being used.
More information on the test here:
http://www.stevefenton.co.uk/Content/Blog/Date/201106/Blog/HTML-5-Video-In-Real-Life/

do html5 audio tags eat up resources

I have pages where i need to play dozens of small audio file when the user clicks on things. Responsiveness is very important.
I'm thinking of using one for each file, and preloading the audio files. Is this the a reasonible approach?
Thanks.
What I experience using SoundManager2 (audio Javascript lib) is that Chrome nor Firefox have no issues loading and playing multiple (100+) sounds through their Html5 capabilities
(Firefox must play OGG though)
With IE9 it's a different story. Looks like it has a limit to load and play no more than 40 sounds. :-(
As, the game we develop requires constantly to have 50+ sounds played within 1 minute period, we have to fallback to Flash for playing sounds on IE9.. luckily SM2 does it too
I also confirm this behaviour with html5 mode using jPlayer. I'm only able to create 40 instances of jPlayer. Each can preload and play sound that it defines.
41st and following instances will fail with an error on IE9/Windows7
Error: "Media URL could not be loaded"
It's reasonable, and probably the correct solution. I recently wrote a demo application (http://www.soundscribe.com) that makes heavy use of individual (and simultaneous) audio clips in HTML5. IE9 and FF3/4 handle it well. Chrome has some issues that seem to be specifically related to simultaneous playback (which probably won't apply to your app). The biggest block I hit was in IE9, which seems to have a mysterious limit on the number of audio objects that can exist at once. The max is about 40, after which IE9 will silently fail to download the file. FF and Chrome both try to support an unlimited number.
The alternative approach of putting all the audio in a single file and changing the offset to play is a bad choice for several reasons. It's much more complicated to code, you need to keep up with additional metadata (where does the clip start, how long is it), and it's likely to work slightly different between browsers. And the worst part, there's really no way to know when your clip is fully loaded. You can only tell when the clip "can play through", which is determined by the browser based on the size of the audio file and the current download rate. This means that even after the browser reports the audio clip is ready, you may not be able to play a clip somewhere near the end.
It seems like a reasonable approach. However you need to consider a couple of things.
Each sound clip will need to be held in memory. While this is will not matter for most cases, users with a lot of tabs open, multiple programs open or old computers may get slow down on their computer. Especially if the sound files are large.
From a usability point of view, if I hear a sound every time a click a button on the site, I'll leave immediately