Giter Club home page Giter Club logo

screenstream's Introduction

Notes

You might not need this anymore!

Recent Chrome versions (70 and up) introduced getDisplayMedia which essentially nullify this project and the need for an extension. You can simply acquire a screen stream with something like this:

navigator.mediaDevices.getDisplayMedia({ audio: false, video: true })
  .then(stream => video.srcObject = stream)
  .catch(handleError);

A working demo can be found here.

This project has been merged into https://github.com/GoogleChrome/webrtc in case something doesn't work have a look over there.

Introduction

This demo app shows you how to use a Chrome extension to access the desktopCapture API in your web-application.

(If you're writing a WebRTC app with screen sharing, and want to avoid sending users to chrome://flags)

Index

Setup

For the Demo to work, you will need to install the extension

  1. Go to chrome://extensions
  2. Check "Developer mode"
  3. Click "Load unpacked extension..."
  4. In the dialog choose the extension folder from the repository

You should see:

NOTE: your ID will differ, that's fine though.

How does it work?

Application (our web-app)

The index.html file contains a "Share screen" button, an empty <video> tag and loads some javascript (app.js). Think of these two files as our "application".

Extension

The extension consists of 4 files:

  1. background.js
  2. content-script.js
  3. manifest.json
  4. icon.png // not important

background.js

holds the main logic of the extension

or in our case, has access to the desktopCapture API. We get access to this API when we ask for permission in manifest.json:

"permissions": [
  "desktopCapture"
]

The background page ("background.js" - chrome generates the related html for us) runs in the extension process and is therefore isolated from our application environment. Meaning that we don't have a direct way to talk to our application. That's why we have the content-script.

1

content-script.js

If your extension needs to interact with web pages, then it needs a content script. A content script is some JavaScript that executes in the context of a page that's been loaded into the browser.

2

The content-script does not have access to variables or functions defined on our page, but it has access to the DOM.

Glueing it together

In order to call navigator.mediaDevices.getUserMedia in app.js, we need a chromeMediaSourceId which we get from our background page.

We have to pass messages through the chain below (left to right):

app.js            |        |content-script.js |      |background.js       | desktopCapture API
------------------|        |------------------|      |--------------------|
window.postMessage|------->|port.postMessage  |----->|port.onMessage------+
                  | window |                  | port |                 get|*streamID*
getUserMedia      |<------ |window.postMessage|<-----|port.postMessage<---+

Lets run through the chain:

When the user clicks on "Share Screen", we post a message to window, because...

window.postMessage({ type: 'SS_UI_REQUEST', text: 'start' }, '*');

the content-script has access to the DOM.

window.addEventListener('message', event => {
  if (event.data.type === 'SS_UI_REQUEST') {
    port.postMessage(event.data);
  }
}, false);

the content-script can also talk to the background page

var port = chrome.runtime.connect(chrome.runtime.id);

the background page is listening on that port,

port.onMessage.addListener(function (msg) {
  if(msg.type === 'SS_UI_REQUEST') {
    requestScreenSharing(port, msg);
  }

gets access to the stream, and sends a message containing the chromeMediaSourceId (streamID) back to the port (the content-script)

function requestScreenSharing(port, msg) {
  desktopMediaRequestId =
  chrome.desktopCapture.chooseDesktopMedia(data_sources, port.sender.tab,
  streamId => {
    msg.type = 'SS_DIALOG_SUCCESS';
    msg.streamId = streamId;
    port.postMessage(msg);
  });
}

the content-script posts it back to app.js

port.onMessage.addListener(msg => {
    window.postMessage(msg, '*');
});

where we finally call navigator.mediaDevices.getUserMedia with the streamID

if (event.data.type && (event.data.type === 'SS_DIALOG_SUCCESS')) {
  startScreenStreamFrom(event.data.streamId);
}

function startScreenStreamFrom(streamId) {
  navigator.mediaDevices
    .getUserMedia({
      audio: false,
      video: {
        mandatory: {
          chromeMediaSource: 'desktop',
          chromeMediaSourceId: streamId
        }
      }
    })
    .then(stream => {
      videoElement = document.getElementById('video');
      videoElement.srcObject = stream;
    })

Please note that the code examples in this README are edited for brevity, complete code is in the corresponding files.

Avoiding a reload after installation

This part was inspired by fippo from &yet.

When the extension is installed, the content-script will not be injected automatically by Chrome. The good news is that background.js will be exectued and we can use it to manually inject the content-script.js in our open pages (tabs):

The relevant code can be found in background.js and looks something like:

chrome.tabs.executeScript(currentTab.id, { file: 'js/content-script.js' }, () => {
  console.log('Injected content-script.');
});

Please note: For this to work, you have to adjust manifest.json by adding "tabs" to the permissions section.

Credits

Thanks to the guys and gals at &yet for talky.io

License

MIT

screenstream's People

Contributors

wpp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

screenstream's Issues

desktopcapture can not close?

i try stop capture by 'chrome.desktopCapture.cancelChooseDesktopMedia(desktopMediaRequestId)';
but seams not working both on mac and window; any solution?

extention doesn't work

Hi, when I try your index.html file, and put the folder to chrome extension. it's still doesn't work. by the way, is it necessary to use ruby as server side ? and ssl ?

Add a license

I'd love to use a fork of this in my project, but to protect myself and my company, I need to have a license attached to the source. Would you consider adding a license to this project, or simply attaching the license included on the webrtc project into which this was merged?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.