Closed lenny76 closed 6 years ago
I don't think so, 😕 Can you please provide a use case/example?
So you want to get a device only if it supports certain image quality?
I'd like to increase the resolution of the video setting higher constrain but i don't know how to do it because the module itself create the video instance and you cannot edit constraints anymore What I want to do is take a picture with higher resolution.
Any ideas?
The library should already take the best available resolution from the camera. 😕
Closing as no follow up, I hope I can improve the docs soon so users can build their own readers on top of the core.
There are many use cases for this request.
The native HTML5 getUserMedia()
API provides a set of constraints that can be used to access media settings like focus, torch, etc. In our particular case, we absolutely need to be able to control the focus constraint, because we are scanning fairly small QR codes, which will be completely blurry/out-of-focus without control of the camera focus.
In the zxing-js library, the code is creating constraints that are passed to the native mediaDevices API; however, unfortunately there's no access to the constraints for consumers of the zxing API, because the constraints params aren't exposed outside the library. You can see this in BrowserCodeReader
line # 235-241, where a videoConstraints
object is being created:
https://github.com/zxing-js/library/blob/master/src/browser/BrowserCodeReader.ts#L235
It seems fairly straightforward to create a non-breaking change/enhancement that would expose the media constraints object to a caller. What would be needed to satisfy this use case is to allow passing in a constraints
object, which would be merged with the object being created in BrowserCodeReader
. Without this, the library is blocking access to critical parts of the mediaDevices
API.
So, as an example:
public async decodeFromInputVideoDeviceContinuously(deviceId: string | null, videoSource: string | HTMLVideoElement | null, callbackFn: DecodeContinuouslyCallback, constraints: : MediaTrackConstraints | null): Promise<void> {
let videoConstraints: MediaTrackConstraints = constraints || {};
if (!deviceId) {
videoConstraints = Object.assign({ facingMode: 'environment' }, constraints);
} else {
videoConstraints = Object.assign({ deviceId: { exact: deviceId } }, constraints);
}
}
Why bother with a constraints object when you can simply pass the device you want as an argument?
@odahcam
As I mentioned above:
because we are scanning fairly small QR codes, which will be completely blurry/out-of-focus without control of the camera focus.
We need to control capabilities like focusMode
, torch
, etc. I know of no way to manage these capabilities without being able to set the constraints on the mediaDevice. Is there some other way that you know of?
[...] you can simply pass the device you want as an argument?
That means you have full control over it, including the constraints, because currently is the only way to access media devices.
@odahcam
Could you please provide an example of what you're suggesting?
Do you mean to literally pass the device
object to this function?
decodeFromInputVideoDeviceContinuously(deviceId: string | null, videoSource: string | HTMLVideoElement | null, callbackFn: DecodeContinuouslyCallback, constraints: : MediaTrackConstraints | null)
Or do you mean the deviceId
?
The only way that I've seen to apply constraints is to a stream obtained from getUserMedia()
, and as I noted above, that call is already being made in the ZxingJs library code in decodeXX
in BrowserCodeReader
.
The examples that I've seen look like this:
navigator.mediaDevices.getUserMedia(constraints)
.then(function(mediaStream) {
So, I'm not clear how I could create such a stream myself and also use the codeReader
.
Once agin, what I'm trying to accomplish is to set the focusMode
for the video device.
Sorry for that, my mistake here, I though it was ngx-scanner. Please take a look at #198 and tell me if it suits your needs.
@odahcam Yes, this new API function seems to be what I was looking for:
/**
* Continuously tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.
*
* @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from
* @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.
* @returns {Promise<Result>} The decoding result.
*
* @memberOf BrowserCodeReader
*/
private async decodeFromConstraints(constraints: MediaStreamConstraints, videoSource: string | HTMLVideoElement, callbackFn: DecodeContinuouslyCallback): Promise<void> {
I see it's in an open PR. When will this be in a release that I can get via npm?
Thanks.
Probably tonight, but subscribe to #199 be sure.
@odahcam I've updated the library this morning to 0.15.0.
When I reviewed your changes, they seemed good and exactly what's needed. However, there are several functions that you've marked as private
, including decodeFromConstraints()
, which is the one that would have solved my use case.
Why is this function private? With this change and the private functions, there isn't really any substantial difference to the consumer of the API, because nothing new is being exposed. Can't these functions all be public?
Thanks.
Of course, they should be public since their creation! Haha, my bad. I made the changes too fast and when I was tired, my main concern was to not break compatibility nor the build and tests, so I forgot to change the methods visibility after refactoring. I can merge a PR and publish a patch by the night if you open one just to change that.
This looks good. Some documentation about it on the front page would be handy.
I'm also having focus problems. On my device the scanner is focusing about 20cm away when I need it to focus about 5cm away. The device can easily handle focusing 5cm away so it's not a hardware issue.
@MrChriZ same issue here. could you solve it?
@MrChriZ same issue here. could you solve it?
I'm afraid it's too long since I did this to really remember... however I think I did get it working and looking back at the code I used here's how I initiated it:
const constraints = { facingMode: 'environment', "video": { width: { exact: 100 } } }; const mediaStreamConstraints = { video: constraints }; const hints = new Map(); hints.set(DecodeHintType.TRY_HARDER, true); let barcodeReader = new BrowserMultiFormatReader(hints); return { barcodeReader, mediaStreamConstraints };
I hope that helps.
const constraints = { facingMode: 'environment', "video": { width: { exact: 100 } } }; const mediaStreamConstraints = { video: constraints }
@MrChriZ the only difference with my code seems to be the TRY_HARDER
hint, but it's doing nothing. Do you remember if you got the camera to focus on a small (and near) image?
Thanks!
I'm afraid I don't really remember. However I created a little test project which is still live: https://d2gg774neoa43f.cloudfront.net/ Just press the scan button to give it a go.
For some reason this solution not working anymore with v0.19.2, but using v0.15.1 working perfectly
hi
is it possible to set the video constraints of the video tag before initialize the camera? I cannot find any idea about it
thanks