Write Screen Sharing Application for Your Own WebSite

Do you want to write multi-user screen sharing application for your own website?

Note: This tutorial uses WebRTC for multi-user screen sharing.

First step, download all codes from this directory: github/Chrome-Extensions/desktopCapture

Second step, modify manifest.json file line 17, and replace with either localhost or your real domain name:

{
    "content_scripts": [ {
       "js": [ "content-script.js" ],
       "all_frames": true,
       "run_at": "document_end",
       "matches": ["https://your-domain.com/*"]
    }]
}

Fourth step, either max a zip and deploy new chrome extension to Google App Store, or install directly using "chrome://extensions" page.


Fifth step, download ONE_to_MANY screen sharing demo from this page: RTCMultiConnection/demos/Screen-Sharing.html


Sixth step, modify a few lines in the above demo:

Search for these two lines:

<script src="/dist/RTCMultiConnection.min.js"></script>
<script src="/socket.io/socket.io.js"></script>

Replace above two lines with:

<script src="https://rtcmulticonnection.herokuapp.com//dist/RTCMultiConnection.min.js"></script>
<script src="https://rtcmulticonnection.herokuapp.com//socket.io/socket.io.js"></script>

Now search for this line:

connection.socketURL = '/';

Replace above line with:

connection.socketURL = 'https://rtcmulticonnection.herokuapp.com:443/';

Now you are done.

Seventh and the last step, upload above HTML file on any HTTPs domain.

You can try on LocalHost as well.

Non-LocalHost domains requires HTTPs.

You can upload to Google Drive, DropBox or any free hosting website that supports HTTPs e.g. appspot.com.


How to test screen sharing?

First person shares his screen and about 10 people can join/see/view his screen.

You can open unlimited parallel rooms.

Maximum number of people who can view single screen is 14. We do not support more than 14 viewers/receivers.

There is a separate demo that allows us share screen over more than 14 users: https://rtcmulticonnection.herokuapp.com/demos/Scalable-Screen-Broadcast.html

RecordRTC and Upload to PHP Server

This tutorial explains how to record videos and microphones using RecordRTC; and upload recorded data to your PHP server.

First step, write a simple RecordRTC video recording application.

Hope you didn't miss this youtube tutorial: https://www.youtube.com/watch?v=YrLzTgdJ-Kg

Here is a LIVE jsFiddle demo: https://jsfiddle.net/e32jwtn5/

Source codes for the demo:

<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdn.WebRTC-Experiment.com/RecordRTC.js"></script>
    </head>

    <body>
        <video id="your-video-id" controls="" autoplay=""></video>

        <script type="text/javascript">
            // capture camera and/or microphone
            navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(function(camera) {

                // preview camera during recording
                document.getElementById('your-video-id').muted = true;
                document.getElementById('your-video-id').srcObject = camera;

                // recording configuration/hints/parameters
                var recordingHints = {
                    type: 'video'
                };

                // initiating the recorder
                var recorder = RecordRTC(camera, recordingHints);

                // starting recording here
                recorder.startRecording();

                // auto stop recording after 5 seconds
                var milliSeconds = 5 * 1000;
                setTimeout(function() {

                    // stop recording
                    recorder.stopRecording(function() {
                        
                        // get recorded blob
                        var blob = recorder.getBlob();

                        // open recorded blob in a new window
                        window.open( URL.createObjectURL(blob) );

                        // release camera
                        document.getElementById('your-video-id').srcObject = null;
                        camera.getTracks().forEach(function(track) {
                            track.stop();
                        });

                        // you can preview recorded data on this page as well
                        document.getElementById('your-video-id').src = URL.createObjectURL(blob);

                    });

                }, milliSeconds);
            });
        </script>
    </body>
</html>

Second step, write a PHP file. Lets name it "save.php".

<?php
// upload directory
$filePath = 'uploads/' . $_POST['video-filename'];

// path to ~/tmp directory
$tempName = $_FILES['video-blob']['tmp_name'];

// move file from ~/tmp to "uploads" directory
if (!move_uploaded_file($tempName, $filePath)) {
    // failure report
    echo 'Problem saving file: '.$tempName;
    die();
}

// success report
echo 'success';
?>

Third & last step, upload recorded blob to PHP.

var formData = new FormData();

// recorded data
formData.append('video-blob', recordedBlob);

// file name
formData.append('video-filename', recordedBlob.name);

// upload using jQuery
$.ajax({
    url: 'save.php', // your server URL
    data: formData,
    cache: false,
    contentType: false,
    processData: false,
    type: 'POST',
    success: function(response) {
        if (response === 'success') {
            alert('successfully uploaded recorded blob');
        } else {
            alert(response);
        }
    }
});

Here is a complete demo, uploading to PHP using jQuery:


<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdn.WebRTC-Experiment.com/RecordRTC.js"></script>
        <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
        <style>
            video {
              max-width: 100%;
              border: 5px solid yellow;
              border-radius: 9px;
            }
            body {
              background: black;
            }
            h1 {
              color: yellow;
            }
        </style>
    </head>

    <body>
        <h1 id="header">RecordRTC Upload to PHP</h1>
        <video id="your-video-id" controls="" autoplay=""></video>

        <script type="text/javascript">
            // capture camera and/or microphone
            navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(function(camera) {

                // preview camera during recording
                document.getElementById('your-video-id').muted = true;
                document.getElementById('your-video-id').srcObject = camera;

                // recording configuration/hints/parameters
                var recordingHints = {
                    type: 'video'
                };

                // initiating the recorder
                var recorder = RecordRTC(camera, recordingHints);

                // starting recording here
                recorder.startRecording();

                // auto stop recording after 5 seconds
                var milliSeconds = 5 * 1000;
                setTimeout(function() {

                    // stop recording
                    recorder.stopRecording(function() {
                        
                        // get recorded blob
                        var blob = recorder.getBlob();

                        // generating a random file name
                        var fileName = getFileName('webm');

                        // we need to upload "File" --- not "Blob"
                        var fileObject = new File([blob], fileName, {
                            type: 'video/webm'
                        });

                        var formData = new FormData();

                        // recorded data
                        formData.append('video-blob', fileObject);

                        // file name
                        formData.append('video-filename', fileObject.name);

                        document.getElementById('header').innerHTML = 'Uploading to PHP using jQuery.... file size: (' +  bytesToSize(fileObject.size) + ')';

                        // upload using jQuery
                        $.ajax({
                            url: 'https://webrtcweb.com/RecordRTC/', // replace with your own server URL
                            data: formData,
                            cache: false,
                            contentType: false,
                            processData: false,
                            type: 'POST',
                            success: function(response) {
                                if (response === 'success') {
                                    alert('successfully uploaded recorded blob');

                                    // file path on server
                                    var fileDownloadURL = 'https://webrtcweb.com/RecordRTC/uploads/' + fileObject.name;

                                    // preview the uploaded file URL
                                    document.getElementById('header').innerHTML = '<a href="' + fileDownloadURL + '" target="_blank">' + fileDownloadURL + '</a>';

                                    // preview uploaded file in a VIDEO element
                                    document.getElementById('your-video-id').src = fileDownloadURL;

                                    // open uploaded file in a new tab
                                    window.open(fileDownloadURL);
                                } else {
                                    alert(response); // error/failure
                                }
                            }
                        });

                        // release camera
                        document.getElementById('your-video-id').srcObject = null;
                        camera.getTracks().forEach(function(track) {
                            track.stop();
                        });

                    });

                }, milliSeconds);
            });

            // this function is used to generate random file name
            function getFileName(fileExtension) {
                var d = new Date();
                var year = d.getUTCFullYear();
                var month = d.getUTCMonth();
                var date = d.getUTCDate();
                return 'RecordRTC-' + year + month + date + '-' + getRandomString() + '.' + fileExtension;
            }

            function getRandomString() {
                if (window.crypto && window.crypto.getRandomValues && navigator.userAgent.indexOf('Safari') === -1) {
                    var a = window.crypto.getRandomValues(new Uint32Array(3)),
                        token = '';
                    for (var i = 0, l = a.length; i < l; i++) {
                        token += a[i].toString(36);
                    }
                    return token;
                } else {
                    return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, '');
                }
            }
        </script>
    </body>
</html>

Here is a demo uploading to PHP using simple JavaScript (no-jQurery):


<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdn.WebRTC-Experiment.com/RecordRTC.js"></script>
        <style>
            video {
              max-width: 100%;
              border: 5px solid yellow;
              border-radius: 9px;
            }
            body {
              background: black;
            }
            h1 {
              color: yellow;
            }
        </style>
    </head>

    <body>
        <h1 id="header">RecordRTC Upload to PHP</h1>
        <video id="your-video-id" controls="" autoplay=""></video>

        <script type="text/javascript">
            // capture camera and/or microphone
            navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(function(camera) {

                // preview camera during recording
                document.getElementById('your-video-id').muted = true;
                document.getElementById('your-video-id').srcObject = camera;

                // recording configuration/hints/parameters
                var recordingHints = {
                    type: 'video'
                };

                // initiating the recorder
                var recorder = RecordRTC(camera, recordingHints);

                // starting recording here
                recorder.startRecording();

                // auto stop recording after 5 seconds
                var milliSeconds = 5 * 1000;
                setTimeout(function() {

                    // stop recording
                    recorder.stopRecording(function() {
                        
                        // get recorded blob
                        var blob = recorder.getBlob();

                        // generating a random file name
                        var fileName = getFileName('webm');

                        // we need to upload "File" --- not "Blob"
                        var fileObject = new File([blob], fileName, {
                            type: 'video/webm'
                        });

                        uploadToPHPServer(fileObject, function(response, fileDownloadURL) {
                            if(response !== 'ended') {
                                document.getElementById('header').innerHTML = response; // upload progress
                                return;
                            }

                            document.getElementById('header').innerHTML = '<a href="' + fileDownloadURL + '" target="_blank">' + fileDownloadURL + '</a>';

                            alert('Successfully uploaded recorded blob.');

                            // preview uploaded file
                            document.getElementById('your-video-id').src = fileDownloadURL;

                            // open uploaded file in a new tab
                            window.open(fileDownloadURL);
                        });

                        // release camera
                        document.getElementById('your-video-id').srcObject = null;
                        camera.getTracks().forEach(function(track) {
                            track.stop();
                        });

                    });

                }, milliSeconds);
            });

            function uploadToPHPServer(blob, callback) {
                // create FormData
                var formData = new FormData();
                formData.append('video-filename', blob.name);
                formData.append('video-blob', blob);
                callback('Uploading recorded-file to server.');
                makeXMLHttpRequest('https://webrtcweb.com/RecordRTC/', formData, function(progress) {
                    if (progress !== 'upload-ended') {
                        callback(progress);
                        return;
                    }
                    var initialURL = 'https://webrtcweb.com/RecordRTC/uploads/' + blob.name;
                    callback('ended', initialURL);
                });
            }

            function makeXMLHttpRequest(url, data, callback) {
                var request = new XMLHttpRequest();
                request.onreadystatechange = function() {
                    if (request.readyState == 4 && request.status == 200) {
                        if (request.responseText === 'success') {
                            callback('upload-ended');
                            return;
                        }
                        alert(request.responseText);
                        return;
                    }
                };
                request.upload.onloadstart = function() {
                    callback('PHP upload started...');
                };
                request.upload.onprogress = function(event) {
                    callback('PHP upload Progress ' + Math.round(event.loaded / event.total * 100) + "%");
                };
                request.upload.onload = function() {
                    callback('progress-about-to-end');
                };
                request.upload.onload = function() {
                    callback('PHP upload ended. Getting file URL.');
                };
                request.upload.onerror = function(error) {
                    callback('PHP upload failed.');
                };
                request.upload.onabort = function(error) {
                    callback('PHP upload aborted.');
                };
                request.open('POST', url);
                request.send(data);
            }

            // this function is used to generate random file name
            function getFileName(fileExtension) {
                var d = new Date();
                var year = d.getUTCFullYear();
                var month = d.getUTCMonth();
                var date = d.getUTCDate();
                return 'RecordRTC-' + year + month + date + '-' + getRandomString() + '.' + fileExtension;
            }

            function getRandomString() {
                if (window.crypto && window.crypto.getRandomValues && navigator.userAgent.indexOf('Safari') === -1) {
                    var a = window.crypto.getRandomValues(new Uint32Array(3)),
                        token = '';
                    for (var i = 0, l = a.length; i < l; i++) {
                        token += a[i].toString(36);
                    }
                    return token;
                } else {
                    return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, '');
                }
            }
        </script>
    </body>
</html>

Want to use up-to-dated PHP file uploading code? Download this file:

https://github.com/muaz-khan/RecordRTC/blob/master/RecordRTC-to-PHP/save.php

Having PHP upload issues on your own server? Please check this wiki:

https://github.com/muaz-khan/RecordRTC/wiki/PHP-Upload-Issues

Hints for PHP upload issues:
  • You need to enable read-write access for "uploads" directory
  • You need to allow "save.php" file to move uploaded files from ~/tmp directory to your "./uploads" directory.
  • You need to set "post_max_size" to at least 100 MB
  • You need to set "upload_max_filesize" to at least 100 MB
  • You need to set "max_input_time" to at least 10800 (or at least 2-3 minutes)
  • For detailed information, please check the wiki page

How PHP saves the recorded blob?


First step, PHP reads "video-filename" HTTP_POST parameter. This parameter helps us set uploaded file name.

Second step, PHP checks for "video-blob" HTTP_POST (i.e. $_FILES) parameter. This parameter allows us get uploaded file data.

Third step, "video-blob" parameter has a nested "tmp_name" paremter i.e.

$tmp_name = $_FILES['video-blob']['tmp_name'];

"tmp_name" parameter helps us locate the uploaded file on ~/tmp directory.

Which means that file is already uploaded to ~/tmp directory. We simply need to move file from ~/tmp to our custom location.

That's why we use "move_upload_file" method.

Fourth and last step, use "move_upload_file" method to move uploaded file from ~/tmp to "./uploads" directory.

"move_upload_file" takes two parameters. First parameter is ~/tmp/fileName.webm and second parameter is "./uploads/fileName.webm".

This method fails in following cases:

  • File was not uploaded to ~/tmp directory; reason: max_upload_filesize or upload_timeout issues.
  • "./uploads" directory doesn't allows "save.php" file to move file. i.e. you did not set read-write privileges for "./uploads" directory.

Here is how to set read-write privileges for "./uploads" directory (using PHP):

<?php
// Read and write for owner, nothing for everybody else
chmod("./uploads", 0600);

// Read and write for owner, read for everybody else
chmod("./uploads", 0644);

// Everything for owner, read and execute for others
chmod("./uploads", 0755);

// Everything for owner, read and execute for owner's group
chmod("./uploads", 0750);
?>

However BASH based privileges are preferred/recommended:

[sudo] chmod 755 ./uploads
[sudo] chown -R www-data:www-data ./uploads

You can use "apache:apache" if "www-data:www-data" doesn't works above.

Searching for RecordRTC simple demos? Please check this directory:

https://github.com/muaz-khan/RecordRTC/tree/master/simple-demos

Have issues/bugs/questions, please report here: https://github.com/muaz-khan/RecordRTC/issues/new