05.12.2013

Сделать снимок с веб-камеры! Онлайн! Бесплатно! Без SMS!

HTML5 getUserMedia API дает доступ к оборудованию пользователя: веб-камере, микрофону и т.д. Далее расскажу как на чистом JavaScript можно сделать снимок с веб-камеры прямо в браузере.

HTML

Разметка для стриминга видео с веб-камеры и кнопки управления.

<div>
    <video id="screenshot-stream" class="videostream" autoplay></video>
    <img id="screenshot" src="">
    <canvas id="screenshot-canvas" style="display:none;"></canvas>
    <p>
        <button id="screenshot-button">Включить камеру</button>
        <button id="screenshot-stop-button" class="hide">Сбросить</button>
    </p>
</div>

CSS

Ничего особенного: задаем размеры video и img, класс hide для чтобы прятать кнопку выключения камеры и класс red для подсветки кнопки.

* {
    border:0;
    margin:0;
    padding:0;
}
html {
    font-size: 1em;
    margin-top: 1em;
}
div {
    text-align:center;
video, img {
    width:400px;
    height:300px;
    display:inline-block;
    vertical-align:top;
}
button {
    margin:.5em;
    font-size: 1em;
    padding:1em;
    background-color: darkblue;
    color:#fff;
    font-family: sans-serif;
    border-radius: 1em;
    border:0;
    cursor:pointer;
    width:12em;
}
button:hover {
    background-color: blue;
}
.red {
    background-color: #ff1c43;
}
.hide {
    display:none;
}

JavaScript

Здесь проверяем наличие функционала и выводим грустные сообщения, если камера не поддерживается или нет доступа. Вешаем события на кнопки ну и так далее. Посмотреть как работает можно здесь.

function hasGetUserMedia() {
    return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
            navigator.mozGetUserMedia || navigator.msGetUserMedia);
}

if (hasGetUserMedia()) {
    function errorCallback(e) {
        if (e.code == 1) {
            alert('Вы запретили доступ к веб-камере');
        } else {
            alert('Ваш браузер не поддерживает getUserMedia');
        }

    }

    (function() {
        var video = document.querySelector('#screenshot-stream');
        var button = document.querySelector('#screenshot-button');
        var canvas = document.querySelector('#screenshot-canvas');
        var img = document.querySelector('#screenshot');
        var ctx = canvas.getContext('2d');
        var localMediaStream = null;

        function sizeCanvas() {
            // video.onloadedmetadata not firing in Chrome so we have to hack.
            // See crbug.com/110938.
            setTimeout(function() {
                canvas.width = video.videoWidth;
                canvas.height = video.videoHeight;
                img.height = video.videoHeight;
                img.width = video.videoWidth;
            }, 100);
        }

        function snapshot() {
            ctx.drawImage(video, 0, 0);
            img.src = canvas.toDataURL('image/jpeg');
        }

        function sizeAndGo(stream) {
            localMediaStream = stream;
            sizeCanvas();
            button.textContent = 'Сделать снимок';
            button.className = 'red';
            document.querySelector('#screenshot-stop-button').className = '';
        }

        button.addEventListener('click', function(e) {
            if (localMediaStream) {
                snapshot();
                return;
            }

            if (navigator.getUserMedia) {
                navigator.getUserMedia('video', function(stream) {
                    video.src = stream;
                    sizeAndGo(stream);
                }, errorCallback);
            } else if (navigator.webkitGetUserMedia) {
                navigator.webkitGetUserMedia({video: true}, function(stream) {
                    video.src = window.URL.createObjectURL(stream);
                    sizeAndGo(stream);
                }, errorCallback);
            } else {
                errorCallback({target: video});
            }
        }, false);

        video.addEventListener('click', snapshot, false);

        document.querySelector('#screenshot-stop-button').addEventListener('click', function(e) {
            video.pause();
            localMediaStream.stop(); // Doesn't do anything in Chrome.
            window.location.reload();
        }, false);
    })();
} else {
    alert('Ваш браузер не поддерживает getUserMedia');
}