camera input select
This commit is contained in:
@@ -1,56 +0,0 @@
|
||||
import Node from './Node';
|
||||
|
||||
export default class Webcam extends Node {
|
||||
|
||||
constructor(options) {
|
||||
super('Webcam', {}, {
|
||||
image: {
|
||||
type: 'Image'
|
||||
},
|
||||
width: {
|
||||
type: 'Number',
|
||||
},
|
||||
height: {
|
||||
type: 'Number',
|
||||
}
|
||||
});
|
||||
this.start()
|
||||
.catch(console.error.bind(console))
|
||||
}
|
||||
|
||||
|
||||
async start() {
|
||||
const devices = (await navigator.mediaDevices.enumerateDevices()).filter((d) => d.kind === 'videoinput')
|
||||
const last = (ary) => ary[ary.length - 1];
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
video: {
|
||||
width: { min: 480, ideal: 1920, max: 1920 },
|
||||
height: { min: 320, ideal: 1080, max: 1080 },
|
||||
deviceId: last(devices).deviceId
|
||||
},
|
||||
});
|
||||
/** @type {HTMLVideoElement} */
|
||||
|
||||
const video = document.createElement('video');
|
||||
// @ts-ignore
|
||||
video.playsinline = true;
|
||||
video.srcObject = stream;
|
||||
video.play();
|
||||
let lastFrameTime = null;
|
||||
const feedLoop = () => {
|
||||
const currentTime = video.currentTime;
|
||||
if (lastFrameTime !== currentTime) {
|
||||
lastFrameTime = currentTime;
|
||||
this.out.image.value = video;
|
||||
this.out.width.value = video.videoWidth;
|
||||
this.out.height.value = video.videoHeight;
|
||||
}
|
||||
if (!this._stopped) {
|
||||
requestAnimationFrame(feedLoop);
|
||||
} else {
|
||||
video.src = null;
|
||||
}
|
||||
};
|
||||
feedLoop();
|
||||
}
|
||||
}
|
||||
94
src/nodes/Webcam.ts
Normal file
94
src/nodes/Webcam.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import Node from './Node';
|
||||
import {last} from 'lodash/array';
|
||||
import {find} from 'lodash/collection';
|
||||
import {NumberVar, StringVar, ImageVar} from './io/AbstractIOSet';
|
||||
|
||||
const outputs = {
|
||||
image: {
|
||||
type: 'Image'
|
||||
} as ImageVar,
|
||||
width: {
|
||||
type: 'Number',
|
||||
} as NumberVar,
|
||||
height: {
|
||||
type: 'Number',
|
||||
} as NumberVar,
|
||||
camera: {
|
||||
type: 'String',
|
||||
enum: [],
|
||||
} as StringVar
|
||||
}
|
||||
|
||||
export default class Webcam extends Node<any, typeof outputs> {
|
||||
|
||||
devices: MediaDeviceInfo[];
|
||||
currentDeviceId: string;
|
||||
video: HTMLVideoElement
|
||||
constructor(options) {
|
||||
super('Webcam', {}, outputs);
|
||||
this.start()
|
||||
.catch(console.error.bind(console))
|
||||
}
|
||||
|
||||
async start() {
|
||||
this.devices = (await navigator.mediaDevices.enumerateDevices()).filter((d) => d.kind === 'videoinput');
|
||||
this.out.camera.__definition.enum = this.devices.map(device => device.label)
|
||||
const deviceId = last(this.devices).deviceId;
|
||||
this.out.camera.value = this.getDeviceById(deviceId).label;
|
||||
|
||||
await this.startDevice(deviceId)
|
||||
|
||||
this.out.camera.onchange(async (label) => {
|
||||
this.video = null;
|
||||
const selectedDeviceId = this.getDeviceByLabel(label).deviceId;
|
||||
await this.startDevice(selectedDeviceId)
|
||||
})
|
||||
}
|
||||
|
||||
private async startDevice(deviceId) {
|
||||
this.currentDeviceId = deviceId;
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
video: {
|
||||
width: { min: 480, ideal: 1920, max: 1920 },
|
||||
height: { min: 320, ideal: 1080, max: 1080 },
|
||||
deviceId
|
||||
},
|
||||
});
|
||||
/** @type {HTMLVideoElement} */
|
||||
this.video = document.createElement('video');
|
||||
// @ts-ignore
|
||||
this.video.playsinline = true;
|
||||
this.video.srcObject = stream;
|
||||
this.video.play();
|
||||
let lastFrameTime = null;
|
||||
const feedLoop = () => {
|
||||
if (!this.video) {
|
||||
return;
|
||||
}
|
||||
const currentTime = this.video.currentTime;
|
||||
if (lastFrameTime !== currentTime) {
|
||||
lastFrameTime = currentTime;
|
||||
// @ts-ignore
|
||||
this.out.image.value = this.video;
|
||||
// @ts-ignore
|
||||
this.out.width.value = this.video.videoWidth;
|
||||
// @ts-ignore
|
||||
this.out.height.value = this.video.videoHeight;
|
||||
}
|
||||
if (!this._stopped) {
|
||||
requestAnimationFrame(feedLoop);
|
||||
} else {
|
||||
this.video.src = null;
|
||||
}
|
||||
};
|
||||
feedLoop();
|
||||
}
|
||||
|
||||
private getDeviceByLabel(label: string) {
|
||||
return find(this.devices, device => device.label === label);
|
||||
}
|
||||
|
||||
private getDeviceById(id: string) {
|
||||
return find(this.devices, device => device.deviceId === id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user