Skip to content
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

feat: add desktopCapturer.getMediaSourceIdForWebContents() to get stream source id from web contents #22701

Merged
merged 2 commits into from
May 26, 2020

Conversation

Volune
Copy link
Contributor

@Volune Volune commented Mar 16, 2020

Description of Change

New feature: add desktopCapturer.getWebContentsStream() to provide a way to get a MediaStream from a WebContents using getUserMedia.

An example code is provided in docs/api/desktop-capturer.md

This should be enough to resolve #4776

Checklist

Release Notes

Notes: Added desktopCapturer.getMediaSourceIdForWebContents(), can be used with getUserMedia to get a stream for a WebContent.

Comments

Feedbacks on the API (especially on functions and arguments naming) are welcomed

These two tests failed locally. Since they don't seem related with the code changes, I assume it's caused by the test environment.

not ok 746 Notification module (dbus) Notification module using org.freedesktop.Notifications "before all" hook
  Error: Timeout of 30000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/mnt/c/dev/github.volune/electron-gn/src/electron/spec-main/api-notification-dbus-spec.ts)
      at listOnTimeout (internal/timers.js:549:17)
      at processTimers (internal/timers.js:492:7)


not ok 324 BrowserWindow module "webPreferences" option "sandbox" option exposes "exit" event to preload script
  Error: Timeout of 30000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/mnt/c/dev/github.volune/electron-gn/src/electron/spec-main/api-browser-window-spec.ts)
      at listOnTimeout (internal/timers.js:549:17)
      at processTimers (internal/timers.js:492:7)

@welcome
Copy link

welcome bot commented Mar 16, 2020

💖 Thanks for opening this pull request! 💖

We use semantic commit messages to streamline the release process. Before your pull request can be merged, you should update your pull request title to start with a semantic prefix.

Examples of commit messages with semantic prefixes:

  • fix: don't overwrite prevent_default if default wasn't prevented
  • feat: add app.isPackaged() method
  • docs: app.isDefaultProtocolClient is now available on Linux

Things that will help get your PR across the finish line:

  • Follow the JavaScript, C++, and Python coding style.
  • Run npm run lint locally to catch formatting errors earlier.
  • Document any user-facing changes you've made following the documentation styleguide.
  • Include tests when adding/changing behavior.
  • Include screenshots and animated GIFs whenever possible.

We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can.

@electron-cation electron-cation bot added new-pr 🌱 PR opened in the last 24 hours and removed new-pr 🌱 PR opened in the last 24 hours labels Mar 16, 2020
docs/api/desktop-capturer.md Outdated Show resolved Hide resolved
}
}

VLOG(0) << "DEVICES " << devices.size();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed that whole file change, it was actually an experiment to use getDisplayMedia and should not have been committed.

@nornagon
Copy link
Member

cc @electron/wg-api

docs/api/structures/web-contents-stream-result.md Outdated Show resolved Hide resolved
@@ -94,6 +138,13 @@ Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`Desktop
**Note** Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher,
which can detected by [`systemPreferences.getMediaAccessStatus`].

### `desktopCapturer.getWebContentsStream(options)`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe getWebContentsStreamInfo? It's not really a stream yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right

At some point I was considering returning a DesktopCapturerSource, but:

  • the description of DesktopCapturerSource.id would not match this case (not "screen:XX" format, that's the "mediaId")
  • don't know if it should return the "mediaId" in the display_id field or not, since that's different format
  • name, thumbnail, appIcon are not provided
  • At this point, the returned id is expected to be used, otherwise it will leak inside DesktopStreamsRegistry. This behavior is not similar to screen/application sources.

I don't know if getWebContentsSource would be a good name or more confusing.

@loc
Copy link
Contributor

loc commented Mar 26, 2020

@Volune what do you think about moving this to be on WebContents? I think contents.getCaptureMediaId() or something like that would provide better ergonomics. Otherwise I think this is looking pretty good.

@jpmcgrath
Copy link

@MarshallOfSound just wondering if this is close to getting approved/merged? I'd love to be able to try of this feature. It would be great to know If this is just around the corner as I could abort my n00bish attempt to build electron from this branch :-)

Apologies if this question sounds demanding/entitled, or is not in keeping with electron community expectations/conventions. Thanks everyone for your efforts with this great framework!

@Volune
Copy link
Contributor Author

Volune commented Apr 25, 2020

@Volune what do you think about moving this to be on WebContents? I think contents.getCaptureMediaId() or something like that would provide better ergonomics. Otherwise I think this is looking pretty good.

@loc The issue I have with that is I need to know the requesting WebContents in order to call content::DesktopStreamsRegistry::GetInstance()->RegisterStream. I don't know how to do that from WebContents. Also a benefit of desktopCapturer is it's available in rendering thread, so there always is a "request_web_contents"
One solution could be to split into WebContents.getMediaId() and deskopCapturer.registerWebContentsStream()
Maybe another solution would be to patch Blink to stop verifying that the stream has been registered, which could make sense for Electron.

(I feel like I already replied that, I guess I forgot to submit my response ☹️ )


just wondering if this is close to getting approved/merged?

The API is not stabilized, so probably not. I will try to update the PR (rebase on top of master) during next week.

@gamerz1990
Copy link

I am in need for this feature hope it will 🙏 done soon 😊

@loc
Copy link
Contributor

loc commented May 19, 2020

Sorry for dropping the ball on this @Volune. I spent some time today thinking about how we could make this better, but couldn't come up with anything that didn't involve significant patching. In the future, I'll try to find an opportunity to improve Chrome's deference to embedders on the issue of screen capture.

One last minor suggestion. I've gone back and forth, but I think I'd prefer to change the signature from:

desktopCapturer.getWebContentsStream({ webContentsId: number }): Promise<{ id: string, mediaId: string}>

to

desktopCapturer.getMediaSourceIdForWebContents(webContentsId: number): Promise<string>

The name is more clear about what it's returning and, though it's reasonable to want to use options objects here to make this more extensible, I think that is pretty unlikely and comes at the cost of a stranger API. Also, since the mediaId is not useful to the consumer, we can safely get rid of it.

Also, we should add a note in the docs that this media source ID is only valid for 10 seconds after it's called.

WDYT?

@Volune
Copy link
Contributor Author

Volune commented May 20, 2020

@loc ok for me

I rebased on top of master, and made the API changes. Tests passed on my Windows, and a small demo app worked too.

@@ -0,0 +1,6 @@
# WebContentsStreamResult Object
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can get rid of this object now.

* `webContentsId` number - Id of the WebContents to get stream of

Returns `Promise<string>` - Resolves with the identifier of a WebContents stream, this identifier can be
used with [`navigator.mediaDevices.getUserMedia`].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this extra indent be removed?

@@ -37,3 +37,7 @@ export async function getSources (options: Electron.SourcesOptions) {

return deserialize(sources);
}

export function getMediaSourceIdForWebContents (webContentsId: number) {
return ipcRendererInternal.invoke<Electron.WebContentsStreamResult>('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_MEDIA_SOURCE_ID_FOR_WEB_CONTENTS', webContentsId, getCurrentStack());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return ipcRendererInternal.invoke<Electron.WebContentsStreamResult>('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_MEDIA_SOURCE_ID_FOR_WEB_CONTENTS', webContentsId, getCurrentStack());
return ipcRendererInternal.invoke<string>('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_MEDIA_SOURCE_ID_FOR_WEB_CONTENTS', webContentsId, getCurrentStack());

@Volune Volune changed the title feat: add desktopCapturer.getWebContentsStream() to get media stream id from web contents feat: add desktopCapturer.getMediaSourceIdForWebContents() to get stream source id from web contents May 21, 2020
@Volune
Copy link
Contributor Author

Volune commented May 21, 2020

  • updated PR (sorry should have better reviewed last changes)
  • CI test issue on mac seems unrelated to this PR (but I can't test on mac)
  • Do I need to do something about release notes?

@jkleinsc jkleinsc requested a review from loc May 21, 2020 14:45
@jkleinsc
Copy link
Contributor

@Volune the failing mac tests were flakes that disappeared on a re-run. In regards to the release notes, I updated your PR description to have a release note that matches the feature. The release-notes status being marked as pending is an issue unrelated to this PR.

@welcome
Copy link

welcome bot commented May 26, 2020

Congrats on merging your first pull request! 🎉🎉🎉

@release-clerk
Copy link

release-clerk bot commented May 26, 2020

Release Notes Persisted

Added desktopCapturer.getMediaSourceIdForWebContents(), can be used with getUserMedia to get a stream for a WebContent.

codebytere pushed a commit that referenced this pull request May 27, 2020
…eam source id from web contents (#22701)

* feat: add desktopCapturer.getMediaSourceIdForWebContents() to get stream source id from web contents

* Cleanup from #22701 PR comments
codebytere pushed a commit that referenced this pull request May 27, 2020
…eam source id from web contents (#22701)

* feat: add desktopCapturer.getMediaSourceIdForWebContents() to get stream source id from web contents

* Cleanup from #22701 PR comments
@yozzh
Copy link

yozzh commented Jun 9, 2020

Hello, @Volune. I have a question about this feature. Is it possible to add alpha channel (transparency) when capturing tab? It will be very useful for third party widgets (ex. stickers)

nornagon added a commit that referenced this pull request Sep 10, 2020
… get stream source id from web contents (#22701)"

This reverts commit 204f001.
nornagon added a commit that referenced this pull request Sep 11, 2020
… get stream source id from web contents (#22701)"

This reverts commit 204f001.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Capture media for specified WebContents
8 participants