Skip to content

Commit

Permalink
Prevent double execution enumerateDevices method which breaks mobile …
Browse files Browse the repository at this point in the history
…chrome and safari Fix basst314#95
  • Loading branch information
yamaha252 committed Nov 25, 2020
1 parent 98e29fc commit 94ef5a7
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 47 deletions.
21 changes: 10 additions & 11 deletions src/app/modules/webcam/util/webcam.util.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
export class WebcamUtil {

private static availableVideoInputs: MediaDeviceInfo[] = [];

/**
* Lists available videoInput devices
* @returns a list of media device info.
*/
public static getAvailableVideoInputs(): Promise<MediaDeviceInfo[]> {
public static async getAvailableVideoInputs(): Promise<MediaDeviceInfo[]> {
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
return Promise.reject('enumerateDevices() not supported.');
throw new Error('enumerateDevices() not supported.');
}

if (!WebcamUtil.availableVideoInputs.length) {
const devices = await navigator.mediaDevices.enumerateDevices();
WebcamUtil.availableVideoInputs = devices.filter((device: MediaDeviceInfo) => device.kind === 'videoinput');
}

return new Promise((resolve, reject) => {
navigator.mediaDevices.enumerateDevices()
.then((devices: MediaDeviceInfo[]) => {
resolve(devices.filter((device: MediaDeviceInfo) => device.kind === 'videoinput'));
})
.catch(err => {
reject(err.message || err);
});
});
return WebcamUtil.availableVideoInputs;
}
}
53 changes: 17 additions & 36 deletions src/app/modules/webcam/webcam/webcam.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ export class WebcamComponent implements AfterViewInit, OnDestroy {
private switchCameraSubscription: Subscription;
/** MediaStream object in use for streaming UserMedia data */
private mediaStream: MediaStream = null;
@ViewChild('video', { static: true }) private video: any;
@ViewChild('video', {static: true}) private video: any;
/** Canvas for Video Snapshots */
@ViewChild('canvas', { static: true }) private canvas: any;
@ViewChild('canvas', {static: true}) private canvas: any;

/** width and height of the active video stream */
private activeVideoSettings: MediaTrackSettings = null;
Expand Down Expand Up @@ -183,17 +183,13 @@ export class WebcamComponent implements AfterViewInit, OnDestroy {
return null;
}

public ngAfterViewInit(): void {
this.detectAvailableDevices()
.then(() => {
// start video
this.switchToVideoInput(null);
})
.catch((err: string) => {
this.initError.next(<WebcamInitError>{message: err});
// fallback: still try to load webcam, even if device enumeration failed
this.switchToVideoInput(null);
});
public async ngAfterViewInit() {
try {
await this.detectAvailableDevices();
} catch (e) {
this.initError.next(<WebcamInitError>{message: e.message});
}
this.switchToVideoInput(null);
}

public ngOnDestroy(): void {
Expand Down Expand Up @@ -317,7 +313,7 @@ export class WebcamComponent implements AfterViewInit, OnDestroy {
const videoTrackConstraints = WebcamComponent.getMediaConstraintsForDevice(deviceId, userVideoTrackConstraints);

navigator.mediaDevices.getUserMedia(<MediaStreamConstraints>{video: videoTrackConstraints})
.then((stream: MediaStream) => {
.then(async (stream: MediaStream) => {
this.mediaStream = stream;
_video.srcObject = stream;
_video.play();
Expand All @@ -329,16 +325,11 @@ export class WebcamComponent implements AfterViewInit, OnDestroy {

// Initial detect may run before user gave permissions, returning no deviceIds. This prevents later camera switches. (#47)
// Run detect once again within getUserMedia callback, to make sure this time we have permissions and get deviceIds.
this.detectAvailableDevices()
.then(() => {
this.activeVideoInputIndex = activeDeviceId ? this.availableVideoInputs
.findIndex((mediaDeviceInfo: MediaDeviceInfo) => mediaDeviceInfo.deviceId === activeDeviceId) : -1;
this.videoInitialized = true;
})
.catch(() => {
this.activeVideoInputIndex = -1;
this.videoInitialized = true;
});
await this.detectAvailableDevices();

this.activeVideoInputIndex = activeDeviceId ? this.availableVideoInputs
.findIndex((mediaDeviceInfo: MediaDeviceInfo) => mediaDeviceInfo.deviceId === activeDeviceId) : -1;
this.videoInitialized = true;
})
.catch((err: MediaStreamError) => {
this.initError.next(<WebcamInitError>{message: err.message, mediaStreamError: err});
Expand Down Expand Up @@ -411,18 +402,8 @@ export class WebcamComponent implements AfterViewInit, OnDestroy {
/**
* Reads available input devices
*/
private detectAvailableDevices(): Promise<MediaDeviceInfo[]> {
return new Promise((resolve, reject) => {
WebcamUtil.getAvailableVideoInputs()
.then((devices: MediaDeviceInfo[]) => {
this.availableVideoInputs = devices;
resolve(devices);
})
.catch(err => {
this.availableVideoInputs = [];
reject(err);
});
});
private async detectAvailableDevices(): Promise<void> {
this.availableVideoInputs = await WebcamUtil.getAvailableVideoInputs();
}

}

0 comments on commit 94ef5a7

Please sign in to comment.