谢创宏

🎉 项目初始化

不能预览此文件类型
  1 +node_modules/*
  1 +# install
  2 +npm install
  1 +<!--
  2 +// Muaz Khan - www.MuazKhan.com
  3 +// MIT License - www.WebRTC-Experiment.com/licence
  4 +// Experiments - github.com/muaz-khan/RecordRTC
  5 +-->
  6 +
  7 +<!DOCTYPE html>
  8 +<html>
  9 +
  10 +<head>
  11 + <meta charset="utf-8" />
  12 + <title>RecordRTC to Node.js</title>
  13 + <script>
  14 + if (location.href.indexOf('file:') == 0) {
  15 + document.write('<h1 style="color:red;">Please load this HTML file on HTTP or HTTPS.</h1>');
  16 + }
  17 + </script>
  18 + <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  19 + <link rel="author" type="text/html" href="https://plus.google.com/+MuazKhan">
  20 + <meta name="author" content="Muaz Khan">
  21 +
  22 + <style>
  23 + html {
  24 + background-color: #f7f7f7;
  25 + }
  26 +
  27 + body {
  28 + background-color: white;
  29 + border: 1px solid rgb(15, 158, 238);
  30 + margin: 1% 35%;
  31 + text-align: center;
  32 + }
  33 +
  34 + hr {
  35 + border: 0;
  36 + border-top: 1px solid rgb(15, 158, 238);
  37 + }
  38 +
  39 + a {
  40 + color: #2844FA;
  41 + text-decoration: none;
  42 + }
  43 +
  44 + a:hover,
  45 + a:focus {
  46 + color: #1B29A4;
  47 + }
  48 +
  49 + a:active {
  50 + color: #000;
  51 + }
  52 +
  53 + audio,
  54 + video {
  55 + border: 1px solid rgb(15, 158, 238);
  56 + width: 94%;
  57 + }
  58 +
  59 + button[disabled],
  60 + input[disabled] {
  61 + background: rgba(216, 205, 205, 0.2);
  62 + border: 1px solid rgb(233, 224, 224);
  63 + }
  64 + </style>
  65 +</head>
  66 +
  67 +<body>
  68 + <h1>RecordRTC to Node.js</h1>
  69 + <p>
  70 + <video></video>
  71 + </p>
  72 + <hr />
  73 +
  74 + <div>
  75 + <label id="percentage">0%</label>
  76 + <progress id="progress-bar" value=0></progress><br />
  77 + </div>
  78 +
  79 + <hr />
  80 +
  81 + <div>
  82 + <button id="btn-start-recording">Start Recording</button>
  83 + <button id="btn-stop-recording" disabled="">Stop Recording</button>
  84 + </div>
  85 +
  86 + <script src="/node_modules/recordrtc/RecordRTC.js"> </script>
  87 +
  88 + <script>
  89 + // fetching DOM references
  90 + var btnStartRecording = document.querySelector('#btn-start-recording');
  91 + var btnStopRecording = document.querySelector('#btn-stop-recording');
  92 +
  93 + var videoElement = document.querySelector('video');
  94 +
  95 + var progressBar = document.querySelector('#progress-bar');
  96 + var percentage = document.querySelector('#percentage');
  97 +
  98 + var recorder;
  99 +
  100 + // reusable helpers
  101 +
  102 + // this function submits recorded blob to nodejs server
  103 + function postFiles() {
  104 + var blob = recorder.getBlob();
  105 +
  106 + // getting unique identifier for the file name
  107 + var fileName = generateRandomString() + '.webm';
  108 +
  109 + var file = new File([blob], fileName, {
  110 + type: 'video/webm'
  111 + });
  112 +
  113 + videoElement.src = videoElement.srcObject = null;
  114 + videoElement.src = URL.createObjectURL(recorder.getBlob());
  115 + if (mediaStream) mediaStream.stop();
  116 + return;
  117 +
  118 + // videoElement.src = '';
  119 + // videoElement.poster = '/ajax-loader.gif';
  120 +
  121 + xhr('/uploadFile', file, function (responseText) {
  122 + var fileURL = JSON.parse(responseText).fileURL;
  123 +
  124 + console.info('fileURL', fileURL);
  125 + videoElement.src = fileURL;
  126 + videoElement.play();
  127 + videoElement.muted = false;
  128 + videoElement.controls = true;
  129 +
  130 + document.querySelector('#footer-h2').innerHTML = '<a href="' + videoElement.src + '">' + videoElement.src + '</a>';
  131 + });
  132 +
  133 + if (mediaStream) mediaStream.stop();
  134 + }
  135 +
  136 + // XHR2/FormData
  137 + function xhr(url, data, callback) {
  138 + var request = new XMLHttpRequest();
  139 + request.onreadystatechange = function () {
  140 + if (request.readyState == 4 && request.status == 200) {
  141 + callback(request.responseText);
  142 + }
  143 + };
  144 +
  145 + request.upload.onprogress = function (event) {
  146 + progressBar.max = event.total;
  147 + progressBar.value = event.loaded;
  148 + progressBar.innerHTML = 'Upload Progress ' + Math.round(event.loaded / event.total * 100) + "%";
  149 + };
  150 +
  151 + request.upload.onload = function () {
  152 + percentage.style.display = 'none';
  153 + progressBar.style.display = 'none';
  154 + };
  155 + request.open('POST', url);
  156 +
  157 + var formData = new FormData();
  158 + formData.append('file', data);
  159 + request.send(formData);
  160 + }
  161 +
  162 + // generating random string
  163 + function generateRandomString() {
  164 + if (window.crypto) {
  165 + var a = window.crypto.getRandomValues(new Uint32Array(3)),
  166 + token = '';
  167 + for (var i = 0, l = a.length; i < l; i++) token += a[i].toString(36);
  168 + return token;
  169 + } else {
  170 + return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, '');
  171 + }
  172 + }
  173 +
  174 + var mediaStream = null;
  175 + // reusable getUserMedia
  176 + function captureUserMedia(success_callback) {
  177 + var session = {
  178 + audio: true,
  179 + video: true
  180 + };
  181 +
  182 + navigator.getUserMedia(session, success_callback, function (error) {
  183 + alert('Unable to capture your camera. Please check console logs.');
  184 + console.error(error);
  185 + });
  186 + }
  187 +
  188 + // UI events handling
  189 + btnStartRecording.onclick = function () {
  190 + btnStartRecording.disabled = true;
  191 +
  192 + captureUserMedia(function (stream) {
  193 + mediaStream = stream;
  194 + // videoElement.src = window.URL.createObjectURL(stream);
  195 + try {
  196 + videoElement.srcObject = stream;
  197 + } catch (error) {
  198 + videoElement.src = window.URL.createObjectURL(stream);
  199 + }
  200 + videoElement.play();
  201 + videoElement.muted = true;
  202 + videoElement.controls = true;
  203 + recorder = RecordRTC(stream, {
  204 + type: 'video'
  205 + });
  206 +
  207 + recorder.startRecording();
  208 +
  209 + // enable stop-recording button
  210 + btnStopRecording.disabled = false;
  211 + });
  212 + };
  213 +
  214 +
  215 + btnStopRecording.onclick = function () {
  216 + btnStartRecording.disabled = false;
  217 + btnStopRecording.disabled = true;
  218 +
  219 + recorder.stopRecording(postFiles);
  220 + };
  221 +
  222 + window.onbeforeunload = function () {
  223 + startRecording.disabled = false;
  224 + };
  225 + </script>
  226 + <footer style="width:100%;position: fixed; right: 0; text-align: center;color:red;">
  227 + <h2 id="footer-h2"></h2>
  228 + Questions?? <a href="mailto:muazkh@gmail.com">muazkh@gmail.com</a>
  229 +
  230 + <br><br>
  231 + Open-Sourced here:<br>
  232 + <a
  233 + href="https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-to-Nodejs">https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-to-Nodejs</a>
  234 + </footer>
  235 +</body>
  236 +
  237 +</html>
  1 +{
  2 + "name": "recordrtc-nodejs",
  3 + "preferGlobal": true,
  4 + "version": "1.0.6",
  5 + "author": {
  6 + "name": "Muaz Khan",
  7 + "email": "muazkh@gmail.com"
  8 + },
  9 + "description": "Records audio/video separately as wav/webm. POST both files in single HttpPost-Request to Node.js (FormData). Node.js code saves both files into disk. Node.js code invokes ffmpeg to merge wav/webm in single webm file. The merged webm file's URL is returned using same HTTP-callback for playback!",
  10 + "contributors": [
  11 + {
  12 + "name": "Muaz Khan",
  13 + "email": "muazkh@gmail.com"
  14 + }
  15 + ],
  16 + "scripts": {
  17 + "start": "node server.js"
  18 + },
  19 + "main": "./server.js",
  20 + "repository": {
  21 + "type": "git",
  22 + "url": "https://github.com/muaz-khan/RecordRTC.git"
  23 + },
  24 + "keywords": [
  25 + "webrtc",
  26 + "javascript",
  27 + "RecordRTC",
  28 + "Node.js",
  29 + "ffmpeg",
  30 + "audio-recording",
  31 + "video-recording",
  32 + "gif-recording",
  33 + "audio/video recording",
  34 + "webp",
  35 + "webm",
  36 + "wav"
  37 + ],
  38 + "analyze": false,
  39 + "license": "MIT",
  40 + "engines": {
  41 + "node": ">=0.6"
  42 + },
  43 + "readmeFilename": "README.md",
  44 + "bugs": {
  45 + "url": "https://github.com/muaz-khan/WebRTC-Experiment/issues"
  46 + },
  47 + "homepage": "https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-to-Nodejs",
  48 + "_id": "recordrtc-nodejs@",
  49 + "_from": "recordrtc-nodejs@",
  50 + "dependencies": {
  51 + "formidable": "latest",
  52 + "mime": "latest",
  53 + "recordrtc": "latest"
  54 + }
  55 +}
  1 +// http://127.0.0.1:9001
  2 +// http://localhost:9001
  3 +
  4 +var server = require('http'),
  5 + url = require('url'),
  6 + path = require('path'),
  7 + fs = require('fs');
  8 +
  9 +var port = 9001;
  10 +
  11 +function serverHandler(request, response) {
  12 + var uri = url.parse(request.url).pathname,
  13 + filename = path.join(process.cwd(), uri);
  14 +
  15 + var isWin = !!process.platform.match(/^win/);
  16 +
  17 + if (filename && filename.toString().indexOf(isWin ? '\\uploadFile' : '/uploadFile') != -1 && request.method.toLowerCase() == 'post') {
  18 + uploadFile(request, response);
  19 + return;
  20 + }
  21 +
  22 + fs.exists(filename, function(exists) {
  23 + if (!exists) {
  24 + response.writeHead(404, {
  25 + 'Content-Type': 'text/plain'
  26 + });
  27 + response.write('404 Not Found: ' + filename + '\n');
  28 + response.end();
  29 + return;
  30 + }
  31 +
  32 + if (filename.indexOf('favicon.ico') !== -1) {
  33 + return;
  34 + }
  35 +
  36 + if (fs.statSync(filename).isDirectory() && !isWin) {
  37 + filename += '/index.html';
  38 + } else if (fs.statSync(filename).isDirectory() && !!isWin) {
  39 + filename += '\\index.html';
  40 + }
  41 +
  42 + fs.readFile(filename, 'binary', function(err, file) {
  43 + if (err) {
  44 + response.writeHead(500, {
  45 + 'Content-Type': 'text/plain'
  46 + });
  47 + response.write(err + '\n');
  48 + response.end();
  49 + return;
  50 + }
  51 +
  52 + var contentType;
  53 +
  54 + if (filename.indexOf('.html') !== -1) {
  55 + contentType = 'text/html';
  56 + }
  57 +
  58 + if (filename.indexOf('.js') !== -1) {
  59 + contentType = 'application/javascript';
  60 + }
  61 +
  62 + if (contentType) {
  63 + response.writeHead(200, {
  64 + 'Content-Type': contentType
  65 + });
  66 + } else response.writeHead(200);
  67 +
  68 + response.write(file, 'binary');
  69 + response.end();
  70 + });
  71 + });
  72 +}
  73 +
  74 +var app;
  75 +
  76 +app = server.createServer(serverHandler);
  77 +
  78 +app = app.listen(port, process.env.IP || "0.0.0.0", function() {
  79 + var addr = app.address();
  80 +
  81 + if (addr.address == '0.0.0.0') {
  82 + addr.address = 'localhost';
  83 + }
  84 +
  85 + app.address = addr.address;
  86 +
  87 + console.log("Server listening at", 'http://' + addr.address + ":" + addr.port);
  88 +});
  89 +
  90 +function uploadFile(request, response) {
  91 + // parse a file upload
  92 + var mime = require('mime');
  93 + var formidable = require('formidable');
  94 + var util = require('util');
  95 +
  96 + var form = new formidable.IncomingForm();
  97 +
  98 + var dir = !!process.platform.match(/^win/) ? '\\uploads\\' : '/uploads/';
  99 +
  100 + form.uploadDir = __dirname + dir;
  101 + form.keepExtensions = true;
  102 + form.maxFieldsSize = 10 * 1024 * 1024;
  103 + form.maxFields = 1000;
  104 + form.multiples = false;
  105 +
  106 + form.parse(request, function(err, fields, files) {
  107 + var file = util.inspect(files);
  108 +
  109 + response.writeHead(200, getHeaders('Content-Type', 'application/json'));
  110 +
  111 + var fileName = file.split('path:')[1].split('\',')[0].split(dir)[1].toString().replace(/\\/g, '').replace(/\//g, '');
  112 + var fileURL = 'http://' + app.address + ':' + port + '/uploads/' + fileName;
  113 +
  114 + console.log('fileURL: ', fileURL);
  115 + response.write(JSON.stringify({
  116 + fileURL: fileURL
  117 + }));
  118 + response.end();
  119 + });
  120 +}
  121 +
  122 +function getHeaders(opt, val) {
  123 + try {
  124 + var headers = {};
  125 + headers["Access-Control-Allow-Origin"] = "https://secure.seedocnow.com";
  126 + headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
  127 + headers["Access-Control-Allow-Credentials"] = true;
  128 + headers["Access-Control-Max-Age"] = '86400'; // 24 hours
  129 + headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept";
  130 +
  131 + if (opt) {
  132 + headers[opt] = val;
  133 + }
  134 +
  135 + return headers;
  136 + } catch (e) {
  137 + return {};
  138 + }
  139 +}
  1 +### [RecordRTC to Node.js](https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-to-Nodejs)
  2 +
  3 +This directory is used to store recorded wav/webm files.