-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clarify grabFrame timing #212
Comments
Agree that it should be clarified. The problem with grabbing the previous frame is that it's possible that the previous frame is no longer easily accessible (might have gone to display buffers), and may even not exist (in the case of before-first-frame). |
That's not overly complicated, though. I rewrote the Chromium implementation for
Isn't Chromium the only implementation, currently? Isn't one of the benefits of implementing early to learn this sort of stuff? I understand not wanting to change a widely implemented, widely used spec, but in this case I think it's reasonable to be more agile here since it's still new. This spec has only been published as a W3C Working Draft, it's not set in stone. Isn't that the point of the draft terminology, that it may change?
It wouldn't need to be a breaking change. Currently the timing of
This problem exists even when waiting for next frame, because there may not be a next frame, or the next frame may come after an arbitrary long amount of time. In fact, I'd consider it worse, since a stream can only have a 'before-first-frame' once (and it's easy to know this if you're tracking the last seen frame), where as a stream could have a 'no-next-frame' happen at any time. For no first frame you could easily reject until there is a first frame - you can't reject if you're waiting for a next frame which never comes, without making an arbitrary decision. This is especially true with remote video being sent by WebRTC, or creating a stream from a canvas, or from a video element. With canvas the stream only sends out a new frame when the content changes, which means if you 'miss the boat' on calling With video, if paused, there will be no new frames on the stream, so again, you may end up with a promise that never resolves or takes a long time. In both of those cases getting the next frame may not be the desired result, and would be confusing behavior to developers. A promise pending on grabbing a frame from a paused video will come out to be an unexpected frame if the video jumps ahead and resumes playing. This isn't just speculation, there's actually a developer bug for Chromium (which I just noticed today) which looks like it's running into this exact issue, and they're using new ReadableStream({
async start(controller) {
console.log("reader start");
},
async pull(controller) {
if (e.track.enabled === false && e.track.readyState === "ended") {
controller.close();
} else {
const frame = await imageCapture.grabFrame();
controller.enqueue(frame);
}
}
}) There's two potential issues in that code since I consider the wait for next frame behavior dangerous for reasons like this. Promises that may never resolve or reject are bad form and dangerous for developers. Implementations could detect things like the stream muting, or ending, and reject any unresolved promise, but the spec doesn't mention this, obviously, and the Chromium implementation doesn't do it. That behavior also has its own can of worms, as promises that seem flaky and reject unexpectedly will lead to bad code to deal with that. |
So does this have a workaround? I'm getting issues where sometimes grabFrame never returns. |
The current implementation of
ImageCapture.grabFrame
in Chromium will always wait for the next frame from the video stream, which was unexpected. The spec doesn't say anything about timing, but I think it should be updated to clarify. If the intention is indeed to wait for the next frame, then personally I thinkImageCapture.grabNextFrame
would more accurately convey the intention.In particular, without clarification in the spec, one implementation may implement it as next frame, one may implement it as current frame, and code written against the spec would act quite different between the two implementations, especially at low frame rates. At 2 FPS the first implementation would always take 500ms to resolve, while the second implementation may only take 5ms to resolve.
I think it would make the most sense to add language to the spec to say that
ImageCapture.grabFrame
should not wait for the next frame, unless this can be done without undue latency.Then I think #210 would offer a nice alternative for implementing the current Chromium behavior.
The text was updated successfully, but these errors were encountered: