Tento článek je překladem tutoriálu getUserMedia #1 – Camera Access z webu Web Apprentice a jeho autorem je Rob Jones. Překlad je zde uveden s laskavým svolením autora.
Úvod
HTML5 obsahuje důležitou a zajímavou novinku, pomocí které může prohlížeč přistupovat k mikrofonu a webkameře na vašem zařízení – navigator.getUserMedia
.
Metoda getUserMedia není zatím implementována ve všech prohlížečích, ovšem to se brzy zlepší…
V prosinci 2013, kdy vznikl tento text, byl getUserMedia podporován jen v prohlížečích Google Chrome a Mozilla Firefox. Aktuální podporu najdete na caniuse.com.
Pro tuhle novinku najdeme jistě hromadu využití – od zábavných, jako je získání vaší podobizny a aplikování rozličných filtrů, až po záznam řeči a video konference.
Tento tutoriál vám předvede, jak pomocí getUserMedia
přistupovat ke kameře a jak z ní získat fotografický snímek.
Naše demo obsahuje dvě okna – živé video nahoře a z něj sejmutou fotografii dole.
Krok za krokem
1: Zprvu uvidíte v našem demu dva prázdné obdélníky a tři tlačítka.
2: Když kliknete na Start Video, tak se vás prohlížeč zeptá, zda povolíte stránce přístup ke kameře. V Google Chrome se objeví panel podobný tomu na obrázku s tlačítky Deny a Allow napravo.
V Mozilla Firefoxu se zobrazí následující dialog. Kliknutím na Share Selected Device povolíte přístup.
3: Za okamžik se vám zobrazí živé video z vaší webkamery v horním okně. Obě okna se přízpůsobí na šířku definovanou ve skriptu.
4: Klikněte na Capture Photo, kdykoliv budete chtít z videa sejmout fotografický snímek.
5: Stop Video zastaví video a vypne kameru. Můžete kameru opět spustit a zase ji zastavit, kolikrát budete chtít.
Co se děje v kódu
Náš kód má tři části – HTML značku video, které je zprvu prázdné, tři tlačítka a canvas element, zprvu také prázdný.
<video id="video"></video>
<div id="controls">
<button id="start_button">Start Video</button>
<button id="stop_button">Stop Video</button>
<button id="capture_button">Capture Photo</button>
</div>
<canvas id="canvas"></canvas>
Style blok zajistí vycentrování prvků na stránce a vykreslení okrajů kolem nich, abychom je viděli i na začátku, když jsou ještě prázdné.
Náš skript pro zjednodušení používá jQuery, které musíme načíst, než se začne vykonávat náš skript.
Protože metoda getUserMedia není zatím plně podporována, připojují k ní výrobci prohlížečů vendor prefix webkit, moz atd. Hack na začátku našeho skriptu mu umožní, aby fungoval v různých prohlížečích.
navigator.getUserMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
Náš skript si nadefinuje několik globálních proměnných, které v něm budeme používat, a pak definuje funkci ready, která se spustí po nahrání stránky.
Dále skript definuje obslužné funkce pro naše tři tlačítka. Callback pro Start Video tlačítko zavolá navigator.getUserMedia
a zapne webkameru.
Metoda navigator.getUserMedia
přijímá tři argumenty. Prvním je hash, který v našem případě určuje, že chceme přistupovat k videu, ale nikoliv ke zvuku. Tím druhým je funkce, která bude zavolána, když getUserMedia
získá přístup ke kameře. Je zavolána s argumentem stream, který reprezentuje vstup z kamery. Tato funkce propojí stream
se src
vlastností objektu video
. Toto propojení je pro Firefox a Chrome trochu odlišné. Ve Firefoxu se připojuje na vlastnost mozSrcObject
, v Chrome na vlastnost src
. Volání url.createObjectURL(stream)
obslouží případ, kdy je stream javascriptovým blobem – datovou strukturou, kterou se nebudu pro zjednodušení v tomto tutoriálu zabývat.
Dále je stream
pro další použití zkopírován do globální proměnné mediaStream
. A konečně video.play()
spustí zobrazování video vstupu na stránce v našem prvku <video>
.
Třetím argumentem metody navigator.getUserMedia
je funkce, která je zavolána, pokud nastane problém v připojování videostreamu. Celé volání tedy vypadá následovně:
navigator.getUserMedia(
{
video: true,
audio: false
},
function(stream) {
if (navigator.mozGetUserMedia) {
video.mozSrcObject = stream;
} else {
var url = window.URL || window.webkitURL;
video.src = url ? url.createObjectURL(stream) : stream;
}
mediaStream = stream;
video.play();
},
function(error) {
console.log("ERROR: " + error);
}
);
Protože se rozměry videa mohou od zařízení k zařízení lišit a protože chceme mít rozměry našeho okna pod kontrolou, musíme nastavit velikost našim prvkům video
a canvas
. Ovšem k těmto rozměrům získáme přístup až po připojení našeho zdroje videa…
Nastavení provedeme v obslužné funkci události prvku video
takto: $("video").on('canplay', function(e) { ...}.
Událost canplay
je vyvolána, když je video nahrané a může být spuštěno. Když k tomu dojde poprvé, načteme vlastnosti videoHeight
a videoWidth
zdroje a použijeme je pro určení rozměrů našeho výstupního okna.
Ve Firefoxu bylo nutné nastavit velikost canvasu již v obslužné funkci pro tlačítko Capture – netuším proč.
V tuto chvíli by již mělo video běžet a zobrazovat se v našem prvku video
a měli byste vidět indikátor na panelu prohlížeče a také na vaší kameře, které oznamují, že kamera běží.
Video by běželo tak dlouho, dokud zůstane stránka v prohlížeči otevřená. To je dle mě příliš obtěžující, proto vždy přidávám možnost video zastavit. Callback tlačítka Stop jednoduše zavolá metodu stop
objektu mediaStream
, který jsme si vytvořili dříve. Video bude zastaveno, ale jeho poslední snímek zůstane zobrazen.
Třetí tlačítko nám umožňuje sejmout aktuální snímek videa. Používá k tomu metodu drawImage
, která je součástí canvas API, a umí získávat data z různých zdrojů, včetně prvku video
. Jednoduše tuto funkci zavoláme spolu s rozměry canvasu a ona již zajistí získání snímku – šikovné a jednoduché.
Ještě si ukážeme náš celý kód pohromadě:
<video id="video"></video>
<br>
<div id="controls">
<button id="start_button">Start Video</button>
<button id="stop_button">Stop Video</button>
<button id="capture_button">Capture Photo</button>
</div>
<br>
<canvas id="canvas"></canvas>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<style>
button {
font-size: 16pt;
}
#controls {
margin-left: auto;
margin-right: auto;
display: block;
text-align: center;
}
#canvas {
margin-left: auto;
margin-right: auto;
display: block;
background-color: #eee;
border: 1px solid black;
}
#video {
margin-left: auto;
margin-right: auto;
display: block;
border: 1px solid black;
}
</style>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<script>
// Hack pro obsloužení vendor prefixů
navigator.getUserMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
var video = document.querySelector('video');
var canvas = document.querySelector('canvas');
var ctx;
var width = 480;
var height = 0;
var mediaStream;
var streaming;
$(document).ready(function() {
if(!navigator.getUserMedia) {
alert("Pardon - váš prohlížež nepodporuje getUserMedia - zkuste Chrome nebo Firefox");
}
ctx = canvas.getContext("2d");
// obsluha tlačítka pro Start videa
$("body").on('click', "#start_button",function(e) {
e.preventDefault();
navigator.getUserMedia(
{
video: true,
audio: false
},
function(stream) {
if (navigator.mozGetUserMedia) {
video.mozSrcObject = stream;
} else {
var url = window.URL || window.webkitURL;
video.src = url ? url.createObjectURL(stream) : stream;
}
mediaStream = stream;
video.play();
},
function(error) {
console.log("ERROR: " + error);
}
);
});
// obsluha tlačítka Stop
$("body").on('click', "#stop_button", function(e) {
e.preventDefault();
mediaStream.stop();
});
// obsluha Image Capture tlačítka
$("body").on('click', "#capture_button", function(e) {
e.preventDefault();
// ?? Kvůli Firefoxu jsem musel přidat resize canvasu
height = video.videoHeight / (video.videoWidth / width);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
ctx.drawImage(video, 0, 0, width, height);
});
// Získá rozměry video streamu, který je připraven k přehrávání,
$("video").on('canplay', function(e) {
if (!streaming) {
height = video.videoHeight / (video.videoWidth / width);
video.setAttribute('width', width);
video.setAttribute('height', height);
streaming = true;
}
});
});
</script>
Další informace
- Mozilla dokumentace k Navigator.getUserMedia
- Mozilla tutoriál pro Web Cam Access
- getUserMedia tutoriál od by Iana Devlina
Demo a výsledný kód
- celý kód najdete na GitHubu
- funkční demo k článku
Přehled komentářů