I'm trying to get the camera to focus on an object, by using focusMode on the stream track received from getUserMedia. But after changing the property of focus mode to manual mode, I don't see it reflect on the stream also I could see that after applying focusMode constraint it stays unchanged(focusMode: continuous). The issue is when I capture an image, using the stream, the image is blurry because of lack of focus.
Here is a code snippet.
navigator.mediaDevices.getUserMedia({ video: true })
.then((stream) => {
video.srcObject = stream;
track = stream.getVideoTracks()[0];
track.applyConstraints({
advanced: [
{ focusMode: 'manual', focusDistance: 0.33 }
]
})
});
Does anybody have experience with getting the camera to focus using the manual or single-shot mode? Any help is appreciated.
Related
I'm developing a webRTC video chat application with a screen-sharing feature, but after getting the video and audio stream, the tab becomes muted.
const stream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: true,
preferCurrentTab: true, //used to locate the current tab easily
});
let audio = new Audio("https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3");
audio.play(); // playing audio why this audio is muted
This is a known bug from Chromiums side: https://bugs.chromium.org/p/chromium/issues/detail?id=1317964&q=preferCurrentTab&can=2
This is the latest update from a Chrome author:
It is on my schedule to implement suppressLocalAudioPlayback, which would then allow me to make the change you're requesting here. Currently, I plan to implement it in August.
So hopefully in one of the next updates, a fix is shipped.
The suppressLocalAudioPlayback audio constraint available in Chrome 109 is what you're looking for. When set to true, it indicates that the browser should stop relaying audio to the local speakers when capture starts. The default value for this constraint is false.
// Prompt the user to share a tab, a window or a screen with audio.
// If successful, stop the captured audio from being played out over
// the local device’s speakers.
const stream = await navigator.mediaDevices.getDisplayMedia({
audio: { suppressLocalAudioPlayback: true },
});
const [audioTrack] = stream.getAudioTracks();
const settings = audioTrack.getSettings();
console.log(settings.suppressLocalAudioPlayback); // true
As of the time of writing, suppressLocalAudioPlayback does not yet work with applyConstraints(). See Chromium Bug 1381959.
I want to get a video from the webcam using JS but no footage.
MESSAGE:
DOMException: Could not start video source
App.js
const video = document.getElementById("video");
function startVideo() {
navigator.getUserMedia(
{
video: {}
},
stream => (video.srcObject = stream),
err => console.log(err)
);
}
startVideo();
index.html
...
<body>
<video id="video" width="720" height="540" autoplay muted></video>
</body>
...
thanks for your help
If anyone else is having this problem and nothing else helps. Make sure that your camera is not already claimed/used by a different software/browser.
TLDR: I have tested your code and had to change it a bit:
https://codepen.io/puradawid/pen/PoqxzPQ
It looks like the problem lays here:
navigator.getUserMedia({
video: {}
},
stream => { video.srcObject = stream },
err => console.log(err)
);
Regarding to docs navigator.getUserMedia is deprecated and there is navigator.mediaDevices.getUserMedia that supports it. However, changing that up doesn't solve the correct problem which is your callback functions. This method returns Promise that is controlled by .then(), so changing it allows me to see my face in codepen:
navigator.mediaDevices.getUserMedia({
video: true
}).then(
stream => (video.srcObject = stream),
err => console.log(err)
);
I ran into this problem on certain android devices (Sony XA2) when trying to toggle the camera on a mobile browser because I am calling navigator.mediaDevices.getUserMedia repeatedly on each camera toggle.
The solution that I found was to make sure to stop all the tracks in previous streams that you created.
this.stream.getTracks().forEach(t => {
t.stop();
this.stream.removeTrack(t);
});
Without the previous code you can't seem to toggle camera on certain Android devices: (Demo),
(Code)
The error shown was DOMException: Requested device not found
By stopping previous tracks: you are able to start a new stream:
(Demo)
Code
Note: The following code snippet doesn't seem to execute in stack overflow due to security restrictions, so please use the jsfiddle links.
class Camera {
constructor({ video }) {
this.facingMode = "environment";
this.video = video;
video.onloadedmetadata = () => {
video.play();
};
}
async toggleCamera() {
if (this.facingMode === "environment") {
this.facingMode = "user";
} else {
this.facingMode = "environment";
}
try {
if (this.stream){
/* On some android devices, it is necessary to stop the previous track*/
this.stream.getTracks().forEach(t => t.stop());
}
this.stream = await navigator.mediaDevices.getUserMedia({
video: {
facingMode: this.facingMode,
}
});
} catch (e) {
console.error(e);
}
this.video.srcObject = this.stream;
}
}
const camera = new Camera({
video: document.querySelector("video"),
});
const button = document.querySelector("button");
button.addEventListener('click', () => {
camera.toggleCamera();
});
<button>
Toggle Camera
</button>
<video></video>
In Windows 10 go to settings->privacy->App permission(left side)->Microphone-> enable 'Allow apps to access your microphone'
After that retry with your JS program....It will work!!
If anyone have such an error and you are working on a laptop. You can try bending your laptop monitor in both directions. Sometimes the cable comes loose. This helped in my case.
Also look into Feature-Policy HTTP header, both on the website and on the host web server config, and make sure camera access is allowed.
I have tried all the other solution but nothing is work. Then finally i need to uninstall my camera driver in Device Manager and then scan for hardware changes. Try to run the app again and it's working.
I'm building electron desktop app in windows 10.
electron: 15.3.0
Source video that helped me: https://www.youtube.com/watch?v=XE2ULFlzkxw
I went to the browser settings for camera and noticed that the default camera was showing as "Leap Motion" which is not a standard camera device. I changed to an actual webcam and the problem was solved.
Sometimes this type of error also appears when you try to make a peer-to-peer call system and your tests are done on the same device. The camera is already used by the initiator and the receiver can no longer activate the camera.
i wanted to take screenshots from a mobilephone camera using javascript getUserMedia function but resolution is very bad.
if (navigator.mediaDevices) {
// access the web cam
navigator.mediaDevices.getUserMedia({
video: {
width: {
min: 1280,
},
height: {
min: 720,
},
facingMode: {
exact: 'environment'
}
}
}).then(function(stream) {
video.srcObject = stream;
video.addEventListener('click', takeSnapshot);
})
.catch(function(error) {
document.body.textContent = 'Could not access the camera. Error: ' + error.name;
});
}
var video = document.querySelector('video'), canvas;
function takeSnapshot(){
var img = document.createElement('img');
var context;
var width = video.offsetWidth, height = video.offsetHeight;
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
context = canvas.getContext('2d');
context.webkitImageSmoothingEnabled = false;
context.mozImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
context.drawImage(video, 0, 0, width, height);
img.src = canvas.toDataURL('image/jpeg');
}
No errors-code, but resolution not good, i cannot read the text of the photo.
There is a method to get real image quality from camera?
MediaCapture
This is what you are using via getUserMedia.
If you have a camera which allows a 1920x1080, 1280x720, and 640x480 resolutions only, the browser implementation of Media Capture can emulate a 480x640 feed from the 1280x720 (see MediaStream). From testing (primarily Chrome) the browser typically scales 720 down to 640 and then crops the center. Sometimes when I have used virtual camera software I see Chrome has added artificial black padding around a non supported resolution. The client sees a success message and a feed of the right dimensions but a person would see a qualitative degradation. Because of this emulation you cannot guarantee the feed is correct or not scaled. However it will typically have the correct dimensions requested.
You can read about constraints here. It basically boils down to: Give me a resolution as close to x. Then the browser determines by its own implementation to reject the constraints and throw an error, get the resolution, or emulate the resolution.
More information of this design is detailed in the mediacapture specification. Especially:
The RTCPeerConnection is an interesting object because it acts
simultaneously as both a sink and a source for over-the-network
streams. As a sink, it has source transformational capabilities (e.g.,
lowering bit-rates, scaling-up / down resolutions, and adjusting
frame-rates), and as a source it could have its own settings changed
by a track source.
The main reason for this is allowing n clients to have access to the same media source but may require different resolutions, bit rate, etc, thus emulation/scaling/transforming attempts to solve this problem. A negative to this is that you never truly know what the source resolution is.
ImageCapture
This is potentially your solution.
If 60FPS video isn't a hard requirement and you have leway on compatibility you can poll ImageCapture to emulate a camera and receive a much clearer image from the camera.
You would have to check for clientside support and then potentially fallback on MediaCapture.
The API enables control over camera features such as zoom, brightness, contrast, ISO and white balance. Best of all, Image Capture allows you to access the full resolution capabilities of any available device camera or webcam. Previous techniques for taking photos on the Web have used video snapshots (MediaCapture rendered to a Canvas), which are lower resolution than that available for still images.
https://developers.google.com/web/updates/2016/12/imagecapture
and its polyfill:
https://github.com/GoogleChromeLabs/imagecapture-polyfill
I just want to mention that when using the imagecapture-polyfill for taking photos in Safari or Chrome on iOS, I was getting really bad image quality until I added a 2 sec. delay in-between getting the MediaStreamTrack and calling the ImageCapture constructor. This is not really an answer because I don't know why this delay is necessary, but maybe it can help someone anyway.
// Media constraints
const constraints = {
audio: false,
video: {
facingMode: { exact: 'environment' }, // Use the back camera (otherwise the front camera will be used by default)
width: { ideal: 99999 },
height: { ideal: 99999 }
}
};
// MediaStream
navigator.mediaDevices.getUserMedia(constraints).then(async mediaStream => { // The user will get a notification on the mobile device that this interface is being used
// MediaStreamTrack
const mediaStreamTrack = mediaStream.getVideoTracks()[0];
// ImageCapture
await new Promise(resolve => setTimeout(resolve, 2000)); // For an unknown reason, adding this delay greatly increases image quality on iOS
this.imageCapture = new ImageCapture(mediaStreamTrack); // Note that iOS doesn't support ImageCapture [as of 2022-11-08] and instead uses the libs/imagecapture-polyfill.js to obtain an image by using the <canvas> instead
// Take picture
return this.imageCapture.takePhoto().then(blob => {
// Upload photo right away
if (blob) {
I also edited the imagecapture-polyfill.js code to get a jpeg instead of a png, greatly reducing the file size.
self.canvasElement.toBlob(resolve, 'image/jpeg'); // [YB 2022-11-02: Output jpeg instead of png]
Trying to access IP Camera that is connected to a wifi.
I am connected to that wifi but I am getting error. If I try open using vlc I am able to connect but not getUserMedia has null.
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
})
export class HomeComponent {
#ViewChild('video') video: any;
constructor() {
}
hasGetUserMedia() {
return !!(navigator.mediaDevices &&
navigator.mediaDevices.getUserMedia);
}
ngAfterViewInit() {
if (this.hasGetUserMedia()) {
// Good to go!
console.log("Gooddd................");
} else {
alert('getUserMedia() is not supported by your browser');
}
let _video = this.video.nativeElement;
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(function (stream) {
_video.src = window.URL.createObjectURL(stream);
_video.play();
}).catch(function (err) {
console.log(err);
});
}
}
}
<video #video width="640" height="480" autoplay></video>
This happens when you dont have any device to capture video or capture audio
try checking if your webcam and your microphone are working fine
Try without "audio: true". Its help for my. (Microphone are not work).
And check webcam on other sites.
Maybe need check permissions for this page.
try changing this line:
_video.src = window.URL.createObjectURL(stream);
with this one:
_video.srcObject = stream;
Use this line to initialize the webcam and microphone:
navigator.mediaDevices.getUserMedia({ audio: true, video: true });
In my case i have connected external camera through USB i was able to get the devices, i was getting kind of devices as audiooutput and videoinput, and there was no audioinput(microphone device) but while i was requesting for devices i passed constraints as..
function Webcam(){
this.constraints = {
video: true,
audio: true
}
this.userMedia = null;
this.mediaDevices = navigator.mediaDevices;
this.initialize = function(){
this.userMedia = this.mediaDevices.getUserMedia(this.constraints);
}
}
let webcam = new Webcam();
webcam.initialize();
So Promise not satisified and getting error as Requested device not found.
Try attaching an earpiece or earplug with microphone to your PC. mine has no microphone that was why I got that error
This issue can also occur on some mobile devices (Sony XA2 running Android) if you had previously already created a MediaStream.
The solution that I found was to make sure to stop all the tracks of previous streams that you created.
this.stream.getTracks().forEach(t => {
t.stop();
// I don't think removeTrack is necessary, but just keeping it.
this.stream.removeTrack(t);
});
Without the previous code you can't seem to toggle camera on certain Android devices: (Demo),
(Code)
The error shown was DOMException: Requested device not found
By stopping previous tracks: you are able to start a new stream:
(Demo)
Code
Note: I also answered a related question here: https://stackoverflow.com/a/73550841/1123985
I have mic and camera but I was getting the same error. I was pretty sure that was related to laptop setting, because I tried everything. turns out my laptop was blocking access to the media. I am using linux and laptop brand name is MSI, I started to look for any sign that related to the camera setting. On F6 button, my laptop has a webcam icon. So I clicked on
fn + F6
It works now. most likely sometimes I click on fn+* keys to see any difference and I blocked the camera access.
On Samsung Galaxy S2 Android 6.0.1 + Chrome v55, when I getUserMedia on page load, the video track acquired appears live.
When I select the back camera from my camera select, I trigger another time my gUM with constraints to use that exact facing back cameraId, the video track is ended, I have a black rectangle instead of a stream.
var constraints = {
video: {
deviceId: {
exact: defaultVideoDeviceId
}
},
audio: true
};
gUM wrapper
function gUM(constraints, callback) {
console.debug("WebRTC constraints", constraints);
// Stopping streaming before starting the new one
if (window.streams.local) {
window.streams.local.getTracks().forEach(function(track) {
track.stop();
});
}
navigator.mediaDevices.getUserMedia(constraints)
.then(stream => {
console.debug("New MediaStream > Tracks", stream.getTracks());
window.streams.local = stream;
callback && callback(stream);
})
.catch(err => {
console.log("Raised error when capturing:", err);
});
}
If I switch back to front, it acquires a new MediaStream and it plays the video.
I'm facing a similar problem too.
My test is a bit different since I'm trying to make a GUM of the back camera while I have a GUM a media stream active that is using the front camera.
I tested in several android devices and only the Xiaomi MI Mix 2 with the MIUI beta 875 with android 8.1 works. This can be because that rom uses the new camera2 android api, or because the Mi Mix 2 camera hardware allows the usage of both the back and the front camera at the same time.
The annoying thing is that sometimes, on certain devices, the GUM doesn't fail, but hangs indefinitely.
Maybe listening to the MediaStreamTrack.onended event after the track.stop() method call, can help to understand when resources are completely free so as you can try a new GUM with different constraints.
Please let me know if you discovered something.
Simone