EN
JavaScript - play web camera video on canvas element (webcam usage example)
6
points
In this short article, you can see how to stream video from web camera to canvas element using JavaScript.
Example preview:
Practical example
Note: it is important to be sure the web camera is connected properly and not used by any other application.
// ONLINE-RUNNER:browser;
<!doctype html>
<html>
<body>
<canvas id="my-canvas" width="640" height="480"></canvas>
<script>
function playStream(canvas, stream) {
var video = document.createElement('video');
video.addEventListener('loadedmetadata', function() {
const context = canvas.getContext('2d');
var drawFrame = function() {
context.drawImage(video, 0, 0);
window.requestAnimationFrame(drawFrame);
};
drawFrame();
});
video.autoplay = true;
video.srcObject = stream;
}
function playCamera(canvas, preferedWidth, preferedHeight) {
var devices = navigator.mediaDevices;
if (devices && 'getUserMedia' in devices) {
var constraints = {
video: {
width: preferedWidth,
height: preferedHeight
}
// you can use microphone adding `audio: true` property here
};
var promise = devices.getUserMedia(constraints);
promise
.then(function(stream) {
playStream(canvas, stream);
})
.catch(function(error) {
console.error(error.name + ': ' + error.message);
});
} else {
console.error('Camera API is not supported.');
}
}
// Usage example:
var canvas = document.querySelector('#my-canvas');
playCamera(canvas, canvas.width, canvas.height);
</script>
</body>
</html>
Hint: used solutions in the above example were introduced in the major web browsers around 2016.
Giving premissions
When a web camera is accessed from JavaScript you should see notification to permit using it. Just let use it by desired website and remove permissions when it is not needed.
Reusable logic
In this section, you can find reusable class that plays indicated stream on canvas element.
// Possible player states:
//
const PLAYER_WAITING = 1;
const PLAYER_STARTING = 2;
const PLAYER_WORKING = 3;
const PLAYER_STOPPING = 4;
function findStream(preferedWidth, preferedHeight, callback) {
const devices = navigator.mediaDevices;
if (devices && 'getUserMedia' in devices) {
const constraints = {
video: {
width: preferedWidth,
height: preferedHeight
}
// you can use microphone adding `audio: true` property here
};
const promise = devices.getUserMedia(constraints);
promise
.then(function(stream) {
callback(stream, null);
})
.catch(function(error) {
callback(null, `${error.name}: ${error.message}`);
});
} else {
callback(null, 'Camera API is not supported.');
}
}
function StreamPlayer(canvas, callback) {
let _state = PLAYER_WAITING;
if (callback) {
callback(_state, null);
}
const _context = canvas.getContext('2d');
const _video = document.createElement('video');
_video.addEventListener('loadedmetadata', function() {
switch (_state) {
case PLAYER_STARTING:
_state = PLAYER_WORKING;
if (callback) {
callback(_state, null);
}
const drawFrame = function() {
switch (_state) {
case PLAYER_WORKING:
_context.drawImage(_video, 0, 0);
window.requestAnimationFrame(drawFrame);
break;
case PLAYER_STOPPING:
_state = PLAYER_WAITING;
if (callback) {
callback(_state, null);
}
break;
}
};
drawFrame();
break;
case PLAYER_STOPPING:
_state = PLAYER_WAITING;
if (callback) {
callback(_state, null);
}
break;
}
});
_video.autoplay = true;
const playStream = function(stream) {
if (_state === PLAYER_WAITING) {
_state = PLAYER_STARTING;
_video.srcObject = stream;
if (callback) {
callback(_state, null);
}
}
};
const stopStream = function() {
if (_state === PLAYER_STARTING || _state === PLAYER_WORKING) {
_state = PLAYER_STOPPING;
_video.srcObject = null;
if (callback) {
callback(_state, null);
}
}
};
// Plays indicated stream.
// e.g.
// const canvas = document.querySelector('#my-canvas');
// const player = new StreamPlayer(canvas, function(state, error) {
// console.log(`state: ${state} error: ${error}`);
// });
// player.play$2(stream); // use `devices.getUserMedia()` method to get stream
//
this.play$1 = playStream;
// Plays detected web camera.
// e.g.
// const canvas = document.querySelector('#my-canvas');
// const player = new StreamPlayer(canvas, function(state, error) {
// console.log(`state: ${state} error: ${error}`);
// });
// player.play$2();
//
this.play$2 = function() {
if (_state === PLAYER_WAITING) {
findStream(canvas.width, canvas.height, function(stream, error) {
if (error) {
stopStream();
if (callback) {
callback(0, error);
}
} else {
playStream(stream);
}
});
}
};
// Stops web camera streaming.
//
this.stop = stopStream;
}
// Usage example 1:
const canvas = document.querySelector('#my-canvas');
const player = new StreamPlayer(canvas, function(state, error) {
console.log(`state: ${state} error: '${error}'`);
});
player.play$2(); // to stop: player.stop();
// Usage example 2:
const canvas = document.querySelector('#my-canvas');
const player = new StreamPlayer(canvas, function(state, error) {
console.log(`state: ${state} error: '${error}'`);
});
findStream(canvas.width, canvas.height, function(stream, error) {
if (error) {
console.log(`error: ${error}`);
} else {
player.play$1(stream); // to stop: player.stop();
}
});
// Where: findStream() uses `devices.getUserMedia()` method to find web camera and access stream