1

I want to start a screen share in my main tab by calling getDisplayMedia, and then clone it to another popup window which I open from my app (using window.open), effectively showing the screen capture twice, in parallel.

According to this thread, this snippet should work - but it doesn't:

async function startCapture() {
  return await navigator.mediaDevices.getDisplayMedia();
}

function openPopup() {
  startCapture().then((stream) => {
    let video = document.getElementById("source");
    video.srcObject = stream;
    let popUpWindow = window.open("", "_blank", "x=y");
    let videoElem = document.createElement("video");
    videoElem.autoplay = true;
    let remoteVideo = popUpWindow.document.body.appendChild(videoElem);
    remoteVideo.srcObject = stream;
  });
}

What am I missing?

amiregelz
  • 1,833
  • 7
  • 25
  • 46

2 Answers2

2

No, not directly, because a MediaStreamTrack is not transferable. It's tied to the document it's created in.

A workaround would be to establish an RTCPeerConnection between the two tabs and transmit the screen-capture track from the tab that has it to the tab that doesn't. This should be relatively performant since the bits never leave your network card.

You can use a BroadcastChannel for the necessary signaling to establish such a connection, or do tricks with localStorage to do the signaling like I do here using a camera, but it works with any source (open in two tabs first, then click the Call button in one).

A limitation of this workaround is that if you close the original tab then you lose both tracks.

jib
  • 40,579
  • 17
  • 100
  • 158
  • 1
    Not sure it applies to OP but with the same limitation (if original doc dies the stream dies) with arguably less coding, they can also probably pass it to the other tab through WindowProxy if that tab was `open`ed. And nitpick, but BCChannels don't do transfer anyway. – Kaiido Jan 01 '21 at 00:50
  • @jib @Kaiido I stumbled upon [this thread](https://github.com/webrtcHacks/adapter/issues/636). Since both windows are same origin, is it possible to use the mechanism described [here](https://medium.com/hackernoon/using-a-react-16-portal-to-do-something-cool-2a2d627b0202) and use the same `ref` or set the `srcObject` of both the original and the copy video elements to the same stream in order to achieve this? – amiregelz Jan 01 '21 at 16:58
  • @jib Do you it's possible? which approach is better? – amiregelz Jan 01 '21 at 22:00
  • @amiregelz you'd need the second tab to be `open`ed by the first document, i.e using `window.open()`. If it has been created by an other mean (e.g the user typed the address in the address bar), then you won't be able to make the two windows communicate directly enough so they can pass the track or stream. – Kaiido Jan 02 '21 at 06:12
  • @Kaiido That's exactly how I open it - with `window.open()` - but I still can't manage to set the stream to the video object of the popup window I open. I'm doing this in React. Do you have an example of how to do it? – amiregelz Jan 02 '21 at 09:51
  • @amiregelz not a react one no, but in bare Web API see [this answer](https://stackoverflow.com/questions/65227332/continue-recording-with-getdisplaymedia-on-page-after-reload/65230020#65230020) to a related question – Kaiido Jan 02 '21 at 11:40
  • @Kaiido Also tried following [this](https://stackoverflow.com/questions/50237238/how-to-pass-canvas-stream-to-another-window-since-createobjecturl-is-deprecated) (just with opposite direction to clone the video to the popup) and it also didn't work. – amiregelz Jan 02 '21 at 18:40
  • @Kaiido According to [this](https://github.com/webrtcHacks/adapter/issues/636#issuecomment-388619724) thread, [this CodePen should work](https://codepen.io/amiregelz/pen/OJRvoPp?editors=1010) - but it doesn't. What am I missing?? – amiregelz Jan 03 '21 at 23:49
  • @amiregelz this codepen works fine on Chrome (Firefox won't allow the capture request to be made from that iframe). But you are never asking the video in the popup to start playing, so you need to right-click -> show controls -> scroll down to the controls and click play. – Kaiido Jan 04 '21 at 00:25
  • @Kaiido I want it to autoplay, can I do it with code? – amiregelz Jan 04 '21 at 09:06
  • 1
    Just add the `muted` attribute. – Kaiido Jan 04 '21 at 09:07
  • @Kaiido Thank you!!! I never thought this is the reason it's not working. I really appreciate your help :) – amiregelz Jan 04 '21 at 10:18
1

As @Kaiido mentioned in the comments, the issue was I needed to add the muted attribute to the destination video for it to play when automatically when duplicating the stream.

More info here: https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide

Autoplay availability
As a general rule, you can assume that media will be allowed to autoplay only if at least one of the following is true:

  • The audio is muted or its volume is set to 0
  • The user has interacted with the site (by clicking, tapping, pressing keys, etc.)
  • If the site has been whitelisted; this may happen either automatically if the browser determines that the user engages with media frequently, or manually through preferences or other user interface features
  • If the autoplay feature policy is used to grant autoplay support to a and its document. Otherwise, the playback will likely be blocked. The exact situations that result in blocking, and the specifics of how sites become whitelisted vary from browser to browser, but the above are good guidelines to go by.
amiregelz
  • 1,833
  • 7
  • 25
  • 46