Skip to content

Commit cbd8bea

Browse files
committed
Allow to get high quality pictures.
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.
1 parent 0ebfea6 commit cbd8bea

File tree

3 files changed

+54
-40
lines changed

3 files changed

+54
-40
lines changed

dist/webcam-easy.js

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
class Webcam {
1+
export default class Webcam {
22
constructor(webcamElement, facingMode = 'user', canvasElement = null, snapSoundElement = null) {
33
this._webcamElement = webcamElement;
44
this._webcamElement.width = this._webcamElement.width || 640;
5-
this._webcamElement.height = this._webcamElement.height || video.width * (3 / 4);
5+
this._webcamElement.height = this._webcamElement.height || this._webcamElement.width * (3 / 4);
66
this._facingMode = facingMode;
77
this._webcamList = [];
88
this._streamList = [];
@@ -41,7 +41,7 @@ class Webcam {
4141
});
4242
if(this._webcamList.length == 1){
4343
this._facingMode = 'user';
44-
}
44+
}
4545
return this._webcamList;
4646
}
4747

@@ -53,14 +53,16 @@ class Webcam {
5353
} else {
5454
videoConstraints.deviceId = { exact: this._selectedDeviceId};
5555
}
56+
/* Try to get a media stream that takes at least 1080p pictures */
57+
videoConstraints.height = { min: 1080 }
5658
var constraints = {
5759
video: videoConstraints,
5860
audio: false
5961
};
6062
return constraints;
6163
}
6264

63-
/* Select camera based on facingMode */
65+
/* Select camera based on facingMode */
6466
selectCamera(){
6567
for(let webcam of this._webcamList){
6668
if( (this._facingMode=='user' && webcam.label.toLowerCase().includes('front'))
@@ -73,21 +75,21 @@ class Webcam {
7375
}
7476
}
7577

76-
/* Change Facing mode and selected camera */
78+
/* Change Facing mode and selected camera */
7779
flip(){
7880
this._facingMode = (this._facingMode == 'user')? 'enviroment': 'user';
7981
this._webcamElement.style.transform = "";
80-
this.selectCamera();
82+
this.selectCamera();
8183
}
8284

8385
/*
8486
1. Get permission from user
8587
2. Get all video input devices info
86-
3. Select camera based on facingMode
88+
3. Select camera based on facingMode
8789
4. Start stream
8890
*/
8991
async start(startStream = true) {
90-
return new Promise((resolve, reject) => {
92+
return new Promise((resolve, reject) => {
9193
this.stop();
9294
navigator.mediaDevices.getUserMedia(this.getMediaConstraints()) //get permisson from user
9395
.then(stream => {
@@ -106,7 +108,7 @@ class Webcam {
106108
}else{
107109
resolve(this._selectedDeviceId);
108110
}
109-
})
111+
})
110112
.catch(error => {
111113
reject(error);
112114
});
@@ -117,27 +119,32 @@ class Webcam {
117119
});
118120
}
119121

120-
/* Get all video input devices info */
122+
/* Get all video input devices info */
121123
async info(){
122-
return new Promise((resolve, reject) => {
124+
return new Promise((resolve, reject) => {
123125
navigator.mediaDevices.enumerateDevices()
124126
.then(devices =>{
125127
this.getVideoInputs(devices);
126128
resolve(this._webcamList);
127-
})
129+
})
128130
.catch(error => {
129131
reject(error);
130132
});
131133
});
132134
}
133-
134-
/* Start streaming webcam to video element */
135+
136+
/* Start streaming webcam to video element */
135137
async stream() {
136-
return new Promise((resolve, reject) => {
138+
return new Promise((resolve, reject) => {
137139
navigator.mediaDevices.getUserMedia(this.getMediaConstraints())
138140
.then(stream => {
141+
let self = this;
139142
this._streamList.push(stream);
140143
this._webcamElement.srcObject = stream;
144+
this._webcamElement.onloadedmetadata = function() {
145+
self.snapHeight = this.videoHeight;
146+
self.snapWidth = this.videoWidth;
147+
}
141148
if(this._facingMode == 'user'){
142149
this._webcamElement.style.transform = "scale(-1,1)";
143150
}
@@ -151,22 +158,22 @@ class Webcam {
151158
});
152159
}
153160

154-
/* Stop streaming webcam */
161+
/* Stop streaming webcam */
155162
stop() {
156163
this._streamList.forEach(stream => {
157164
stream.getTracks().forEach(track => {
158165
track.stop();
159166
});
160-
});
167+
});
161168
}
162169

163170
snap() {
164171
if(this._canvasElement!=null){
165172
if(this._snapSoundElement!= null){
166173
this._snapSoundElement.play();
167174
}
168-
this._canvasElement.height = this._webcamElement.scrollHeight;
169-
this._canvasElement.width = this._webcamElement.scrollWidth;
175+
this._canvasElement.width = this.snapWidth || this._webcamElement.scrollWidth;
176+
this._canvasElement.height = this.snapHeight || this._webcamElement.scrollHeight;
170177
let context = this._canvasElement.getContext('2d');
171178
if(this._facingMode == 'user'){
172179
context.translate(this._canvasElement.width, 0);
@@ -180,5 +187,5 @@ class Webcam {
180187
else{
181188
throw "canvas element is missing";
182189
}
183-
}
184-
}
190+
}
191+
}

dist/webcam-easy.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/webcam-easy.js

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default class Webcam {
4141
});
4242
if(this._webcamList.length == 1){
4343
this._facingMode = 'user';
44-
}
44+
}
4545
return this._webcamList;
4646
}
4747

@@ -53,14 +53,16 @@ export default class Webcam {
5353
} else {
5454
videoConstraints.deviceId = { exact: this._selectedDeviceId};
5555
}
56+
/* Try to get a media stream that takes at least 1080p pictures */
57+
videoConstraints.height = { min: 1080 }
5658
var constraints = {
5759
video: videoConstraints,
5860
audio: false
5961
};
6062
return constraints;
6163
}
6264

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

76-
/* Change Facing mode and selected camera */
78+
/* Change Facing mode and selected camera */
7779
flip(){
7880
this._facingMode = (this._facingMode == 'user')? 'enviroment': 'user';
7981
this._webcamElement.style.transform = "";
80-
this.selectCamera();
82+
this.selectCamera();
8183
}
8284

8385
/*
8486
1. Get permission from user
8587
2. Get all video input devices info
86-
3. Select camera based on facingMode
88+
3. Select camera based on facingMode
8789
4. Start stream
8890
*/
8991
async start(startStream = true) {
90-
return new Promise((resolve, reject) => {
92+
return new Promise((resolve, reject) => {
9193
this.stop();
9294
navigator.mediaDevices.getUserMedia(this.getMediaConstraints()) //get permisson from user
9395
.then(stream => {
@@ -106,7 +108,7 @@ export default class Webcam {
106108
}else{
107109
resolve(this._selectedDeviceId);
108110
}
109-
})
111+
})
110112
.catch(error => {
111113
reject(error);
112114
});
@@ -117,27 +119,32 @@ export default class Webcam {
117119
});
118120
}
119121

120-
/* Get all video input devices info */
122+
/* Get all video input devices info */
121123
async info(){
122-
return new Promise((resolve, reject) => {
124+
return new Promise((resolve, reject) => {
123125
navigator.mediaDevices.enumerateDevices()
124126
.then(devices =>{
125127
this.getVideoInputs(devices);
126128
resolve(this._webcamList);
127-
})
129+
})
128130
.catch(error => {
129131
reject(error);
130132
});
131133
});
132134
}
133-
134-
/* Start streaming webcam to video element */
135+
136+
/* Start streaming webcam to video element */
135137
async stream() {
136-
return new Promise((resolve, reject) => {
138+
return new Promise((resolve, reject) => {
137139
navigator.mediaDevices.getUserMedia(this.getMediaConstraints())
138140
.then(stream => {
141+
let self = this;
139142
this._streamList.push(stream);
140143
this._webcamElement.srcObject = stream;
144+
this._webcamElement.onloadedmetadata = function() {
145+
self.snapHeight = this.videoHeight;
146+
self.snapWidth = this.videoWidth;
147+
}
141148
if(this._facingMode == 'user'){
142149
this._webcamElement.style.transform = "scale(-1,1)";
143150
}
@@ -151,22 +158,22 @@ export default class Webcam {
151158
});
152159
}
153160

154-
/* Stop streaming webcam */
161+
/* Stop streaming webcam */
155162
stop() {
156163
this._streamList.forEach(stream => {
157164
stream.getTracks().forEach(track => {
158165
track.stop();
159166
});
160-
});
167+
});
161168
}
162169

163170
snap() {
164171
if(this._canvasElement!=null){
165172
if(this._snapSoundElement!= null){
166173
this._snapSoundElement.play();
167174
}
168-
this._canvasElement.height = this._webcamElement.scrollHeight;
169-
this._canvasElement.width = this._webcamElement.scrollWidth;
175+
this._canvasElement.width = this.snapWidth || this._webcamElement.scrollWidth;
176+
this._canvasElement.height = this.snapHeight || this._webcamElement.scrollHeight;
170177
let context = this._canvasElement.getContext('2d');
171178
if(this._facingMode == 'user'){
172179
context.translate(this._canvasElement.width, 0);
@@ -180,5 +187,5 @@ export default class Webcam {
180187
else{
181188
throw "canvas element is missing";
182189
}
183-
}
190+
}
184191
}

0 commit comments

Comments
 (0)