zxing-js / library

Multi-format 1D/2D barcode image processing library, usable in JavaScript ecosystem.
https://zxing-js.github.io/library/
Apache License 2.0
2.5k stars 547 forks source link

video constraint #70

Closed lenny76 closed 6 years ago

lenny76 commented 6 years ago

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

odahcam commented 6 years ago

I don't think so, 😕 Can you please provide a use case/example?

lenny76 commented 6 years ago

https://webrtc.github.io/samples/src/content/getusermedia/resolution/

odahcam commented 6 years ago

So you want to get a device only if it supports certain image quality?

lenny76 commented 6 years ago

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?

odahcam commented 6 years ago

The library should already take the best available resolution from the camera. 😕

odahcam commented 6 years ago

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.

ghost commented 5 years ago

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);
    }

}
odahcam commented 5 years ago

Why bother with a constraints object when you can simply pass the device you want as an argument?

ghost commented 5 years ago

@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?

odahcam commented 5 years ago

[...] 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.

ghost commented 5 years ago

@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.

odahcam commented 5 years ago

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.

ghost commented 5 years ago

@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.

odahcam commented 5 years ago

Probably tonight, but subscribe to #199 be sure.

ghost commented 5 years ago

@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.

odahcam commented 5 years ago

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.

ghost commented 5 years ago

@odahcam https://github.com/zxing-js/library/pull/201

MrChriZ commented 5 years ago

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.

natoszme commented 2 years ago

@MrChriZ same issue here. could you solve it?

MrChriZ commented 2 years ago

@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.

natoszme commented 2 years ago

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!

MrChriZ commented 2 years ago

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.

DogmaZh commented 1 year ago

For some reason this solution not working anymore with v0.19.2, but using v0.15.1 working perfectly