谢创宏

🎉 项目初始化

不能预览此文件类型
node_modules/*
\ No newline at end of file
... ...
# install
npm install
\ No newline at end of file
... ...
<!--
// Muaz Khan - www.MuazKhan.com
// MIT License - www.WebRTC-Experiment.com/licence
// Experiments - github.com/muaz-khan/RecordRTC
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>RecordRTC to Node.js</title>
<script>
if (location.href.indexOf('file:') == 0) {
document.write('<h1 style="color:red;">Please load this HTML file on HTTP or HTTPS.</h1>');
}
</script>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="author" type="text/html" href="https://plus.google.com/+MuazKhan">
<meta name="author" content="Muaz Khan">
<style>
html {
background-color: #f7f7f7;
}
body {
background-color: white;
border: 1px solid rgb(15, 158, 238);
margin: 1% 35%;
text-align: center;
}
hr {
border: 0;
border-top: 1px solid rgb(15, 158, 238);
}
a {
color: #2844FA;
text-decoration: none;
}
a:hover,
a:focus {
color: #1B29A4;
}
a:active {
color: #000;
}
audio,
video {
border: 1px solid rgb(15, 158, 238);
width: 94%;
}
button[disabled],
input[disabled] {
background: rgba(216, 205, 205, 0.2);
border: 1px solid rgb(233, 224, 224);
}
</style>
</head>
<body>
<h1>RecordRTC to Node.js</h1>
<p>
<video></video>
</p>
<hr />
<div>
<label id="percentage">0%</label>
<progress id="progress-bar" value=0></progress><br />
</div>
<hr />
<div>
<button id="btn-start-recording">Start Recording</button>
<button id="btn-stop-recording" disabled="">Stop Recording</button>
</div>
<script src="/node_modules/recordrtc/RecordRTC.js"> </script>
<script>
// fetching DOM references
var btnStartRecording = document.querySelector('#btn-start-recording');
var btnStopRecording = document.querySelector('#btn-stop-recording');
var videoElement = document.querySelector('video');
var progressBar = document.querySelector('#progress-bar');
var percentage = document.querySelector('#percentage');
var recorder;
// reusable helpers
// this function submits recorded blob to nodejs server
function postFiles() {
var blob = recorder.getBlob();
// getting unique identifier for the file name
var fileName = generateRandomString() + '.webm';
var file = new File([blob], fileName, {
type: 'video/webm'
});
videoElement.src = videoElement.srcObject = null;
videoElement.src = URL.createObjectURL(recorder.getBlob());
if (mediaStream) mediaStream.stop();
return;
// videoElement.src = '';
// videoElement.poster = '/ajax-loader.gif';
xhr('/uploadFile', file, function (responseText) {
var fileURL = JSON.parse(responseText).fileURL;
console.info('fileURL', fileURL);
videoElement.src = fileURL;
videoElement.play();
videoElement.muted = false;
videoElement.controls = true;
document.querySelector('#footer-h2').innerHTML = '<a href="' + videoElement.src + '">' + videoElement.src + '</a>';
});
if (mediaStream) mediaStream.stop();
}
// XHR2/FormData
function xhr(url, data, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200) {
callback(request.responseText);
}
};
request.upload.onprogress = function (event) {
progressBar.max = event.total;
progressBar.value = event.loaded;
progressBar.innerHTML = 'Upload Progress ' + Math.round(event.loaded / event.total * 100) + "%";
};
request.upload.onload = function () {
percentage.style.display = 'none';
progressBar.style.display = 'none';
};
request.open('POST', url);
var formData = new FormData();
formData.append('file', data);
request.send(formData);
}
// generating random string
function generateRandomString() {
if (window.crypto) {
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, '');
}
}
var mediaStream = null;
// reusable getUserMedia
function captureUserMedia(success_callback) {
var session = {
audio: true,
video: true
};
navigator.getUserMedia(session, success_callback, function (error) {
alert('Unable to capture your camera. Please check console logs.');
console.error(error);
});
}
// UI events handling
btnStartRecording.onclick = function () {
btnStartRecording.disabled = true;
captureUserMedia(function (stream) {
mediaStream = stream;
// videoElement.src = window.URL.createObjectURL(stream);
try {
videoElement.srcObject = stream;
} catch (error) {
videoElement.src = window.URL.createObjectURL(stream);
}
videoElement.play();
videoElement.muted = true;
videoElement.controls = true;
recorder = RecordRTC(stream, {
type: 'video'
});
recorder.startRecording();
// enable stop-recording button
btnStopRecording.disabled = false;
});
};
btnStopRecording.onclick = function () {
btnStartRecording.disabled = false;
btnStopRecording.disabled = true;
recorder.stopRecording(postFiles);
};
window.onbeforeunload = function () {
startRecording.disabled = false;
};
</script>
<footer style="width:100%;position: fixed; right: 0; text-align: center;color:red;">
<h2 id="footer-h2"></h2>
Questions?? <a href="mailto:muazkh@gmail.com">muazkh@gmail.com</a>
<br><br>
Open-Sourced here:<br>
<a
href="https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-to-Nodejs">https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-to-Nodejs</a>
</footer>
</body>
</html>
\ No newline at end of file
... ...
{
"name": "recordrtc-nodejs",
"preferGlobal": true,
"version": "1.0.6",
"author": {
"name": "Muaz Khan",
"email": "muazkh@gmail.com"
},
"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!",
"contributors": [
{
"name": "Muaz Khan",
"email": "muazkh@gmail.com"
}
],
"scripts": {
"start": "node server.js"
},
"main": "./server.js",
"repository": {
"type": "git",
"url": "https://github.com/muaz-khan/RecordRTC.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/RecordRTC/tree/master/RecordRTC-to-Nodejs",
"_id": "recordrtc-nodejs@",
"_from": "recordrtc-nodejs@",
"dependencies": {
"formidable": "latest",
"mime": "latest",
"recordrtc": "latest"
}
}
... ...
// http://127.0.0.1:9001
// http://localhost:9001
var server = require('http'),
url = require('url'),
path = require('path'),
fs = require('fs');
var port = 9001;
function serverHandler(request, response) {
var uri = url.parse(request.url).pathname,
filename = path.join(process.cwd(), uri);
var isWin = !!process.platform.match(/^win/);
if (filename && filename.toString().indexOf(isWin ? '\\uploadFile' : '/uploadFile') != -1 && request.method.toLowerCase() == 'post') {
uploadFile(request, response);
return;
}
fs.exists(filename, function(exists) {
if (!exists) {
response.writeHead(404, {
'Content-Type': 'text/plain'
});
response.write('404 Not Found: ' + filename + '\n');
response.end();
return;
}
if (filename.indexOf('favicon.ico') !== -1) {
return;
}
if (fs.statSync(filename).isDirectory() && !isWin) {
filename += '/index.html';
} else if (fs.statSync(filename).isDirectory() && !!isWin) {
filename += '\\index.html';
}
fs.readFile(filename, 'binary', function(err, file) {
if (err) {
response.writeHead(500, {
'Content-Type': 'text/plain'
});
response.write(err + '\n');
response.end();
return;
}
var contentType;
if (filename.indexOf('.html') !== -1) {
contentType = 'text/html';
}
if (filename.indexOf('.js') !== -1) {
contentType = 'application/javascript';
}
if (contentType) {
response.writeHead(200, {
'Content-Type': contentType
});
} else response.writeHead(200);
response.write(file, 'binary');
response.end();
});
});
}
var app;
app = server.createServer(serverHandler);
app = app.listen(port, process.env.IP || "0.0.0.0", function() {
var addr = app.address();
if (addr.address == '0.0.0.0') {
addr.address = 'localhost';
}
app.address = addr.address;
console.log("Server listening at", 'http://' + addr.address + ":" + addr.port);
});
function uploadFile(request, response) {
// parse a file upload
var mime = require('mime');
var formidable = require('formidable');
var util = require('util');
var form = new formidable.IncomingForm();
var dir = !!process.platform.match(/^win/) ? '\\uploads\\' : '/uploads/';
form.uploadDir = __dirname + dir;
form.keepExtensions = true;
form.maxFieldsSize = 10 * 1024 * 1024;
form.maxFields = 1000;
form.multiples = false;
form.parse(request, function(err, fields, files) {
var file = util.inspect(files);
response.writeHead(200, getHeaders('Content-Type', 'application/json'));
var fileName = file.split('path:')[1].split('\',')[0].split(dir)[1].toString().replace(/\\/g, '').replace(/\//g, '');
var fileURL = 'http://' + app.address + ':' + port + '/uploads/' + fileName;
console.log('fileURL: ', fileURL);
response.write(JSON.stringify({
fileURL: fileURL
}));
response.end();
});
}
function getHeaders(opt, val) {
try {
var headers = {};
headers["Access-Control-Allow-Origin"] = "https://secure.seedocnow.com";
headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
headers["Access-Control-Allow-Credentials"] = true;
headers["Access-Control-Max-Age"] = '86400'; // 24 hours
headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept";
if (opt) {
headers[opt] = val;
}
return headers;
} catch (e) {
return {};
}
}
... ...
### [RecordRTC to Node.js](https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-to-Nodejs)
This directory is used to store recorded wav/webm files.
... ...