Get device labels onpageshow
I'm coding a web app, where user can use his camera (and choose which one to use). The problem is that I want user to be available to choose the camera before it is enabled. In the current code, when user turns on a page, he sees an empty list of cameras and when he enables the camera stream, dropdown list populates with camera names. I want the dropdown list populate when he turns on that web page.
P.S. when I stop() the camera, it disables camera and gives just a black screen. Why it is black instead of background colour?
CameraStreamView.cshtml
@using Api.Models
@{
ViewBag.Title = "Smart Vision";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="~/Content/Contact-Form-Clean.css">
</head>
<body onpageshow="Init()">
<div id="container">
<video id="video" style="display: block; margin: 0 auto; margin-top: 30px;" width="300" height="400" autoplay></video>
<button id="enableStream" style="display: block; margin: 0 auto; margin-top: 20px; height: 70px; width: 200px" onclick="start()">Enable camera</button>
<button id="disableStream" style="display: block; margin: 0 auto; margin-top: 20px; height: 70px; width: 200px" onclick="stop()">Disable camera</button>
<label for="videoSource">Video source: </label><select id="videoSource"></select>
</div>
<script src="~/Scripts/GetCameraFeed.js"></script>
</body>
</html>
GetCameraFeed.js
const videoSelect = document.querySelector('select#videoSource');
const selectors = [videoSelect];
function gotDevices(deviceInfos) {
// Handles being called several times to update labels. Preserve values.
const values = selectors.map(select => select.value);
selectors.forEach(select => {
while (select.firstChild) {
select.removeChild(select.firstChild);
}
});
for (let i = 0; i !== deviceInfos.length; ++i) {
const deviceInfo = deviceInfos[i];
const option = document.createElement('option');
option.value = deviceInfo.deviceId;
if (deviceInfo.kind === 'videoinput') {
option.text = deviceInfo.label;
videoSelect.appendChild(option);
}
}
selectors.forEach((select, selectorIndex) => {
if (Array.prototype.slice.call(select.childNodes).some(n => n.value === values[selectorIndex])) {
select.value = values[selectorIndex];
}
});
}
function Init() {
navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
}
function gotStream(stream) {
window.stream = stream; // make stream available to console
video.srcObject = stream;
// Refresh button list in case labels have become available
return navigator.mediaDevices.enumerateDevices();
}
function handleError(error) {
console.log('navigator.getUserMedia error: ', error);
}
function start() {
const videoSource = videoSelect.value;
const constraints = {
video: { deviceId: videoSource ? { exact: videoSource } : undefined }
};
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).then(gotDevices).catch(handleError);
}
function stop() {
video.pause();
video.src = "";
stream.getTracks().forEach(track => track.stop());
console.log("Stopping stream");
}
javascript webrtc getusermedia
add a comment |
I'm coding a web app, where user can use his camera (and choose which one to use). The problem is that I want user to be available to choose the camera before it is enabled. In the current code, when user turns on a page, he sees an empty list of cameras and when he enables the camera stream, dropdown list populates with camera names. I want the dropdown list populate when he turns on that web page.
P.S. when I stop() the camera, it disables camera and gives just a black screen. Why it is black instead of background colour?
CameraStreamView.cshtml
@using Api.Models
@{
ViewBag.Title = "Smart Vision";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="~/Content/Contact-Form-Clean.css">
</head>
<body onpageshow="Init()">
<div id="container">
<video id="video" style="display: block; margin: 0 auto; margin-top: 30px;" width="300" height="400" autoplay></video>
<button id="enableStream" style="display: block; margin: 0 auto; margin-top: 20px; height: 70px; width: 200px" onclick="start()">Enable camera</button>
<button id="disableStream" style="display: block; margin: 0 auto; margin-top: 20px; height: 70px; width: 200px" onclick="stop()">Disable camera</button>
<label for="videoSource">Video source: </label><select id="videoSource"></select>
</div>
<script src="~/Scripts/GetCameraFeed.js"></script>
</body>
</html>
GetCameraFeed.js
const videoSelect = document.querySelector('select#videoSource');
const selectors = [videoSelect];
function gotDevices(deviceInfos) {
// Handles being called several times to update labels. Preserve values.
const values = selectors.map(select => select.value);
selectors.forEach(select => {
while (select.firstChild) {
select.removeChild(select.firstChild);
}
});
for (let i = 0; i !== deviceInfos.length; ++i) {
const deviceInfo = deviceInfos[i];
const option = document.createElement('option');
option.value = deviceInfo.deviceId;
if (deviceInfo.kind === 'videoinput') {
option.text = deviceInfo.label;
videoSelect.appendChild(option);
}
}
selectors.forEach((select, selectorIndex) => {
if (Array.prototype.slice.call(select.childNodes).some(n => n.value === values[selectorIndex])) {
select.value = values[selectorIndex];
}
});
}
function Init() {
navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
}
function gotStream(stream) {
window.stream = stream; // make stream available to console
video.srcObject = stream;
// Refresh button list in case labels have become available
return navigator.mediaDevices.enumerateDevices();
}
function handleError(error) {
console.log('navigator.getUserMedia error: ', error);
}
function start() {
const videoSource = videoSelect.value;
const constraints = {
video: { deviceId: videoSource ? { exact: videoSource } : undefined }
};
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).then(gotDevices).catch(handleError);
}
function stop() {
video.pause();
video.src = "";
stream.getTracks().forEach(track => track.stop());
console.log("Stopping stream");
}
javascript webrtc getusermedia
add a comment |
I'm coding a web app, where user can use his camera (and choose which one to use). The problem is that I want user to be available to choose the camera before it is enabled. In the current code, when user turns on a page, he sees an empty list of cameras and when he enables the camera stream, dropdown list populates with camera names. I want the dropdown list populate when he turns on that web page.
P.S. when I stop() the camera, it disables camera and gives just a black screen. Why it is black instead of background colour?
CameraStreamView.cshtml
@using Api.Models
@{
ViewBag.Title = "Smart Vision";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="~/Content/Contact-Form-Clean.css">
</head>
<body onpageshow="Init()">
<div id="container">
<video id="video" style="display: block; margin: 0 auto; margin-top: 30px;" width="300" height="400" autoplay></video>
<button id="enableStream" style="display: block; margin: 0 auto; margin-top: 20px; height: 70px; width: 200px" onclick="start()">Enable camera</button>
<button id="disableStream" style="display: block; margin: 0 auto; margin-top: 20px; height: 70px; width: 200px" onclick="stop()">Disable camera</button>
<label for="videoSource">Video source: </label><select id="videoSource"></select>
</div>
<script src="~/Scripts/GetCameraFeed.js"></script>
</body>
</html>
GetCameraFeed.js
const videoSelect = document.querySelector('select#videoSource');
const selectors = [videoSelect];
function gotDevices(deviceInfos) {
// Handles being called several times to update labels. Preserve values.
const values = selectors.map(select => select.value);
selectors.forEach(select => {
while (select.firstChild) {
select.removeChild(select.firstChild);
}
});
for (let i = 0; i !== deviceInfos.length; ++i) {
const deviceInfo = deviceInfos[i];
const option = document.createElement('option');
option.value = deviceInfo.deviceId;
if (deviceInfo.kind === 'videoinput') {
option.text = deviceInfo.label;
videoSelect.appendChild(option);
}
}
selectors.forEach((select, selectorIndex) => {
if (Array.prototype.slice.call(select.childNodes).some(n => n.value === values[selectorIndex])) {
select.value = values[selectorIndex];
}
});
}
function Init() {
navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
}
function gotStream(stream) {
window.stream = stream; // make stream available to console
video.srcObject = stream;
// Refresh button list in case labels have become available
return navigator.mediaDevices.enumerateDevices();
}
function handleError(error) {
console.log('navigator.getUserMedia error: ', error);
}
function start() {
const videoSource = videoSelect.value;
const constraints = {
video: { deviceId: videoSource ? { exact: videoSource } : undefined }
};
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).then(gotDevices).catch(handleError);
}
function stop() {
video.pause();
video.src = "";
stream.getTracks().forEach(track => track.stop());
console.log("Stopping stream");
}
javascript webrtc getusermedia
I'm coding a web app, where user can use his camera (and choose which one to use). The problem is that I want user to be available to choose the camera before it is enabled. In the current code, when user turns on a page, he sees an empty list of cameras and when he enables the camera stream, dropdown list populates with camera names. I want the dropdown list populate when he turns on that web page.
P.S. when I stop() the camera, it disables camera and gives just a black screen. Why it is black instead of background colour?
CameraStreamView.cshtml
@using Api.Models
@{
ViewBag.Title = "Smart Vision";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="~/Content/Contact-Form-Clean.css">
</head>
<body onpageshow="Init()">
<div id="container">
<video id="video" style="display: block; margin: 0 auto; margin-top: 30px;" width="300" height="400" autoplay></video>
<button id="enableStream" style="display: block; margin: 0 auto; margin-top: 20px; height: 70px; width: 200px" onclick="start()">Enable camera</button>
<button id="disableStream" style="display: block; margin: 0 auto; margin-top: 20px; height: 70px; width: 200px" onclick="stop()">Disable camera</button>
<label for="videoSource">Video source: </label><select id="videoSource"></select>
</div>
<script src="~/Scripts/GetCameraFeed.js"></script>
</body>
</html>
GetCameraFeed.js
const videoSelect = document.querySelector('select#videoSource');
const selectors = [videoSelect];
function gotDevices(deviceInfos) {
// Handles being called several times to update labels. Preserve values.
const values = selectors.map(select => select.value);
selectors.forEach(select => {
while (select.firstChild) {
select.removeChild(select.firstChild);
}
});
for (let i = 0; i !== deviceInfos.length; ++i) {
const deviceInfo = deviceInfos[i];
const option = document.createElement('option');
option.value = deviceInfo.deviceId;
if (deviceInfo.kind === 'videoinput') {
option.text = deviceInfo.label;
videoSelect.appendChild(option);
}
}
selectors.forEach((select, selectorIndex) => {
if (Array.prototype.slice.call(select.childNodes).some(n => n.value === values[selectorIndex])) {
select.value = values[selectorIndex];
}
});
}
function Init() {
navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
}
function gotStream(stream) {
window.stream = stream; // make stream available to console
video.srcObject = stream;
// Refresh button list in case labels have become available
return navigator.mediaDevices.enumerateDevices();
}
function handleError(error) {
console.log('navigator.getUserMedia error: ', error);
}
function start() {
const videoSource = videoSelect.value;
const constraints = {
video: { deviceId: videoSource ? { exact: videoSource } : undefined }
};
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).then(gotDevices).catch(handleError);
}
function stop() {
video.pause();
video.src = "";
stream.getTracks().forEach(track => track.stop());
console.log("Stopping stream");
}
javascript webrtc getusermedia
javascript webrtc getusermedia
edited Nov 12 '18 at 18:54
Deivyyyy
asked Nov 12 '18 at 18:44
DeivyyyyDeivyyyy
85
85
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
What you want is explicitly disallowed, due to fingerprinting concerns. Details about a user's setup let web sites identify them uniquely on the web, a privacy concern.
Once users trust your site with their camera and microphone, this information is considered relevant to share.
The working group determined this to be a reasonable trade-off, for several reasons:
- Most desktop users have only one camera or none.
- Most phone users have two, but you can use the facingMode constraint to pick.
- Given 1 and 2, an up-front choice is arguably an inferior user experience for most.
I would consider changing your code to ask for the default camera the first time, and give users a choice to change it after the fact, should they need to. It's what most WebRTC sites do.
Note that this should only be a problem the first time a user visits your site. Provided they've granted camera or microphone just once in the past, you should be able to see the labels, at least in Chrome.
Unlike Chrome, Firefox does not persist permission implicitly, so you'd need a little more work to get labels on page-load on repeat visits:
enumerateDevices
returns a deviceId
for each device, which is persisted for your site provided the user has granted (or will grant within this session) camera or microphone at least once. You can use cookies or local storage to correlate deviceId
s to device labels. This also survives people manually revoking permission in Chrome.
1
Thanks! Definitely keeping this in mind when updating the script!
– Deivyyyy
Nov 13 '18 at 19:43
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53268269%2fget-device-labels-onpageshow%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
What you want is explicitly disallowed, due to fingerprinting concerns. Details about a user's setup let web sites identify them uniquely on the web, a privacy concern.
Once users trust your site with their camera and microphone, this information is considered relevant to share.
The working group determined this to be a reasonable trade-off, for several reasons:
- Most desktop users have only one camera or none.
- Most phone users have two, but you can use the facingMode constraint to pick.
- Given 1 and 2, an up-front choice is arguably an inferior user experience for most.
I would consider changing your code to ask for the default camera the first time, and give users a choice to change it after the fact, should they need to. It's what most WebRTC sites do.
Note that this should only be a problem the first time a user visits your site. Provided they've granted camera or microphone just once in the past, you should be able to see the labels, at least in Chrome.
Unlike Chrome, Firefox does not persist permission implicitly, so you'd need a little more work to get labels on page-load on repeat visits:
enumerateDevices
returns a deviceId
for each device, which is persisted for your site provided the user has granted (or will grant within this session) camera or microphone at least once. You can use cookies or local storage to correlate deviceId
s to device labels. This also survives people manually revoking permission in Chrome.
1
Thanks! Definitely keeping this in mind when updating the script!
– Deivyyyy
Nov 13 '18 at 19:43
add a comment |
What you want is explicitly disallowed, due to fingerprinting concerns. Details about a user's setup let web sites identify them uniquely on the web, a privacy concern.
Once users trust your site with their camera and microphone, this information is considered relevant to share.
The working group determined this to be a reasonable trade-off, for several reasons:
- Most desktop users have only one camera or none.
- Most phone users have two, but you can use the facingMode constraint to pick.
- Given 1 and 2, an up-front choice is arguably an inferior user experience for most.
I would consider changing your code to ask for the default camera the first time, and give users a choice to change it after the fact, should they need to. It's what most WebRTC sites do.
Note that this should only be a problem the first time a user visits your site. Provided they've granted camera or microphone just once in the past, you should be able to see the labels, at least in Chrome.
Unlike Chrome, Firefox does not persist permission implicitly, so you'd need a little more work to get labels on page-load on repeat visits:
enumerateDevices
returns a deviceId
for each device, which is persisted for your site provided the user has granted (or will grant within this session) camera or microphone at least once. You can use cookies or local storage to correlate deviceId
s to device labels. This also survives people manually revoking permission in Chrome.
1
Thanks! Definitely keeping this in mind when updating the script!
– Deivyyyy
Nov 13 '18 at 19:43
add a comment |
What you want is explicitly disallowed, due to fingerprinting concerns. Details about a user's setup let web sites identify them uniquely on the web, a privacy concern.
Once users trust your site with their camera and microphone, this information is considered relevant to share.
The working group determined this to be a reasonable trade-off, for several reasons:
- Most desktop users have only one camera or none.
- Most phone users have two, but you can use the facingMode constraint to pick.
- Given 1 and 2, an up-front choice is arguably an inferior user experience for most.
I would consider changing your code to ask for the default camera the first time, and give users a choice to change it after the fact, should they need to. It's what most WebRTC sites do.
Note that this should only be a problem the first time a user visits your site. Provided they've granted camera or microphone just once in the past, you should be able to see the labels, at least in Chrome.
Unlike Chrome, Firefox does not persist permission implicitly, so you'd need a little more work to get labels on page-load on repeat visits:
enumerateDevices
returns a deviceId
for each device, which is persisted for your site provided the user has granted (or will grant within this session) camera or microphone at least once. You can use cookies or local storage to correlate deviceId
s to device labels. This also survives people manually revoking permission in Chrome.
What you want is explicitly disallowed, due to fingerprinting concerns. Details about a user's setup let web sites identify them uniquely on the web, a privacy concern.
Once users trust your site with their camera and microphone, this information is considered relevant to share.
The working group determined this to be a reasonable trade-off, for several reasons:
- Most desktop users have only one camera or none.
- Most phone users have two, but you can use the facingMode constraint to pick.
- Given 1 and 2, an up-front choice is arguably an inferior user experience for most.
I would consider changing your code to ask for the default camera the first time, and give users a choice to change it after the fact, should they need to. It's what most WebRTC sites do.
Note that this should only be a problem the first time a user visits your site. Provided they've granted camera or microphone just once in the past, you should be able to see the labels, at least in Chrome.
Unlike Chrome, Firefox does not persist permission implicitly, so you'd need a little more work to get labels on page-load on repeat visits:
enumerateDevices
returns a deviceId
for each device, which is persisted for your site provided the user has granted (or will grant within this session) camera or microphone at least once. You can use cookies or local storage to correlate deviceId
s to device labels. This also survives people manually revoking permission in Chrome.
answered Nov 13 '18 at 15:18
jibjib
20.4k64389
20.4k64389
1
Thanks! Definitely keeping this in mind when updating the script!
– Deivyyyy
Nov 13 '18 at 19:43
add a comment |
1
Thanks! Definitely keeping this in mind when updating the script!
– Deivyyyy
Nov 13 '18 at 19:43
1
1
Thanks! Definitely keeping this in mind when updating the script!
– Deivyyyy
Nov 13 '18 at 19:43
Thanks! Definitely keeping this in mind when updating the script!
– Deivyyyy
Nov 13 '18 at 19:43
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53268269%2fget-device-labels-onpageshow%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown