1

I would like to use x to output a list of all connected webcams with ID. Unfortunately, I always get the following error message (see picture). enter image description here Does anyone have an idea what this could be? I am thankful for any help!

Here is my code:

const devices = []; var list; let video; function setup() { list = navigator.mediaDevices.enumerateDevices().then(gotDevices); var constraints1 = { video: { deviceId: { exact: list[0].id }, } }; canvas = createCanvas(width,height); background(255); video = createCapture(constraints1); } function gotDevices(deviceInfos) { for (let i = 0; i !== deviceInfos.length; ++i) { const deviceInfo = deviceInfos[i]; if (deviceInfo.kind == 'videoinput') { devices.push({ label: deviceInfo.label, id: deviceInfo.deviceId }); } } return devices; } 

-------------------------------EDIT (Current status)-----------------------

var deviceList = []; function preload() { navigator.mediaDevices.enumerateDevices().then(getDevices); } function setup() { var constraints = { video: { deviceId: { exact: deviceList[1].id }, } }; canvas = createCanvas(width, height); background(255); video = createCapture(constraints); //console.log(deviceList); } function getDevices(devices) { //arrayCopy(devices, deviceList); for (let i = 0; i < devices.length; ++i) { let deviceInfo = devices[i]; //Only get videodevices and push them into deviceList if (deviceInfo.kind == 'videoinput') { deviceList.push({ label: deviceInfo.label, id: deviceInfo.deviceId }); // console.log("Device name :", devices[i].label); // console.log("DeviceID :", devices[i].deviceId); } } } 

Unfortunately, I get the following error here: enter image description here

6
  • 1
    Are you sure 'list' is an array? Commented Jan 26, 2022 at 20:53
  • devices[0].id should run without error. Commented Jan 27, 2022 at 6:02
  • Unfortunately not. As soon as I enter devices[0].id as a constraint I get the following error: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'id') Commented Jan 27, 2022 at 14:07
  • My comment applied to the original code that you posted. Not the code that I posted. They're two different techniques. The original only works for the first video input that it comes across. The code I posted shows all the video and audio possibilities. You have to decide which one you're going to use. Don't try and mix them until you understand it better. Commented Jan 27, 2022 at 16:05
  • I'm testing in p5.js web editor with Chrome browser. What are you using to run these demos? Commented Jan 27, 2022 at 20:01

2 Answers 2

3

The information that you are looking for is down in the 'getDevices' function. The following runs on my system and will show the device name and id in the console window. It will also create a global array for audio and video devices that you may access in setup(); Note that the deviceList is obtained in preload() which is run only once before the rest of your code.

var deviceList = []; function preload() { navigator.mediaDevices.enumerateDevices().then(getDevices); } function setup() { var constraints = { video: { } }; canvas = createCanvas(width, height); background(255); video = createCapture(constraints); //console.log(deviceList); for (let x = 0; x < deviceList.length; x++) { console.log(deviceList[x]); } } function getDevices(devices) { // console.log(devices); // To see all devices arrayCopy(devices, deviceList); for (let i = 0; i < devices.length; ++i) { let deviceInfo = devices[i]; if (deviceInfo.kind == 'videoinput') { console.log("Device name :", devices[i].label); console.log("DeviceID :", devices[i].deviceId); } } } 

DropDownList of Devices

// N.B. Will not run in Processing IDE with Safari - Requires p5.js web editor and Chrome browser // Loads deviceList array into pullDown list // Drop Down List parts => a.)display field, b.)arrow, c.)listItems // Syntax: List(x, y, w, h, itemH, txtSize) let list; let selectedItem = -1; let drop = false; let itemY = []; var deviceList = []; function preload() { navigator.mediaDevices.enumerateDevices().then(getDevices); } class List { constructor(x, y, w, h, itemH, txtSize) { this.x = x; this.y = y; this.w = w; this.h = h; this.itemH = itemH; this.txtSize = txtSize; this.arrwX = this.x + this.w; this.arrwY = this.y; this.arrwH = this.h; } openVideoInput (videoSelected) { var constraints = { video: { deviceId: { exact: deviceList[videoSelected].id }, } }; createCapture(constraints); } press(mx, my) { // arrow touches if ((mx >= this.arrwX) && (mx <= this.arrwX+this.arrwH) && (my >= this.arrwY) && (my <= this.arrwY+this.arrwH)) { if (drop == true) { drop = false; } else { drop = true; } } // list touches if (drop) { if (deviceList.length > 0) { for (let j = 0; j < deviceList.length; j++) { if ((mx >= this.x) && (mx <= this.x + this.w) && (my >= itemY[j] ) && (my <= itemY[j] + this.itemH)) { selectedItem = j; console.log("selectedItem :", selectedItem); list.openVideoInput(selectedItem); drop = false; } } } } } displayFieldString(title) { fill(255); // background color rect(this.x, this.y, this.w, this.h); fill(0); // text color textSize(this.txtSize); text(title, this.x + 10, this.y + this.txtSize); } display() { if (selectedItem == -1) { this.displayFieldString("Select video input:"); } else { this.displayFieldString(deviceList[selectedItem].label); } // arrow fill(255); // arrow background color rect(this.arrwX, this.arrwY, this.arrwH, this.arrwH); fill(0, 255, 0); // arrow color triangle(this.arrwX+5, this.arrwY+5, this.arrwX+this.arrwH-5, this.arrwY+5, this.arrwX+this.arrwH/2, this.arrwY+this.arrwH-5); // listItems if ((deviceList.length > 0) && (drop)) { for (let j = 0; j < deviceList.length; j++) { itemY[j] = (this.y + this.h) + j*this.itemH; fill(255); rect(this.x, itemY[j], this.w, this.itemH); fill(0); textSize(this.txtSize); text(deviceList[j].label, this.x + 10, itemY[j] + this.txtSize); } } if (!drop) { rect(this.x, this.y + this.h, this.w, 0); } } } function setup() { createCanvas(400, 200); list = new List(30, 30, 320, 24, 24, 16); } function draw() { background(220); list.display(); } function getDevices(devices) { for (let i = 0; i < devices.length; ++i) { let deviceInfo = devices[i]; //Only get videodevices and push them into deviceList if (deviceInfo.kind == 'videoinput') { deviceList.push( { label:deviceInfo.label, id:deviceInfo.deviceId } ); } } } function mousePressed() { list.press(mouseX, mouseY); } 
Sign up to request clarification or add additional context in comments.

11 Comments

Hi apodidae, many thanks for your reply! :-) I thought list should be an array, since I return the device array in the function. At least that was my thought, but I think you are right.... My problem is that I have to read the current device id every time I start the application. So I wonder if there is a way to return the ID's of the devices (webcams) and save them in a separate global variable (optimally an array). I'm just biting my teeth on this one.
See edit. Added a global array to hold device list.
Hello apodidae, thanks for your answer! I have now updated the code to the current state, however I am still not able to start my video using the command: exact: deviceList[1].id It is important that the video source is selected directly from the array
If you have two video cameras hooked to your system, your edited technique will work. I was able to switch to a second camera by changing the [0] to a [1]. It won't work if you only have one camera connected.
Thanks for the answer. Yes, the original code works for multiple video inputs, because it goes through the entire devices array and pushes each video input into the new array. But exactly, the goal is to control three different cameras using their id.
|
0

Ok, now that I've looked further on the Internet for a solution and also found one, I thought I'd post it here too. Maybe it still helps someone else. The problem was that the array deviceList[] is not completely filled when the code reaches the following line:

deviceList[1].id within setup() 

The easiest way to solve this problem was to postpone the automatically initialization of the p5js library until your callback getDevices() has finished its job. Thanks again to apodidae for his help.

var deviceList = []; navigator.mediaDevices.enumerateDevices().then(getDevices); const setup = function () { var constraints = { video: { deviceId: { exact: deviceList[0].id }, } }; var constraints1 = { video: { deviceId: { exact: deviceList[1].id }, } }; canvas = createCanvas(width, height); background(255); video = createCapture(constraints); video2 = createCapture(constraints1); console.log(deviceList); }; const draw = function () { }; function startP5() { globalThis.setup = setup; // place callback setup() into global context globalThis.draw = draw; new p5; } function getDevices(devices) { //arrayCopy(devices, deviceList); for (let i = 0; i < devices.length; ++i) { let deviceInfo = devices[i]; //Only get videodevices and push them into deviceList if (deviceInfo.kind == 'videoinput') { deviceList.push({ label: deviceInfo.label, id: deviceInfo.deviceId }); // console.log("Device name :", devices[i].label); // console.log("DeviceID :", devices[i].deviceId); } } startP5(); } 

Here again the link to the other discussion

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.