I am mostly disappointed by the headline which I hope is there for link-baiting and Google juice. In other words, really cheap and lame propaganda.
The post has a good intention: there is a problem with open media standards in HTML5 that there is no way to protect premium content from being downloaded. There is no DRM, there is no encryption or watermarking. If we want premium content publishers on the bandwagon, then we need to think about that. Posts like this with this headline make it hard for us to even reach people to talk about the options. It is FUD and Adobe as a company that claims to support HTML5 should know better.
Right now, I do tell people who are paranoid about their content to use Flash as it has a certain degree of protection against simple downloading. If Adobe’s official spokespeople keep spouting messages like this, I will move to tell them to use Silverlight.
The argument that it is easy to download video in HTML5 as you can see it in the source is like saying that it is easy to steal newspapers in train stations as they are easy to reach. It is invalid – that you can steal it is not the issue here, the issue is what you do with the paper. Do you take it from the stand and go and pay it without looking at it? Do you read it on the spot and then put it back? Do you leave with it without paying? Or do you check the headlines and when you are intrigued you go and pay for it? Do you take the paper, go to a copier, copy it and then try to sell the copies? Fact is – it is dead easy to get the paper, the same way it is dead easy to get a video online.
I find myself many a time downloading YouTube videos as I am on the go a lot. Being on the go (and considering data plans and roaming) means I have no connection, or I have a flaky connection that downloads the movie to minute 3 and then stalls while the fan of my laptop spins. Instead, at home when I got my fat connection I download some talks and screencasts and watch them offline using VLC. Then I delete them – or I blog about them first linking to YouTube and advertise them that way.
Allowing people to download a movie means you get a bigger audience. If you make people jump through hoops to watch a movie or make them watch a 5 minute ad for a 10 second film you shouldn’t be surprised if they use P2P filesharing or Hotfile, Rapidshare, Fileserve, Megaupload and dozens of other services to download the movie in 10 seconds and then watch it at their leisure.
Recognise something? The mere fact that there are thousands of downloaders for YouTube and paid for hosting services that offer easy to download pirated copies means that there is a demand for that feature. A feature that would make me damn happy to have on YouTube and I would pay for it.
So instead of demonising HTML5 as the backdoor that will allow evil doers to steal your goodies maybe it is time for premium content providers to open up to the needs of web users, and find a way to publish previews of content and the full content for subscribed users. There are ways to make money and share your products – but not if you spend most of your time and money on things that seemingly give you protection but in reality are just a glass shield.
Yesterday evening I went to Holborn in London to attend the London Web Standards Pick’n’Mix event.
The place (a room under a bar with an own bar – win!) was packed and actually amazingly warm. The sound was good (except for the handheld mic which turned Jim O’Donnell’s announcements into Jungle remixes) and people were eager to hear about cool new stuff.
One thing I really liked was that instead of the normal thanking of the sponsors the organisers also listed job offers before the first talk – pretty clever way to advertise your job. If you need a London web geek, contact them!
Peter was the first to take the stage with a 5 minute lighting talk about CSS layout models. He had written an article with the same title on CSS3.info in 2006 and covered what had improved since then (not much, really). His slides are available on Slideshare.
Peter did a good job (considering also that this was his first public presentation) on covering the basics of CSS layouts. What we use now, like Floats, Absolute positioning or JavaScript (Masonry.js) and what is there to come:
Peter rightfully claimed that layout is now the new challenge for CSS and browser vendors to tackle.
How to write jQueryJavaScript that doesn’t suck – Ross Bruniges
Ross is a regular in the UK scene and and overall great guy. One of those loud, drinking but also silent types that doesn’t get the credit he deserves for helping web standards rock the city. He has a special way about him which also showed in the fact that he gave out mini pork pie as prizes for questions! Ross gave a great reminder talk covering best practices in JavaScript development if you want your code to work and be taken over by other developers without calling you names. The slides and links are available on his posterous.
The first point was to organise your stuff as you you will hand over to other developers.
JSLint was next on his list, first and foremost as it helps you find simple problems with your code, like:
semicolon insertion which can lead to wrongly returned values (yes, { should not be on a new line in JS, sorry)
Double equals instead of triple equals – you should check type and value
Personally I use the JSTools Textmate Bundle which lints my JS when I save it – very simple reminder to do the right thing.
Ross then explained that long chains in JQuery are tempting but also hard to read and debug. One trick to use is to split the chain at the full stop and insert a newline and tab in front of it.
YAGNI - you ain’t gonna need it – was next and on the back of this the reminder to create smaller, aptly named functions that do one task well instead of all-encompassing monster methods. This can also be achieved by looking at your functions once you are done, detect duplicate tasks and move them out into an own helper method.
Custom events were the next great tip and I can only agree that there is nothing better for separating your functionality from your source and allowing other developers to extend your widgets.
Then we moved on to performance and that there is nothing worse than optimising prematurely and forgetting about old browsers when you think about performance testing.
For starters it is very important to write good selectors in jQuery as the sizzle engine parses your strings from right to left. This means that $('#foo div') makes IE read all DIV elements, loops through them and checks which ones have a parent with the ID foo instead of doing a getElementById and then a getElementsByTagName to achieve the same.
In the same vein it is important to cache results in variables to avoid IE doing this over and over again and to return false when elements can’t be found as jQuery is very adamant in trying to find them.
Event Delegation was the next big thing on the menu and again I can’t agree more – it is very elegant and makes your JS independent of HTML changes. It is much less expensive having one event listener than using each() to apply lots of them throughout the document. One gotcha Ross mentioned is that jQuery’s live() always goes all the way up to the document leverl whilst delegate() allows you to define a scope like “only in this DIV”. There’s a good overview at Brandon Aaron’s blog.
Reflow and repainting issues were next on the performance menu, which in essence means that you shouldn’t touch the DOM too much and instead create long HTML strings and inject them into hidden elements before showing them.
Accessibility was another topic, which started with Ross reminding us that CSS styles for hover should also get focus and blur styles and that instead of using hover you should use .bind(mouseenter focus) and mouseleave blur in jQuery.
The next thing was not to forget the edge cases as things will go wrong when they can go wrong. This means using $.ajax() instead of $.getJSON() as it allows you to define timeouts and error cases (and doesn’t break caches because of callback parameters).
Ross’ last points were about sending HTML5 to IE and bewaring of HTML5shiv as it means you do the job CSS should do with JavaScript. Instead it might make more sense to use a DIV with a class around each new semantic element.
All in all Ross did a great job and I hope he inspired some of you to dig deeper (hence also my notes and more links here).
With the last talk of the day just before the merriment of beverages and conversation, Kornel changed the pace a bit and also shifted the focus from front-end technologies to the server and even further into the infrastructure of the web itself.
He talked in detail about:
MIME type issues when serving files on the web
How sending headers on the servers makes a lot more sense than using a META tag
How to properly force a download of a file using Content-Disposition: attachment
Bugs in IE - especially around caching and filename attributes
How faking MIME types seems to be a quick solution but will bite us further down the line
html vs application/xhtml+xml
I am not quite sure of the percentage of people in the audience understanding what was going on but I for one was very impressed with the research and the cool no-nonsense presentation style. Bad encoding of files on the web is a big issue and can make or break your web site as in the end you want to show users files in the way they were intended to be shown.
Summary
All in all it was a great evening and I am looking forward to the next meeting of this group. My advice would be to change the structure a bit to one big talk and several lightning talks to give more people the chance to show what they are doing. This is a great meetup to get your first experiences in speaking and the audience is knowledgable and sympathetic.
Posted in General | Comments Off on That was the London Web Standards “Pick’n’Mix” meetup
Some time ago I posted about a demo to zoom and rotate video with HTML5 and CSS3. Now I wrote up a detailed blog post on Mozilla about the techniques to rotate and zoom video. The final outcome is this player:
I am currently in Boston and went to MIT to give a guest lecture on HTML5 multimedia as part of a lecture series by Mozilla leading up to a game competition. Here are the slides and some notes on what I talked about.
It is sometimes a good idea to think back about what we did before we continue to move on. That gives us a chance to avoid repeating mistakes and to remember solutions to issues we face once more.
In the beginning, we had images as the only multimedia elements in browsers. As the connection speeds were bad we had to be very careful in what formats to use:
JPEG images have millions of colours but are lossy when you make them smaller in file size. You can see those “artifacts” when people save text screenshots as JPEG - the text looks fuzzy and is hard to read.
GIF images had a fixed number of 256 colours, had transparent pixels and could be animated images. Saving photos as GIF resulted in dithering to simulate more colours and larger files.
PNG was the first open format and a good middle ground – no animation though and IE doesn’t get the transparency right
WBMP was a special 2 colour format for mobile devices in WML pages
As the connection speeds were bad we came up with some very clever image formats and browser attributes:
Progressive JPG shows a highly artifacted and small (in filesize) version of the image first and increases its quality during download
Interlaced GIF loaded the GIF line by line – first lines 1, 3, 5, 7 and so and then 2, 4, 6 and so on – that way you saw what the image was about whilst it was loading
Netscape had a lowsrc attribute that allowed you to define a smaller image to show first which gradually got covered up by the full fat image
We animated with GIFs and later on with JavaScript animations – the latter giving us control over the animation but also requiring JS, which was not commonly used or turned on.
Audio on web sites was mostly MIDI background sounds – and let’s thank our lucky stars that this is over.
Next we used Java Applets for high fidelity animations and they gave a lot of web sites the charm of things found in the bargain bin at Hallmark.
Then RealPlayer came around. Now not on the “to have” list of anyone any more RealPlayer was awesome for its time: SMIL support, great streaming ability, supported by all platforms and very good compression. A shame that both the player and the encoders were closed and you had to pay for everything.
Other players that allowed video embedding were Quicktime, Windows Media Player, Shockwave and even Adobe Acrobat had some image conversion options. Other plugins like iPix allowed for zooming into images and VRML was the idea of having 3D worlds inside the browser.
All of them had the same problems though – they were plugins and thus alien to the browser. You needed to constantly upgrade them, they made the browser less stable and there was no interaction with the rest of the page.
Another issue is security – a lot of security exploits of browsers actually work by attacking plugins as they have deeper access into the operating systems than JavaScript itself.
After a while, Flash came out as the main plugin people would use for multimedia on the web. It came with great abilities, a good set of editors and libraries and allowed you to show and – more importantly – protect your videos from being downloaded. Right now DRM will be one of the the main reasons to use Flash movies instead of going native with HTML5.
Annoyances with Flash
The first thing I found lately with Flash is bad performance. On my MacBook air watching a few YouTube videos triggers the fan of the processor – something HTML5 Video doesn’t do. The reason is that Flash is a one size fits all solution for audio, video, animation and lately also 3D animation.
Whilst Air and Flex allows you to build movies with external editors, you mostly still use Flash builder to create your files instead of the editor you use to build the rest of the page.
No matter how cool Flash is, it is still an alien, black box in the browser and not available to manipulate from the outside. This means first of all bad accessibility:
You can’t reach Flash videos with your keyboard on browsers othe than IE - regardless of keyboard controls inside the video
Keyboard access in the movies needs to be added by the developers.
Whilst audio and video can be powerful tools to aid people with learning difficulties it is tough to make them available to them because of the two points above
The way to make Flash talk to the rest of the page is to provide APIs to your Flash controls. YouTube for example has an API that allows you to write your own player controls that are keyboard accessible. I’ve used this API in the past to build Easy YouTube. Some things I could not do though – like providing subtitles and captions in an accessible manner.
HTML5 audio and video
And this is where HTML5 comes to the rescue – it comes with native audio and video elements that are not in a black box but part of the browser and as accessible for you to manipulate like a block of text, an element or an image is. There are many upsides to native multimedia controls:
Better accessibility
Better performance – the elements do one thing well rather than being a catch-all solution
Much simpler API
Allows for styling and overlays – covering Flash movies with other elements in Internet Explorer was always a pain
View-source “hackable” – changes can be done in plain HTML rather than needing changes in another editor and compilation
Take Oprah’s new web site for example – hovering over any of the big pictures reveals a video. This is HTML5 video and thus easy to maintain in a CMS without the whole page being a Flash movie. It is also much higher quality and smaller file size than animated GIFs.
Painful stuff – codecs and conversion
Of course not all is sunshine, bunnies and daisies in HTML5 video and audio land and the reason is copyright and intellectual property. An open system using closed video and audio encodings cannot work. Video and audio gets converted to smaller, stream-able formats before it goes on the web. There is no such things as an “AVI file” or “MOV file” – these are container formats with audio and video streams all using different codecs to make them small. The issue is that these systems are all copyrighted and you need to pay money to create files in these formats. Which is why we needed open formats for HTML5.
We now have H.264 or MP4 files that are open but we might need to pay for them later, we have Ogg Theora files that are open and Google released VP8 or WebM to have a new, high quality and small filesize format for the web. Our job now is to convert proprietary format videos as created by our digital cameras into these open formats. There are a lot of tools for that:
Audacity is a full-fledged audio editor that allows you to save OGG audio files.
WebM tools allow you to create files in WebM format.
ffmpeg is a command line tool that most of the above solutions use in one way or another.
A very simple way to convert a video to all the necessary formats is to host it on Archive.org. If your video is licensed with Creative Commons archive.org does not only offer you full-length hosting (YouTube only allows 15-30 minutes) but also converts the video to OGG and MP4 automatically for you.
Embedding
Embedding HTML5 video into your document is incredibly easy:
Anything inside the audio or video that will be displayed when the browser doesn’t support them – in this case a not very helpful message but an important one. Normally you’d use this to offer a link to download the audio or video file or a Flash fallback (if you really must).
Right now, that doesn’t do anything though. If you want to display a video that the user can control (jumping to another time, changing the volume, playing our pausing the video) all you need to do is add a controls attribute:
With that you have a video that can be controlled via mouse or keyboard – it is that easy. The controls look different from browser to browser and some have features others don’t. Safari for example is the only browser that allows the video to be full screen. Other browser makers decided against that option to prevent people from using video for phishing purposes.
In order to support all the capable browsers you need to offer the video in at least two formats:
Use MP4 as the first format to ensure that iOS devices play it. Make sure to add a type attribute to each source as otherwise browsers will load a small part of each file to determine the type.
Additionally you can use the media attribute to serve different quality movies to different devices. The following example sends a high quality video to devices that are wider than 800 pixels and a lesser quality version to others (when using MP4):
Other attributes you can use in the video and audio tag are:
poster – define a picture to show before loading.
height/width – dimensions of the video
loop – automatically restart the video or audio
preload (auto/none/metadata) – when set to auto the browser preloads the video/audio when it is possible (most mobile browsers will not to save bandwidth, though). When set to metadata only the necessary data gets loaded to show the length of the media and set the right dimensions
Controlling
As there are differences in the controls across browsers you might want to create your own player controls. This is pretty easy. You have a few methods to use:
load() – load a new media.
canPlayType(type) – returns probably, maybe and “” (really!)
play() – play the movie
pause() – pause the movie.
addTrack(label,kind,language) -for subtitles
You also have a few properties to control and read the state of different parts of the video/audio file:
Video details
width
height
videoWidth
videoHeight
poster
Controls
controls
volume
muted
Tracks
tracks
Network state
src
currentSrc
networkState
preload
buffered
Ready state
readyState
seeking
Playback state
currentTime
startTime
duration
paused
defaultPlayBackRate
playbackRate
played
seekable
ended
autoplay
loop
This is a lot to play with. For example to create a simple play button for an audio file you might have a button element in the page with the class button. To make it functional all you need to do is this:
var audio = document.getElementsByTagName(‘audio’)[0];
var play = document.getElementsByClassName(‘play’)[0];
play.addEventListener(‘click’,function(e){
var t = e.target;
if(audio.paused){
audio.play();
t.innerHTML = ‘pause’;
} else {
audio.pause();
t.innerHTML = ‘play’;
}
e.preventDefault();
});
You check if audio.paused is true and call play() when it is, otherwise you call pause(). Change the innerHTML of the button at the same time and you are doen.
However, simply checking the state of an object is not safe. It makes much more sense to actually listen to events fired by the audio/video object. And there are a lot of interesting events to listen to:
loadstart
progress
suspend
abort
error
emptied
stalled
play
pause
loadedmetadata
loadeddate
waiting
playing
canplay
canplaythrough
seeking
seeked
timeupdate
ended
ratechange
Using these events, the player button code changes slightly:
video.addEventListener(‘play’, playEvent, false);
video.addEventListener(‘pause’, pausedEvent, false);
video.addEventListener(‘ended’, function () {
this.pause();
}, false);
function playEvent() {
play.innerHTML = ‘pause’;
}
function pausedEvent() {
play.innerHTML = ‘play’;
}
play.onclick = function () {
if (video.ended) { video.currentTime = 0; }
if (video.paused){
video.play();
}else{
video.pause();
}
};
No magic there.
If you want to see all the events and properties in action (and more importantly see if a browser supports them or not) check out the Media events demo page at the W3C web site.
One very good trick for syncing video and other effects is using the currentTime property. One example of that is the Spirit of Indiana demo where we sync a Google Maps animation with a video. The main gotcha is that the timeupdate event fires a lot and not necessarily every second. Therefore you need to throttle the changes to full seconds by using parseInt(). You can see this in action at the video demo:
window.addEventListener(‘load’,
function() {
var stage = document.getElementById(‘stage’);
var log = document.getElementById(‘logger’);
var seqlog = document.getElementById(‘loggersequences’);
var v = document.getElementsByTagName(‘video’)[0];
but = document.createElement(‘button’);
but.innerHTML = ‘Click to see Lindbergh’s flight’;
stage.appendChild(but);
but.addEventListener(‘click’,function(e) {
v.play();
e.preventDefault();
},false);
var now = 0;
v.addEventListener(‘timeupdate’,function(o){
log.innerHTML = v.currentTime;
var full = parseInt(v.currentTime);
if(full >= now) {
seqlog.innerHTML = now;
now = now + 1;
}
},false);
},
false);
Transforming
The real power of HTML5 and native video is when you can see how easy it is to transform the video element in the page. Here are some demos:
Transforming Video shows how simple it is to create a player that allows you to zoom inside a video and rotate it using CSS transformations
Paul Rouget’s round video demo shows how to create a play/pause button in SVG, greyscale a video and rotate it using CSS transformations
Paul’s Video Mashup demo shows how to apply SVG filters like Gaussian Blur, masking and how to apply CSS transforms to a running video
Simply check the source codes on these demos to see how they are done – the power of an open web.
Realtime changes
Adding filters and transforming the video container with CSS is one thing. Using Canvas and copying frames from the video into it you can do realtime changes to the video itself, which is really nice.
Paul Rouget’s Green demo shows how to simulate a green screen effect with open web technologies. You copy each frame over to a canvas and read out the RGB value of each pixel. When it is green, just set its opacity to allow the picture behind the video to shine through.
The dynamic content injection by Paul shows how to analyse a video and find white parts to use as corner points for an embedded canvas. You can then inject other videos, canvas animations or images into the other video.
The Tracker demo shows how to detect human shapes and movement in a video
The edge detection demo shows how to detect edges in a live video using JavaScript
Awesome audio stuff
As you can see there is a lot of cool realtime things you can do with video. Audio is less sexy somehow as you can play and maybe play backwards (only works in Safari at the moment). Wouldn’t it be cool to read out the audio data or dynamically generate sounds though?
One cool demo using this API is the HTML5 Guitar Tab generator and there is already a library out there called sfxr that allows you to create audio on the fly.