Skip to content

Instantly share code, notes, and snippets.

@kalaschnik
Last active August 25, 2020 11:30
Show Gist options
  • Save kalaschnik/8a5ea604f63d9676bf434413e6072310 to your computer and use it in GitHub Desktop.
Save kalaschnik/8a5ea604f63d9676bf434413e6072310 to your computer and use it in GitHub Desktop.
Demo of Webcam using JavaScript's WebRTC API: getUserMedia()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WebRTC Webcam Demo</title>
</head>
<body>
<video id="video-preview" muted></video>
<button style="height: 2rem;" id="button-start">🔴 START RECORDING</button
><br /><br />
<button id="button-stop">🚫 STOP RECORDING</button>
<video id="video-playback" controls></video>
<script src="webcam-recorder-previewer.js"></script>
</body>
</html>
// define the media track constraints object
// NB https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints
(function () {
const constraintObj = {
audio: true,
video: true,
// video: {
// facingMode: "user",
// width: { min: 640, ideal: 1280, max: 1920 },
// height: { min: 480, ideal: 720, max: 1080 }
// }
// Other useful props:
// width: 1280, height: 720 -- preference only
// facingMode: {exact: "user"} // forcing to be user camera
// facingMode: "environment"
};
// handle older browsers that might implement getUserMedia in some way
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
navigator.mediaDevices.getUserMedia = function (constraintObj) {
const getUserMedia =
navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
if (!getUserMedia) {
return Promise.reject(
new Error("getUserMedia is not implemented in this browser")
);
}
return new Promise(function (resolve, reject) {
getUserMedia.call(navigator, constraintObj, resolve, reject);
});
};
} else {
// this logs all Audio/Video IO connections:
navigator.mediaDevices
.enumerateDevices()
.then(devices => {
devices.forEach(device => {
console.log(device.kind.toUpperCase(), device.label);
//, device.deviceId
});
})
.catch(err => {
console.log(err.name, err.message);
});
}
// Use WebRTC getUserMedia method() and provide constraintObj
navigator.mediaDevices
.getUserMedia(constraintObj) // getUserMedia returns a promise
.then(function (mediaStreamObj) {
// on fullfillment you get a stream object
// connect the stream object to the first video element
const video = document.querySelector("#video-preview");
if ("srcObject" in video) {
video.srcObject = mediaStreamObj;
} else {
// legacy version
video.src = window.URL.createObjectURL(mediaStreamObj);
}
// PREVIEW THE CURRENT WEBCAM STREAM
video.onloadedmetadata = () => video.play();
// RECORDING PART
const start = document.getElementById("button-start");
const stop = document.getElementById("button-stop");
const videoPlayback = document.getElementById("video-playback");
// MediaStream Recorind API (you pass in the stream object as parameter)
const mediaRecorder = new MediaRecorder(mediaStreamObj);
let dataChunks = [];
// add listeners for start/stop clicks
start.addEventListener("click", () => {
mediaRecorder.start();
console.log(mediaRecorder.state);
});
stop.addEventListener("click", () => {
mediaRecorder.stop();
console.log(mediaRecorder.state);
});
// store data chunks while recording
mediaRecorder.ondataavailable = function (ev) {
dataChunks.push(ev.data);
};
// After pressing stop the onstop event fires
// Create a blob
mediaRecorder.onstop = () => {
let blob = new Blob(dataChunks, { type: "video/mp4;" });
// if there is another recording it is good to reset the data chunks, otherwise this gets appended
dataChunks = [];
// convert blob into objectURL
let videoURL = window.URL.createObjectURL(blob);
videoPlayback.src = videoURL;
};
})
.catch(err => {
console.log(err.name, err.message);
// If getUserMedia rejects the Promise one of the following errors may occur:
// AbortError - generic unknown cause
// NotAllowedError (SecurityError) - user rejected permissions
// NotFoundError - missing media track
// NotReadableError - user permissions given but hardware/OS error
// OverconstrainedError - constraint video settings preventing
// TypeError - audio: false, video: false
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment