Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

WebRTC Screencasting in Chrome

5.00/5 (5 votes)
12 Apr 2018CPOL7 min read 21.2K   401  
Screencasting (demo screen, screensharing) already works in Google Chrome. The technology allows capturing a window of the browser itself as well as windows of other applicaitons. For example, you can capture Firefox running in a separate window.

image

Screencasting in Chrome

Screencasting (demo screen, screensharing) already works in Google Chrome. The technology allows capturing a window of the browser itself as well as windows of other applications. For example, you can capture Firefox running in a separate window. It's fine, but there is a security issue. In the Chrome browser screencasting is turned off. To enable screencasting, you need Chrome Desktop Capture API, and this article shows how to do this.

Screencasting Extension

To make screencasting work, the user should install your Chrome extension designed specifically for your website (domain). The very first run of screencasting requires the following actions from a user:

  1. The user opens the website and clicks Start screensharing.

    image

  2. The user is asked to add the extension for this action.

    image

The Chrome browser asks to add the extension in a standard box, where a user can add the extension in just one click. The box notifies the user that the extension can capture the screen.

Your Own Extension

The next step is creating an extension for your domain. Let's say your test domain is mysupercat.com. In this case, when creating the extension, you should put the domain name into the code. Besides, your domain (the website on this domain) must work via HTTPS. Correspondingly, your screencasting page should open something like this: https://mysupercat.com/screen-sharing.php.

The domain and HTTPS are, basically, all you need to create your own extension for screencasting. And you don't need to purchase SSL certificates. Self-signed certificates will do fine as long as your page does open via HTTPS, even if it's read and strikethrough:

image

Oh, and you need to spare five bucks. This is what you need to pay to become a Chrome developer community. Let's conclude. To start creating and testing your own extension, you need:

  • domain name
  • HTTPS hosting
  • 5 dollars on your credit card

Publishing the Extension

  1. Go to Chrome Developer Dashboard and pay 5 bucks for membership.

    image

  2. Prepare a ZIP containing files of the extension. To do this, download 2 files here. Edit the manifest.json file and put your own:
    • name
    • author
    • description
    • homepage_url

For example:

JSON
"Name" : "My cool screen sharing extension",
"Author" : "I am",
"Description" : "The extensions shares screens from my website",
"Homepage_url" : "https://mysupercat.com",
{
  "name" : "Flashphoner Screen Sharing",
  "author": "Flashphoner",
  "version" : "1.4",
  "manifest_version" : 2,
  "minimum_chrome_version": "34",
  "description" : "This Chrome extension is developed for 
                   http://flashphoner.com WCS Api to enable screen capture.",
  "homepage_url": "http://flashphoner.com",
  "background": {
    "scripts": ["background-script.js"],
    "persistent": false
  },
  "externally_connectable": {
    "matches": [
      "https://flashphoner.com/*",
      "https://*.flashphoner.com/*",
      "*://localhost/*",
      "*://127.0.0.1/*"
    ]
  },
  "icons": {
    "16": "logo16.png",
    "48": "logo48.png",
    "128": "logo128.png"
  },
  "permissions": [
    "desktopCapture"
  ],
  "web_accessible_resources": [
    "logo48.png"
  ]
}

Pack these files to a ZIP archive with all the icons and other pictures. You can read more about icons here. Additional images are discussed here. Then click Add new item.

image

Then, after reading the agreement, upload your ZIP archive.

image

After the archive is uploaded, verify everything and save.

image

Now, you only need to publish the extension from the Dashboard by clicking the Publish button.

image

The published extension looks like this in the Dashboard:

image

Done. The extension is packed, published and is available for installing to a browser.

In-line Install

Without in-line install, your users would have to open Chrome Store and install your extension from there. Not a big deal, but:

  • This is not very convenient to a user.
  • The user can get lost on the extension installation page and never get back to your page.

In-line installing of an extension is that nifty standard box that allows a user to skip visiting Chrome Store:

image

To configure in-line install, you should have a control over the domain and hosting specified in the manifest (manifest.json file). For example, if your domain is mysupercat.com, you will need to pass the standard verification procedure and confirm your ownership of this domain. To enable in-line install, enable the This item uses in-line install flag on the configuration page of the extension.

image

Then, you add your own website.

Search Console will open in a new window where you can pass verification.

The next step is to upload the identifier file to your hosting to confirm ownership of your domain / website.

image

Verification is successful.

The verified site is displayed in the list of websites available for this extension, and now you can use in-line installing for the extension.

image

Integrating Screencasting to the Web Page

The extension is read and configured for in-line installing. We only need to embed the code to invoke the extension to the HTML page and test it. Screencasting in Google Chrome uses WebRTC API. So, to finish this test, we need a WebRTC platform. As a server-side WebRTc platform, we will use Web Call Server and Web SDK - a set of API scripts for this server.

  1. Create an HTML page for screencasting screen-sharing.html. The page is 20 lines of code that looks as follows:
    HTML
    <p><title></p>
    <h1>Screen Sharing</h1>
    <p>Install Now</p>
    <h2>Capture</h2>
    <div id="localVideo" style="width: 320px; height: 240px"> </div>
    <h2>Preview</h2>
    <div id="remoteVideo" style="width: 320px; height: 240px"> </div>
    <p>Connect and share screen</p>
    <p id="status"> </p>
  2. Upload the screen-sharing.js script. We will examine it in detail later.
    HTML
    <script type="text/javascript" src="screen-sharing.js"></script>
  3. Specify where to look for the screencasting extension.
    HTML
    <link rel="chrome-webstore-item" 
     href="https://chrome.google.com/webstore/detail/nlbaajplpmleofphigmgaifhoikjmbkg">
  4. Add a button to execute installing of the extension.
    HTML
    <button id="installExtensionButton" onclick="installExtension()" type="button">Install Now</button>
  5. Add a div - the localVideo element that will display the captured screen locally.
    HTML
    <div id="localVideo" style="width: 320px; height: 240px"> </div>
  6. Add a div - the remoteVideo element that will act as a player displaying what was received from the server, that is, it displays the video stream captured to localVideo and sent to the server.
    HTML
    <div id="remoteVideo" style="width: 320px; height: 240px"> </div>
  7. The button that initiates screencasting and displays the status of the stream.
    HTML
    <button id="publishBtn" onclick="connectAndShareScreen()" type="button">Connect and share screen</button>
    <p id="status"> </p>

    Or page looks like this:

    image

  8. Create JavaScript code for screencasting screen-sharing.js. The code is available for download here. The code is a couple of screens with 5 main functions.
    JavaScript
    var SESSION_STATUS = Flashphoner.constants.SESSION_STATUS;
    var STREAM_STATUS = Flashphoner.constants.STREAM_STATUS;
    var localVideo;
    var remoteVideo;
    var extensionId = "nlbaajplpmleofphigmgaifhoikjmbkg";
    
    function init_page() {
       //init api
       try {
           Flashphoner.init({screenSharingExtensionId: extensionId});
       } catch (e) {
           //can't init
           return;
       }
    
       var interval = setInterval(function () {
           chrome.runtime.sendMessage(extensionId, {type: "isInstalled"}, function (response) {
               if (response) {
                   document.getElementById("installExtensionButton").disabled = true;
                   clearInterval(interval);
                   localVideo = document.getElementById("localVideo");
                   remoteVideo = document.getElementById("remoteVideo");
               } else {
                   document.getElementById("installExtensionButton").disabled = false;
               }
           });
       }, 500);
    }
    
    function connectAndShareScreen() {
       var url = "wss://wcs5-eu.flashphoner.com:8443";
       console.log("Create new session with url " + url);
       Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function (session) {
           //session connected, start streaming
           startStreaming(session);
       }).on(SESSION_STATUS.DISCONNECTED, function () {
           setStatus(SESSION_STATUS.DISCONNECTED);
       }).on(SESSION_STATUS.FAILED, function () {
           setStatus(SESSION_STATUS.FAILED);
       });
    }
    
    function startStreaming(session) {
       var streamName = "test123";
       var constraints = {
           video: {
               width: 320,
               height: 240,
               frameRate: 10,
               type: "screen"
           }
       };
       session.createStream({
           name: streamName,
           display: localVideo,
           constraints: constraints
       }).on(STREAM_STATUS.PUBLISHING, function (publishStream) {
           setStatus(STREAM_STATUS.PUBLISHING);
           //play preview
           session.createStream({
               name: streamName,
               display: remoteVideo
           }).on(STREAM_STATUS.PLAYING, function (previewStream) {
               //enable stop button
           }).on(STREAM_STATUS.STOPPED, function () {
               publishStream.stop();
           }).on(STREAM_STATUS.FAILED, function () {
               //preview failed, stop publishStream
               if (publishStream.status() == STREAM_STATUS.PUBLISHING) {
                   setStatus(STREAM_STATUS.FAILED);
                   publishStream.stop();
               }
           }).play();
       }).on(STREAM_STATUS.UNPUBLISHED, function () {
           setStatus(STREAM_STATUS.UNPUBLISHED);
           //enable start button
       }).on(STREAM_STATUS.FAILED, function () {
           setStatus(STREAM_STATUS.FAILED);
       }).publish();
    }
    
    //show connection or local stream status
    function setStatus(status) {
       var statusField = document.getElementById("status");
       statusField.innerHTML = status;
    }
    
    //install extension
    function installExtension() {
       chrome.webstore.install();
    }

Let's examine this code in detail.

  1. First, we declare several variables: statuses, localVideo and remoteVideo elements, and extensionId that contains the unique id of the screencasting extension.
    JavaScript
    var SESSION_STATUS = Flashphoner.constants.SESSION_STATUS;
    var STREAM_STATUS = Flashphoner.constants.STREAM_STATUS;
    var localVideo;
    var remoteVideo;
    var extensionId = "nlbaajplpmleofphigmgaifhoikjmbkg"
  2. Then, we send extensionId to the Flashphoner API, as a result the API knows which extension is used for screencasting.
    JavaScript
    Flashphoner.init({screenSharingExtensionId: extensionId});
  3. Periodically, we check Chrome and see if the extension is installed. If the extension is installed, we don't need the Install extension button any more and we can hide it.
    JavaScript
    chrome.runtime.sendMessage(extensionId, {type: "isInstalled"}, function (response) {...}
  4. The connectAndShareScreen function establishes connection to the server, and as soon it does (ESTABLISHED), it begins capturing and sending the video stream by delegating control to the startStreaming function.
    JavaScript
    function connectAndShareScreen() {
       var url = "wss://wcs5-eu.flashphoner.com:8443";
       console.log("Create new session with url " + url);
       Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function (session) {
           //session connected, start streaming
           startStreaming(session);
       }).on(SESSION_STATUS.DISCONNECTED, function () {
           setStatus(SESSION_STATUS.DISCONNECTED);
       }).on(SESSION_STATUS.FAILED, function () {
           setStatus(SESSION_STATUS.FAILED);
       });
    }
  5. Before screencasting starts, we set such stream parameters as video resolution and FPS.
    JavaScript
    var constraints = {
           video: {
               width: 320,
               height: 240,
               frameRate: 10,
               type: "screen"
           }
       };
  6. Then we create the stream itself and invoke the publish() method. Please note, the stream is named test123.
    JavaScript
    session.createStream({
           name: streamName,
           display: localVideo,
           constraints: constraints
       }).publish();
  7. After the test123 stream is successfully sent to the server, the execution is transferred to the handler of the PUBLISHING event.
    JavaScript
    on(STREAM_STATUS.PUBLISHING, function (publishStream) {...}
  8. Now we only need to play the stream in the adjacent div remoteVideo. To do this, we invoke the play() function.
    JavaScript
    session.createStream({
               name: streamName,
               display: remoteVideo
           }).play();

The page and the script are ready for testing.

Preparing to Test

As a result, we have the following files:

  • screen-sharing.html
  • screen-sharing.js
  • flashphoner.js

flashphoner.js is included to Web SDK build. The latest build is available for download here. In addition to HTML and JS files, we need the rebroadcasting server that accepts a video stream and broadcasts it to all others (in our case - back to the same page).

Testing of screencasting follows the below diagram:

image

The same way, we can broadcast the screencasting stream to multiple connected users:

image

Testing Screencasting in Chrome

  1. Open the screen-sharing.html page via HTTPS in Google Chrome:

    image

  2. Click the Install Now button to add the extension using in-line installing:

    image

  3. Click Add extension and start screencasting by clicking Connect and share screen. Chrome asks to choose what to capture. This can be a tab or a window of Chrome itself, or another application.

    image

  4. Click Share and end up enjoying the final result. The screen is captured, sent to the server via WebRTC and returns back when the Preview block displays it.

    image

Conclusion

Therefore, we successfully tested screencasting using a simple test page screen-sharing.html in the Google Chrome browser. The test page contains the extension for screencasting that we published in Chrome Store and installed in one click without opening the Store.

During testing, the page operated via the HTTPS protocol and have sent and received video via Web Call Server - a WebRTC media server to broadcast streaming video.

To integrate screencasting to the HTML page, we used the flashphoner.js script that is a part of the Web SDK build for the WCS server.

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)