/video-upload-s3

Live streaming upload to S3 by javascript.

Primary LanguageHTML

Live streaming upload to S3 by javascript.

Just file upload with form element just-upload.html

File upload after streaming in index.html

The user will need to grant access to the Camera and Microphone using the getUserMedia API. Using this stream, RecordRTC will be able to start the video recording.We will use following libraries.

<script src="https://www.WebRTC-Experiment.com/RecordRTC.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/RecordRTC/5.5.5/RecordRTC.js"></script>

The following example shows how to implement a basic start/stop recorder using RecordRTC :

	<button id="btn-start-recording">
            Start Recording
        </button>
		
        <button disabled="disabled" id="btn-stop-recording">
            Stop Recording
        </button>
		
        <button id="cancel-button">
            Cancel Upload
        </button>
document.getElementById('btn-start-recording').addEventListener("click", function(){
        // Disable start recording button
        this.disabled = true;

        // Request access to the media devices
        navigator.mediaDevices.getUserMedia({
            audio: true, 
            video: true
        }).then(function(stream) {
            // Display a live preview on the video element of the page
            setSrcObject(stream, video);

            // Start to display the preview on the video element
            // and mute the video to disable the echo issue !
            video.play();
            video.muted = true;

            // Initialize the recorder
            recorder = new RecordRTCPromisesHandler(stream, {
                mimeType: 'video/webm',
                bitsPerSecond: 128000
            });

            // Start recording the video
            recorder.startRecording().then(function() {
                console.info('Recording video ...');
            }).catch(function(error) {
                console.log(error);
                console.error('Cannot start video recording: ', error);
            });

            // release stream on stopRecording
            recorder.stream = stream;

            // Enable stop recording button
            document.getElementById('btn-stop-recording').disabled = false;
        }).catch(function(error) {
                   console.log(error);
            console.error("Cannot access media devices: ", error);
        });
    }, false);
	
	
   // When the user clicks on Stop video recording
    document.getElementById('btn-stop-recording').addEventListener("click", function(){
        this.disabled = true;

        recorder.stopRecording().then(function() {
            console.info('stopRecording success');

            // Retrieve recorded video as blob and display in the preview element
            var blob = recorder.getBlob();
            video.src = URL.createObjectURL(blob);
            video.play();

            // Unmute video on preview
            video.muted = false;

            // Stop the device streaming
            recorder.stream.stop();

            // Enable record button again !
            document.getElementById('btn-start-recording').disabled = false;
        }).catch(function(error) {
            console.error('stopRecording failure', error);
        });
    }, false);
	

Configuration

const recorder = RecordRTC(stream, {
     // audio, video, canvas, gif
    type: 'video',

    // audio/webm
    // video/webm;codecs=vp9
    // video/webm;codecs=vp8
    // video/webm;codecs=h264
    // video/x-matroska;codecs=avc1
    // video/mpeg -- NOT supported by any browser, yet
    // video/mp4  -- NOT supported by any browser, yet
    // audio/wav
    // audio/ogg  -- ONLY Firefox
    // demo: simple-demos/isTypeSupported.html
    mimeType: 'video/webm',

    // MediaStreamRecorder, StereoAudioRecorder, WebAssemblyRecorder
    // CanvasRecorder, GifRecorder, WhammyRecorder
    recorderType: MediaStreamRecorder,

    // disable logs
    disableLogs: true,

    // get intervals based blobs
    // value in milliseconds
    timeSlice: 1000,

    // requires timeSlice above
    // returns blob via callback function
    ondataavailable: function(blob) {},

    // auto stop recording if camera stops
    checkForInactiveTracks: false,

    // requires timeSlice above
    onTimeStamp: function(timestamp) {},

    // both for audio and video tracks
    bitsPerSecond: 128000,

    // only for audio track
    audioBitsPerSecond: 128000,

    // only for video track
    videoBitsPerSecond: 128000,

    // used by CanvasRecorder and WhammyRecorder
    // it is kind of a "frameRate"
    frameInterval: 90,

    // if you are recording multiple streams into single file
    // this helps you see what is being recorded
    previewStream: function(stream) {},

    // used by CanvasRecorder and WhammyRecorder
    // you can pass {width:640, height: 480} as well
    video: HTMLVideoElement,

    // used by CanvasRecorder and WhammyRecorder
    canvas: {
        width: 640,
        height: 480
    },

    // used by StereoAudioRecorder
    // the range 22050 to 96000.
    sampleRate: 96000,

    // used by StereoAudioRecorder
    // the range 22050 to 96000.
    // let us force 16khz recording:
    desiredSampRate: 16000,

    // used by StereoAudioRecorder
    // Legal values are (256, 512, 1024, 2048, 4096, 8192, 16384).
    bufferSize: 16384,

    // used by StereoAudioRecorder
    // 1 or 2
    numberOfAudioChannels: 2,

    // used by WebAssemblyRecorder
    frameRate: 30,

    // used by WebAssemblyRecorder
    bitrate: 128000,

    // used by MultiStreamRecorder - to access HTMLCanvasElement
    elementClass: 'multi-streams-mixer'
});

Now we have to upload the video/audio file to s3

  1. In the Amazon S3 console, create an Amazon S3 bucket that you will use to store the photos in the album. Make sure you have both Read and Write permissions on Objects.

  2. In the Amazon Cognito console, create an Amazon Cognito identity pool using Federated Identities with access enabled for unauthenticated users in the same region as the Amazon S3 bucket. You need to include the identity pool ID in the code to obtain credentials for the browser script.

  3. In the IAM console, find the IAM role created by Amazon Cognito for unauthenticated users. Add the following policy to grant read and write permissions to an Amazon S3 bucket.

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "s3:*"
         ],
         "Resource": [
            "arn:aws:s3:::BUCKET_NAME/*"
         ]
      }
   ]
}

Before the browser script can access the Amazon S3 bucket, you must first set up its CORS configuration as follows.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

Obtain the credentials needed to configure the SDK by calling the CognitoIdentityCredentials method, providing the Amazon Cognito identity pool ID. Next, create an AWS.S3 service object.

 <script src="https://sdk.amazonaws.com/js/aws-sdk-2.283.1.min.js"></script> // Include in html head
AWS.config.region = 'us-east-2'; // 1. Enter your region

 AWS.config.credentials = new AWS.CognitoIdentityCredentials({
       IdentityPoolId: 'IDENTITY_POOL_ID' // 2. Enter your identity pool
 });

AWS.config.credentials.get(function(err) {
	if (err) alert(err);
	console.log(AWS.config.credentials);
});

var bucketName = 'BUCKET_NAME/*'; // Enter your bucket name
var bucket = new AWS.S3({
	params: {
		Bucket: bucketName
	}
});

To upload a file to Amazon S3 bucket, when stop recording

 function dataURLtoFile(dataurl, filename) {
            var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
                bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
            while(n--){
                u8arr[n] = bstr.charCodeAt(n);
            }
            return new File([u8arr], filename, {type:mime});
  }

 document.getElementById('btn-stop-recording').addEventListener("click", function(){
        this.disabled = true;

        recorder.stopRecording().then(function() {
            console.info('stopRecording success');

           var DataUrl = recorder.getDataURL();
           var random = Math.random( ); 
           DataUrl.then(function(result) {

                var url_file = dataURLtoFile(result, random +'.webm');

         var objKey = 'testing/' + url_file.name;
            var params = {
                Key: objKey,
                ContentType: url_file.type,
                Body: url_file,
                ACL: 'public-read'
            };

            var request = bucket.putObject(params);

            request.on('httpUploadProgress', function (progress) {
                percentage.innerHTML = parseInt((progress.loaded * 100) / progress.total)+'%'; 
                console.log("Uploaded :: " + parseInt((progress.loaded * 100) / progress.total)+'%');
               // console.log(progress.loaded + " of " + progress.total + " bytes");
            }).send(function(err, data){
                percentage.innerHTML = "File has been uploaded successfully.";
                listObjs();
            });


            cancelUpload.addEventListener('click', function() {
                    if(request.abort()){
                        percentage.innerHTML = "Uploading has been canceled.";
                    }
            });

    // here you can use the result of promiseB
});
           
            

            video.play();

            // Unmute video on preview
            video.muted = false;

            // Stop the device streaming
            recorder.stream.stop();

            // Enable record button again !
            document.getElementById('btn-start-recording').disabled = false;
        }).catch(function(error) {
            console.error('stopRecording failure', error);
        });
    }, false);