GoogleChromeLabs / imagecapture-polyfill

MediaStream ImageCapture polyfill. Take photos from the browser as easy as .takePhoto().then(processPhoto)
https://googlechromelabs.github.io/imagecapture-polyfill/
Apache License 2.0
186 stars 26 forks source link

DOMException: setOptions failed on takePhoto() #15

Open cormip opened 6 years ago

cormip commented 6 years ago

Using your own Quick Start example in Chrome Version 64.0.3282.186 (Official Build) (64-bit), the error DOMException: setOptions failed is thrown when takePhoto() is called:

function gotMedia(mediaStream) {
  // Extract video track.
  videoDevice = mediaStream.getVideoTracks()[0];
  // Check if this device supports a picture mode...
  let captureDevice = new ImageCapture(videoDevice);
  if (captureDevice) {
    captureDevice.takePhoto().then(processPhoto).catch(stopCamera);
    captureDevice.grabFrame().then(processFrame).catch(stopCamera);
  }
}
kbrownhbs commented 6 years ago

I have the same issue with: Version 64.0.3282.186 (Official Build) (64-bit)

webappdesigner commented 6 years ago

the same issue, here also; Version 65.0.3325.162 (Official Build) (64-bit)

NasskalteJuni commented 6 years ago

Same Issue, Chrome 65.0.3325.162 (Official Build, 64-bit for Windows). Example Code to reproduce:

navigator.mediaDevices.getUserMedia({audio: false, video: true}).then((stream) => {
   let track = stream.getVideoTracks()[0];
   console.log(track) // -> MediaStreamTrack Object
   let capture = new ImageCapture(track);
   return capture.takePhoto();
}).then(console.log).catch(console.error)
// -> throws error:
// DOMException: setOptions failed
NasskalteJuni commented 6 years ago

Not a fix for takePhoto or a reason why this happens but for those who only need to get an Image while this is not fixed or explained: I used grabFrame, since this error does not occur when calling this method and then reversed the polyfill video to canvas to image process a bit by drawing the resulting bitmap on a canvas and getting the Image as DataURL. If someone has a better way to convert the ImageBitmap to an Image, I would appreciate it very much. Samplecode:

navigator.mediaDevices.getUserMedia({audio: false, video: true}).then((stream) => {
   let track = stream.getVideoTracks()[0];
   console.log(track)
   let capture = new ImageCapture(track);
   console.log(capture) 
   return capture.grabFrame();
}).then((bitmap) => {
   let canvas = document.createElement('canvas');
   let context = canvas.getContext('2d');
   context.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height)
   return canvas.toDataURL();
}).then((src) => {
   // do something with the source
   console.log(src)
}).catch(console.error)

Does not solve that takePhoto always throws an error, but may be useful in a few situations

thijstriemstra commented 6 years ago

looks like they will remove the method ImageCapture.setOptions in Chrome 66 (https://developers.google.com/web/updates/2018/03/chrome-66-deprecations):

Current thinking on setting device options is to use the constrainable pattern . Consequently this property was removed from the ImageCapture specification . Since this method appears to have little to no use on production websites, it is being removed. A replacement method is not available at this time.

And adjusted the method signature (takePhoto now requires an options object) and released that change in Chrome 65: https://github.com/w3c/mediacapture-image/pull/150/files#diff-ec9cfa5f3f35ec1f84feb2e59686c34dL54

ghost commented 6 years ago

I have same issue, Version 68.0.3440.106 (Official Build) (64-bit) in Mas OS.

AnReZa commented 6 years ago

Does anybody know how to overcome this issue in Chrome 68? I'm getting the exact same error. Using the GrabFrame option isn't really an option for me, because taking full-resolution images is a requirement for my project.

I already tried this approach from the video.js library, which doesn't solve the problem and has been removed from their code in favor of the GrabFrame method as a workaround.

Does anybody know, which parameters are required in order to prevent the method from crashing?

@thijstriemstra Maybe you?

Antarus66 commented 5 years ago

I have the same thing. Version 73.0.3683.103 (Official Build) (64-bit) in Mac OS.

ebubep commented 5 years ago

Experiencing same issue. Chrome 76.0.3809.111 , Android 8.1.0 Only grabFrame() works

AnReZa commented 5 years ago

Looks like nobody is working on this issue.

luke-robertson commented 4 years ago

no updated ?

jmourell commented 4 years ago

Any updates on this?

NasskalteJuni commented 4 years ago

Any updates on this?

In the current Version of Chrome, it seems to work again. Version: Version 80.0.3987.149 (Official Build) (64-Bit)

working code:

(async () =>{
  const stream = await navigator.mediaDevices.getUserMedia({video:true, audio:false});
  if(!stream.getVideoTracks().length) throw new Error('no webcam');
  const capture = new ImageCapture(stream.getVideoTracks()[0]);
  const photoBlob = await capture.takePhoto();
  console.log(photoBlob)
})()

If problems still exist, they might be bound to a specific browser version. Close issue?

rossman15 commented 4 years ago

Any update on this?

Still failing...

const stream = await navigator.mediaDevices.getDisplayMedia({video:true, audio:false});
  const capture = new ImageCapture(stream.getVideoTracks()[0]);
  const photoBlob = await capture.takePhoto();
  console.log(photoBlob)
marcoippolito commented 4 years ago

Hi all! With:

      const capture = new ImageCapture(this.peer_stream.getVideoTracks()[0]);
      if (capture) {
        console.log(capture);
        const photoBlob = capture.takePhoto();
        console.log(photoBlob);
      }

I get this error: Uncaught (in promise) DOMException: The associated Track is in an invalid state.

marcoippolito commented 4 years ago

Any news about how to solve it? Google Chrome 81.0.4044.138

dalyr95 commented 4 years ago

Any news about how to solve it? Google Chrome 81.0.4044.138

Same Error: InvalidStateError: The associated Track is in an invalid state. Mozilla/5.0 (Linux; Android 10; RMX1971) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.101 Mobile Safari/537.36

JulianKlug commented 4 years ago

same problem here. Any news on the issue?

SuperPat45 commented 4 years ago

the problem does not appear on Chrome android

BioKalandra commented 4 years ago

hi. i'm jan. same issue on my end. best regards

rfaivre commented 4 years ago

Any update on the issue?

justb commented 2 years ago

Any update on the issue? Please don't abandon us.

simonmaass commented 2 years ago

i have the same issue in chrome Version 98.0.4758.102 (Offizieller Build) (64-Bit)

dandv commented 2 years ago

Hi everyone. While I'm the original creator of this library, I haven't been with Google for 3 years.

Could anyone from @GoogleChromeLabs take a look? @PaulKinlan / @paulirish ?

JulianKlug commented 2 years ago

@GoogleChromeLabs - would be great to have some updates on this feature 🤔

PaulKinlan commented 2 years ago

@beaufortfrancois might be able to help.

beaufortfrancois commented 2 years ago

The "InvalidStateError: The associated Track is in an invalid state." error is returned when TrackIsInactive() is true according to https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/imagecapture/image_capture.cc;l=252;drc=287fa204b78ccaa8da5c1a155c5fbfacafef31c8

bool TrackIsInactive(const MediaStreamTrack& track) {
  return track.readyState() != "live" || !track.enabled() || track.muted();
}

Can you look at readyState, muted, and enabled attributes from your video track and see if one is true?

AlbinNewSeed commented 11 months ago

@beaufortfrancois Any updates on this? Would be nice to be able to easily screenshot streams in the browser. Right now the method to draw the imageBitmap to a canvas doesn't work if the stream is a portrait mode camera, as there is no way to infer whether or not the stream is in portrait/landscape mode from the MediaTrack methods, and the height and width of the imageBitmap stays the same when flipped leading to a skewed image.