Skip to content

Commit

Permalink
Allow to get high quality pictures.
Browse files Browse the repository at this point in the history
Prior to this commit the quality of the picture was taken from the video
html component, which in general will lead to pretty low resolution.

Instead of that, we add a video constraint, so if possible the video will
project a stream with height of at least 1080p. We store global height
and width from the selected stream and set the canvas to those when snap
is taken.
  • Loading branch information
firvida committed Aug 4, 2021
1 parent 0ebfea6 commit 2d01f6f
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 40 deletions.
49 changes: 28 additions & 21 deletions dist/webcam-easy.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
class Webcam {
export default class Webcam {
constructor(webcamElement, facingMode = 'user', canvasElement = null, snapSoundElement = null) {
this._webcamElement = webcamElement;
this._webcamElement.width = this._webcamElement.width || 640;
this._webcamElement.height = this._webcamElement.height || video.width * (3 / 4);
this._webcamElement.height = this._webcamElement.height || this._webcamElement.width * (3 / 4);
this._facingMode = facingMode;
this._webcamList = [];
this._streamList = [];
Expand Down Expand Up @@ -41,7 +41,7 @@ class Webcam {
});
if(this._webcamList.length == 1){
this._facingMode = 'user';
}
}
return this._webcamList;
}

Expand All @@ -53,14 +53,16 @@ class Webcam {
} else {
videoConstraints.deviceId = { exact: this._selectedDeviceId};
}
/* Try to get a media stream that takes at least 1080p pictures */
videoConstraints.height = { min: 1080 }
var constraints = {
video: videoConstraints,
audio: false
};
return constraints;
}

/* Select camera based on facingMode */
/* Select camera based on facingMode */
selectCamera(){
for(let webcam of this._webcamList){
if( (this._facingMode=='user' && webcam.label.toLowerCase().includes('front'))
Expand All @@ -73,21 +75,21 @@ class Webcam {
}
}

/* Change Facing mode and selected camera */
/* Change Facing mode and selected camera */
flip(){
this._facingMode = (this._facingMode == 'user')? 'enviroment': 'user';
this._webcamElement.style.transform = "";
this.selectCamera();
this.selectCamera();
}

/*
1. Get permission from user
2. Get all video input devices info
3. Select camera based on facingMode
3. Select camera based on facingMode
4. Start stream
*/
async start(startStream = true) {
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
this.stop();
navigator.mediaDevices.getUserMedia(this.getMediaConstraints()) //get permisson from user
.then(stream => {
Expand All @@ -106,7 +108,7 @@ class Webcam {
}else{
resolve(this._selectedDeviceId);
}
})
})
.catch(error => {
reject(error);
});
Expand All @@ -117,27 +119,32 @@ class Webcam {
});
}

/* Get all video input devices info */
/* Get all video input devices info */
async info(){
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
navigator.mediaDevices.enumerateDevices()
.then(devices =>{
this.getVideoInputs(devices);
resolve(this._webcamList);
})
})
.catch(error => {
reject(error);
});
});
}
/* Start streaming webcam to video element */

/* Start streaming webcam to video element */
async stream() {
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
navigator.mediaDevices.getUserMedia(this.getMediaConstraints())
.then(stream => {
let self = this;
this._streamList.push(stream);
this._webcamElement.srcObject = stream;
this._webcamElement.onloadedmetadata = function() {
self.snapHeight = this.videoHeight;
self.snapWidth = this.videoWidth;
}
if(this._facingMode == 'user'){
this._webcamElement.style.transform = "scale(-1,1)";
}
Expand All @@ -151,22 +158,22 @@ class Webcam {
});
}

/* Stop streaming webcam */
/* Stop streaming webcam */
stop() {
this._streamList.forEach(stream => {
stream.getTracks().forEach(track => {
track.stop();
});
});
});
}

snap() {
if(this._canvasElement!=null){
if(this._snapSoundElement!= null){
this._snapSoundElement.play();
}
this._canvasElement.height = this._webcamElement.scrollHeight;
this._canvasElement.width = this._webcamElement.scrollWidth;
this._canvasElement.width = this.snapWidth || this._webcamElement.scrollWidth;
this._canvasElement.height = this.snapHeight || this._webcamElement.scrollHeight;
let context = this._canvasElement.getContext('2d');
if(this._facingMode == 'user'){
context.translate(this._canvasElement.width, 0);
Expand All @@ -180,5 +187,5 @@ class Webcam {
else{
throw "canvas element is missing";
}
}
}
}
}
2 changes: 1 addition & 1 deletion dist/webcam-easy.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 25 additions & 18 deletions src/webcam-easy.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default class Webcam {
});
if(this._webcamList.length == 1){
this._facingMode = 'user';
}
}
return this._webcamList;
}

Expand All @@ -53,14 +53,16 @@ export default class Webcam {
} else {
videoConstraints.deviceId = { exact: this._selectedDeviceId};
}
/* Try to get a media stream that takes at least 1080p pictures */
videoConstraints.height = { min: 1080 }
var constraints = {
video: videoConstraints,
audio: false
};
return constraints;
}

/* Select camera based on facingMode */
/* Select camera based on facingMode */
selectCamera(){
for(let webcam of this._webcamList){
if( (this._facingMode=='user' && webcam.label.toLowerCase().includes('front'))
Expand All @@ -73,21 +75,21 @@ export default class Webcam {
}
}

/* Change Facing mode and selected camera */
/* Change Facing mode and selected camera */
flip(){
this._facingMode = (this._facingMode == 'user')? 'enviroment': 'user';
this._webcamElement.style.transform = "";
this.selectCamera();
this.selectCamera();
}

/*
1. Get permission from user
2. Get all video input devices info
3. Select camera based on facingMode
3. Select camera based on facingMode
4. Start stream
*/
async start(startStream = true) {
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
this.stop();
navigator.mediaDevices.getUserMedia(this.getMediaConstraints()) //get permisson from user
.then(stream => {
Expand All @@ -106,7 +108,7 @@ export default class Webcam {
}else{
resolve(this._selectedDeviceId);
}
})
})
.catch(error => {
reject(error);
});
Expand All @@ -117,27 +119,32 @@ export default class Webcam {
});
}

/* Get all video input devices info */
/* Get all video input devices info */
async info(){
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
navigator.mediaDevices.enumerateDevices()
.then(devices =>{
this.getVideoInputs(devices);
resolve(this._webcamList);
})
})
.catch(error => {
reject(error);
});
});
}
/* Start streaming webcam to video element */

/* Start streaming webcam to video element */
async stream() {
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
navigator.mediaDevices.getUserMedia(this.getMediaConstraints())
.then(stream => {
let self = this;
this._streamList.push(stream);
this._webcamElement.srcObject = stream;
this._webcamElement.onloadedmetadata = function() {
self.snapHeight = this.videoHeight;
self.snapWidth = this.videoWidth;
}
if(this._facingMode == 'user'){
this._webcamElement.style.transform = "scale(-1,1)";
}
Expand All @@ -151,22 +158,22 @@ export default class Webcam {
});
}

/* Stop streaming webcam */
/* Stop streaming webcam */
stop() {
this._streamList.forEach(stream => {
stream.getTracks().forEach(track => {
track.stop();
});
});
});
}

snap() {
if(this._canvasElement!=null){
if(this._snapSoundElement!= null){
this._snapSoundElement.play();
}
this._canvasElement.height = this._webcamElement.scrollHeight;
this._canvasElement.width = this._webcamElement.scrollWidth;
this._canvasElement.width = this.snapWidth || this._webcamElement.scrollWidth;
this._canvasElement.height = this.snapHeight || this._webcamElement.scrollHeight;
let context = this._canvasElement.getContext('2d');
if(this._facingMode == 'user'){
context.translate(this._canvasElement.width, 0);
Expand All @@ -180,5 +187,5 @@ export default class Webcam {
else{
throw "canvas element is missing";
}
}
}
}

0 comments on commit 2d01f6f

Please sign in to comment.