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