Web, Meet the <device> Element (And Orientation Events)

Recently we've been prototyping on Opera Mobile for Android to add support for both the HTML <device> element and the W3C's proposed orientation events specification.

In our first internal build, web developers are able to access, display and interact in real-time with a user's web camera using native HTML features. ...

This information is out of date. For the latest information, please refer here: http://my.opera.com/core/blog/2011/03/23/webcam-orientation-preview

The <device> element

Developers are able to request a real-time video stream of the device's back-facing camera. The resulting camera stream may be displayed in any web page by assigning the device element's data attribute to a HTML <video> element.

The simple example below demonstrates how our implementation of the HTML <device> element can be used to display the web camera in a web page:

<!DOCTYPE html>
<h1>Simple web camera display demo</h1>
<device type="media"/>
<video autoplay></video>
<script type="text/javascript">
var device = document.getElementsByTagName('device')[0],
		video = document.getElementsByTagName('video')[0];
device.addEventListener('change', function() {
	video.src = device.data;
}, true);
</script>

Opera's implementation

Currently, the device element's change event is triggered when the page is loaded or when a dynamic HTML device element is created in script and appended to the document. In the future we will be considering different user experiences to ensure that the user can opt-in and authorize the sharing of their web camera with a web page. In the absence of this user opt-in functionality, we have currently chosen to disable access to any Stream pixel data via a HTML <canvas> element.

In addition to the limitations above, keen observers will note that we have simplified the proposed Stream interface by not implementing its proposed methods and attributes. By doing this we were still able to provide the core functionality of the <device> element without unnecessarily exposing a URI. As demonstrated above, the Stream object itself should instead be assigned directly to a video element's src attribute. When a video element's src parameter has been assigned a Stream object and that attribute is subsequently queried the result is a reserved, though unresolvable, URI of about:streamurl.

While prototyping with <device> we discovered some inherent problems with using a HTML element. Although our initial implementation in this build does not provide any native user interface for the <device> element, the element's design would require native user interface components to be inserted in to a web page in order to allow the user to initiate and grant access to their devices. From experience with form controls, we know that this can be sub-optimal for designers, as it limits their ability to customize the controls. We feel a better approach is to allow authors to create their own user interfaces and provide an API that provides the same functionality. Therefore, we welcome and will continue prototyping on the latest changes introduced in to the WHATWG's HTML draft.

Orientation events

Here's an example of using orientation events to create a simple compass:

<!DOCTYPE html>
<h1>Simple compass demo</h1>
<canvas id="arrow" width="480" height="480"></canvas>
<p id='orient'></p>
<script type="text/javascript">
window.addEventListener('deviceorientation', function(evt) {
	var arrow = document.getElementById('arrow');
	var ctx = arrow.getContext('2d');
	ctx.clearRect(0,0,480,480);

	alpha = -Math.PI *(evt.alpha/180.0);

	var x1 = 240 + Math.round(240.0 * Math.sin(alpha));
	var y1 = 240 - Math.round(240.0 * Math.cos(alpha));
	var x2 = 240 + Math.round(10.0 * Math.sin(alpha - Math.PI/2));
	var y2 = 240 - Math.round(10.0 * Math.cos(alpha - Math.PI/2));
	var x3 = 240 + Math.round(10.0 * Math.sin(alpha + Math.PI/2));
	var y3 = 240 - Math.round(10.0 * Math.cos(alpha + Math.PI/2));

	ctx.beginPath();
	ctx.moveTo(x1,y1);
	ctx.lineTo(x2,y2);
	ctx.lineTo(x3,y3);
	ctx.closePath();
	ctx.fill();

	var orient = document.getElementById('orient');
	orient.innerHTML = "(" + evt.alpha + ", " + evt.beta + ", " +
												 evt.gamma + ")";
}, true);
</script>

Next steps

We're still at the very beginning of the long road to ubiquitous web standards support for accessing the user's web camera and microphone in the browser. In the coming weeks and months we plan to continue developing and releasing updates related to these technologies.

We plan to:

  • Release a public Android build for developers.
  • Add support for other major mobile and desktop platforms.
  • Continue to actively participate in the related standards process to ensure this functionality becomes ubiquitous across the whole web and available in all browsers and web runtimes.
  • Support microphone streams and allow assignment of those streams to
  • Build user interfaces, both on desktop and mobile, that enable the user to explicitly opt-in to web camera sharing and opt-out or modify their web camera sharing once initial authorization has been provided to a web page.
  • Prototype on whether the derived user experiences for authorizing web cam access are better exposed as a JavaScript API or as an HTML <device> element.
  • Actively participate in the W3C RTC-Web Activity to provide webcam and microphone streaming capabilities across the web.
  • Prototype on how we can expose other aspects of the local device (e.g. mounted file systems) to end users in a privacy-secure way.

Our current prototyping demonstrates one well-known method for web camera access although the methods used to access device functionality (and to a lesser extent, orientation events) will change significantly before they are adopted as ubiquitous web standards.

We'll be releasing a build shortly. In the mean time please give us your feedback in the comments below!