{
  "name": "recordrtc",
  "preferGlobal": true,
  "version": "2.0.0",
  "author": {
    "name": "Muaz Khan",
    "email": "muazkh@gmail.com"
  },
  "description": "RecordRTC is a server-less (entire client-side) JavaScript library can be used to record WebRTC audio/video media streams. It supports cross-browser audio/video recording. Current experiment:  1. Records audio/video separately as wav/webm 2. POST both files in single HttpPost-Request to Node.js (FormData) 3. Node.js code saves both files into disk 4. Node.js code invokes ffmpeg to merge wav/webm in single WebM file 5. The merged webm file's URL is returned using same HTTP-callback for playback!",
  "contributors": [
    {
      "name": "Muaz Khan",
      "email": "muazkh@gmail.com"
    }
  ],
  "scripts": {
    "start": "node index"
  },
  "main": "./index",
  "repository": {
    "type": "git",
    "url": "https://github.com/muaz-khan/WebRTC-Experiment.git"
  },
  "keywords": [
    "webrtc",
    "javascript",
    "RecordRTC",
    "Node.js",
    "ffmpeg",
    "audio-recording",
    "video-recording",
    "gif-recording",
    "audio/video recording",
    "webp",
    "webm",
    "wav"
  ],
  "analyze": false,
  "license": "MIT",
  "engines": {
    "node": ">=0.6"
  },
  "readmeFilename": "README.md",
  "bugs": {
    "url": "https://github.com/muaz-khan/WebRTC-Experiment/issues"
  },
  "homepage": "https://github.com/muaz-khan/WebRTC-Experiment",
  "_id": "recordrtc@2.0.0",
  "_from": "recordrtc@",
  "readme": "#### [RecordRTC to Node.js](https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RecordRTC/RecordRTC-to-Nodejs)\n\n<a href=\"https://nodei.co/npm/recordrtc/\">\n    <img src=\"https://nodei.co/npm/recordrtc.png\">\n</a>\n\n```\nnpm install recordrtc\n\n// to run it!\ncd ./node_modules/recordrtc/ && node index.js\n```\n\n**Make sure that directory names MUST NOT have spaces; e.g.**\n\n```\n// invalid directory\nC:\\Hello Sir\\Another\\RecordRTC\n\n// valid\nC:\\Hello-Sir\\Another\\RecordRTC\n\n// invalid directory\nC:\\First\\Second Dir\\Third\\RecordRTC\n\n// valid\nC:\\\\First\\Second-Dir\\Third\\RecordRTC\n```\n\nThis experiment:\n\n1. Records audio/video separately as wav/webm\n2. POST both files in single HttpPost-Request to Node.js (FormData)\n3. Node.js code saves both files into disk\n4. Node.js code invokes ffmpeg to merge wav/webm in single \"webm\" file\n5. The merged webm file's URL is returned using same HTTP-callback for playback!\n\n=\n\n##### Windows Batch File (`merger.bat`)\n\n`merger.bat` file is executed to invoke ffmpeg functionalities on windows:\n\n```\n@echo off\n\"C:\\ffmpeg\\bin\\ffmpeg.exe\" -i %1 -i %2  %3\n```\n\n**It is assumed that you already have installed ffmpeg on your system.** Though, EXE file is hard-coded to \"C:\\ffmpeg\\bin\\ffmpeg.exe\" however you can easily edit it according to your own installations.\n\n=\n\n##### `.sh` file\n\n`merger.sh` file is executed to invoke ffmpeg functionalities on Mac/Linux/etc.\n\n```\nffmpeg -i video-file.webm -i audio-file.wav -map 0:0 -map 1:0 output-file-name.webm\n```\n\nUsing Linux; ffmpeg installation is super-easy! You can install DEVEL packages as well.\n\n=\n\n##### How to install ffmpeg on windows?\n\n1. Download ffmpeg and extract ZIP file\n2. Rename extracted directory to \"ffmpeg\"\n3. Right click over \"My Computer\" icon and select \"Properties\" context-menu option\n4. Select \"Advance system settings\" from top-left section\n5. Click \"Environment Variables...\" button from \"Advanced\" tab\n6. Click \"New...\" button and in the \"Variable name\" box, enter \"Path\".\n7. In the \"Variable value\" box, enter extracted directory full URI e.g. \"C:\\ffmpeg\"\n8. Click \"OK\" and done!\n\nhttp://www.wikihow.com/Install-FFmpeg-on-Windows\n\n=\n\n##### How to install ffmpeg on Mac OSX?\n\nMake sure you have **homebrew** installed. Then run following command:\n\n```\nbrew install ffmpeg --with-libvpx --with-theora --whit-libogg --with-libvorbis\n```\n\n##### How to test?\n\nIn the node.js command prompt window; type `node index`; then open `http://localhost:8000/`.\n\n=\n\n##### RecordRTC invocation code in `index.html`\n\n```javascript\nvar startRecording = document.getElementById('start-recording');\nvar stopRecording = document.getElementById('stop-recording');\nvar cameraPreview = document.getElementById('camera-preview');\n\nvar audio = document.querySelector('audio');\n\nvar recordAudio, recordVideo;\nstartRecording.onclick = function() {\n    startRecording.disabled = true;\n    var video_constraints = {\n        mandatory: { },\n        optional: []\n    };\n    navigator.getUserMedia({\n            audio: true,\n            video: video_constraints\n        }, function(stream) {\n            cameraPreview.src = window.URL.createObjectURL(stream);\n            cameraPreview.play();\n\n            recordAudio = RecordRTC(stream, {\n                bufferSize: 4096\n            });\n\n            recordVideo = RecordRTC(stream, {\n                type: 'video'\n            });\n\n            recordAudio.startRecording();\n            recordVideo.startRecording();\n\n            stopRecording.disabled = false;\n        });\n};\n\nvar fileName;\nstopRecording.onclick = function() {\n    startRecording.disabled = false;\n    stopRecording.disabled = true;\n\n    fileName = Math.round(Math.random() * 99999999) + 99999999;\n\n    recordAudio.stopRecording();\n    recordVideo.stopRecording();\n\n    recordAudio.getDataURL(function(audioDataURL) {\n        recordVideo.getDataURL(function(videoDataURL) {\n            var files = {\n                audio: {\n                    name: fileName + '.wav',\n                    type: 'audio/wav',\n                    contents: audioDataURL\n                },\n                video: {\n                    name: fileName + '.webm',\n                    type: 'video/webm',\n                    contents: videoDataURL\n                }\n            };\n\n            cameraPreview.src = '';\n            cameraPreview.poster = '//www.webrtc-experiment.com/images/ajax-loader.gif';\n\n            xhr('/upload', JSON.stringify(files), function(fileName) {\n                var href = location.href.substr(0, location.href.lastIndexOf('/') + 1);\n                cameraPreview.src = href + 'uploads/' + fileName;\n                cameraPreview.play();\n            });\n        });\n    });\n};\n\nfunction xhr(url, data, callback) {\n    var request = new XMLHttpRequest();\n    request.onreadystatechange = function() {\n        if (request.readyState == 4 && request.status == 200) {\n            callback(request.responseText);\n        }\n    };\n    request.open('POST', url);\n    request.send(data);\n}\n```\n\n=\n\n##### `index.js`\n\n```javascript\nvar server = require('./server'),\n    handlers = require('./handlers'),\n    router = require('./router'),\n    handle = { };\n\nhandle[\"/\"] = handlers.home;\nhandle[\"/home\"] = handlers.home;\nhandle[\"/upload\"] = handlers.upload;\nhandle._static = handlers.serveStatic;\n\nserver.start(router.route, handle);\n```\n\n=\n\n##### `server.js`\n\n```javascript\nvar config = require('./config'),\n    http = require('http'),\n    url = require('url');\n\nfunction start(route, handle) {\n\n    function onRequest(request, response) {\n\n        var pathname = url.parse(request.url).pathname,\n            postData = '';\n\n        request.setEncoding('utf8');\n\n        request.addListener('data', function(postDataChunk) {\n            postData += postDataChunk;\n        });\n\n        request.addListener('end', function() {\n            route(handle, pathname, response, postData);\n        });\n    }\n\n    http.createServer(onRequest).listen(config.port);\n}\n\nexports.start = start;\n```\n\n=\n\n##### `handlers.js`\n\n```javascript\nvar config = require('./config'),\n    fs = require('fs'),\n    sys = require('sys'),\n    exec = require('child_process').exec;\n\nfunction home(response, postData) {\n    response.writeHead(200, { 'Content-Type': 'text/html' });\n    response.end(fs.readFileSync('./static/index.html'));\n}\n\n// this function uploads files\n\nfunction upload(response, postData) {\n    var files = JSON.parse(postData);\n\n    // writing audio file to disk\n    _upload(response, files.audio);\n\n    // writing video file to disk\n    _upload(response, files.video);\n\n    merge(response, files);\n}\n\n// this function merges wav/webm files\n\nfunction merge(response, files) {\n    // detect the current operating system\n    var isWin = !!process.platform.match(/^win/);\n\n    if (isWin) {\n      // following command tries to merge wav/webm files using ffmpeg\n      var merger = __dirname + '\\\\merger.bat';\n      var audioFile = __dirname + '\\\\uploads\\\\' + files.audio.name;\n      var videoFile = __dirname + '\\\\uploads\\\\' + files.video.name;\n      var mergedFile = __dirname + '\\\\uploads\\\\' + files.audio.name.split('.')[0] + '-merged.webm';\n\n      // if a \"directory\" has space in its name; below command will fail\n      // e.g. \"c:\\\\dir name\\\\uploads\" will fail.\n      // it must be like this: \"c:\\\\dir-name\\\\uploads\"\n      var command = merger + ', ' + videoFile + \" \" + audioFile + \" \" + mergedFile + '';\n      var cmd = exec(command, function(error, stdout, stderr) {\n          if (error) {\n              console.log(error.stack);\n              console.log('Error code: ' + error.code);\n              console.log('Signal received: ' + error.signal);\n              response.statusCode = 404;\n              response.end();\n          } else {\n              response.statusCode = 200;\n              response.writeHead(200, { 'Content-Type': 'application/json' });\n              response.end(files.audio.name.split('.')[0] + '-merged.webm');\n\n              // removing audio/video files\n              fs.unlink(audioFile);\n              fs.unlink(videoFile);\n\n              // auto delete file after 1-minute\n              setTimeout(function() {\n                  fs.unlink(mergedFile);\n              }, 60 * 1000);\n          }\n      });\n    } else { // its probably *nix, assume ffmpeg is available\n      var audioFile = __dirname + '/uploads/' + files.audio.name;\n      var videoFile = __dirname + '/uploads/' + files.video.name;\n      var mergedFile = __dirname + '/uploads/' + files.audio.name.split('.')[0] + '-merged.webm';\n      var util = require('util'),\n        exec = require('child_process').exec;\n        //child_process = require('child_process');\n\n        var command = \"ffmpeg -i \" + videoFile + \" -i \" + audioFile + \" -map 0:0 -map 1:0 \" + mergedFile;\n\n        var child = exec(command, function(error, stdout, stderr){\n\n            stdout ? util.print('stdout: ' + stdout) : null;\n            stderr ? util.print('stderr: ' + stderr) : null;\n\n            if (error) {\n\n                console.log('exec error: ' + error);\n                response.statusCode = 404;\n                response.end();\n\n            } else {\n\n              response.statusCode = 200;\n              response.writeHead(200, { 'Content-Type': 'application/json' });\n              response.end(files.audio.name.split('.')[0] + '-merged.webm');\n\n              // removing audio/video files\n              fs.unlink(audioFile);\n              fs.unlink(videoFile);\n\n              // auto delete file after 1-minute\n              setTimeout(function() {\n                  fs.unlink(mergedFile);\n              }, 60 * 1000);\n\n            }\n\n        });\n\n    }\n}\n\nfunction _upload(response, file) {\n    var fileRootName = file.name.split('.').shift(),\n        fileExtension = file.name.split('.').pop(),\n        filePathBase = config.upload_dir + '/',\n        fileRootNameWithBase = filePathBase + fileRootName,\n        filePath = fileRootNameWithBase + '.' + fileExtension,\n        fileID = 2,\n        fileBuffer;\n\n    while (fs.existsSync(filePath)) {\n        filePath = fileRootNameWithBase + '(' + fileID + ').' + fileExtension;\n        fileID += 1;\n    }\n\n    file.contents = file.contents.split(',').pop();\n\n    fileBuffer = new Buffer(file.contents, \"base64\");\n\n    if (config.s3_enabled) {\n\n        var knox = require('knox'),\n            client = knox.createClient(config.s3),\n            headers = { 'Content-Type': file.type };\n\n        client.putBuffer(fileBuffer, fileRootName, headers);\n\n    } else {\n        fs.writeFileSync(filePath, fileBuffer);\n    }\n}\n\nfunction serveStatic(response, pathname, postData) {\n\n    var extension = pathname.split('.').pop(),\n        extensionTypes = {\n            'js': 'application/javascript',\n            'webm': 'video/webm',\n            'gif': 'image/gif'\n        };\n\n    response.writeHead(200, { 'Content-Type': extensionTypes[extension] });\n    if (extensionTypes[extension] == 'video/webm')\n        response.end(fs.readFileSync('.' + pathname));\n    else\n        response.end(fs.readFileSync('./static' + pathname));\n}\n\nexports.home = home;\nexports.upload = upload;\nexports.serveStatic = serveStatic;\n```\n\n=\n\n##### `router.js`\n\n```javascript\nfunction respondWithHTTPCode(response, code) {\n    response.writeHead(code, { 'Content-Type': 'text/plain' });\n    response.end();\n}\n\nfunction route(handle, pathname, response, postData) {\n\n    var extension = pathname.split('.').pop();\n\n    var staticFiles = {\n        js: 'js',\n        gif: 'gif',\n        css: 'css',\n        webm: 'webm'\n    };\n\n    if ('function' === typeof handle[pathname]) {\n        handle[pathname](response, postData);\n    } else if (staticFiles[extension]) {\n        handle._static(response, pathname, postData);\n    } else {\n        respondWithHTTPCode(response, 404);\n    }\n}\n\nexports.route = route;\n```\n\n=\n\n##### `config.js`\n\n```javascript\nexports.port = 8000;\nexports.upload_dir = './uploads';\n\nexports.s3 = {\n    key: '',\n    secret: '',\n    bucket: ''\n};\n\nexports.s3_enabled = false;\n```\n\n=\n\n##### License\n\n[RecordRTC](https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RecordRTC) is released under [MIT licence](https://www.webrtc-experiment.com/licence/) . Copyright (c) 2013 [Muaz Khan](https://plus.google.com/+MuazKhan).\n",
  "dist": {
    "shasum": "e5569e4a8abd06cb5d6081329131fbda7ca87a0a"
  },
  "_resolved": "https://registry.npmjs.org/recordrtc/-/recordrtc-2.0.0.tgz"
}
