recordrtc
Version:
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.
1,069 lines (875 loc) • 47.1 kB
HTML
<!--
> Muaz Khan - www.MuazKhan.com
> MIT License - www.WebRTC-Experiment.com/licence
> Documentation - github.com/muaz-khan/RecordRTC
> and - RecordRTC.org
-->
<html lang="en">
<head>
<title>RecordRTC to PHP ® Muaz Khan</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="author" type="text/html" href="https://plus.google.com/+MuazKhan">
<meta name="author" content="Muaz Khan">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="stylesheet" href="https://cdn.webrtc-experiment.com/style.css">
<style>
audio {
vertical-align: bottom;
width: 10em;
}
video {
max-width: 100%;
vertical-align: top;
}
input {
border: 1px solid #d9d9d9;
border-radius: 1px;
font-size: 2em;
margin: .2em;
width: 30%;
}
p,
.inner {
padding: 1em;
}
li {
border-bottom: 1px solid rgb(189, 189, 189);
border-left: 1px solid rgb(189, 189, 189);
padding: .5em;
}
label {
display: inline-block;
width: 8em;
}
</style>
<style>
.recordrtc button {
font-size: inherit;
}
.recordrtc button, .recordrtc select {
vertical-align: middle;
line-height: 1;
padding: 2px 5px;
height: auto;
font-size: inherit;
margin: 0;
}
.recordrtc, .recordrtc .header {
display: block;
text-align: center;
padding-top: 0;
}
.recordrtc video {
width: 70%;
}
.recordrtc option[disabled] {
display: none;
}
</style>
<script src="https://cdn.webrtc-experiment.com/RecordRTC.js"></script>
<script src="https://cdn.webrtc-experiment.com/gif-recorder.js"></script>
<script src="https://cdn.webrtc-experiment.com/getScreenId.js"></script>
<!-- for Edige/FF/Chrome/Opera/etc. getUserMedia support -->
<script src="https://cdn.webrtc-experiment.com/gumadapter.js"></script>
</head>
<body>
<article>
<header style="text-align: center;">
<h1>
<a href="https://github.com/muaz-khan/RecordRTC" target="_blank">RecordRTC</a> to <a href="https://github.com/muaz-khan/RecordRTC/RecordRTC-to-PHP" target="_blank">PHP</a> ®
<a href="https://github.com/muaz-khan" target="_blank">Muaz Khan</a>
</h1>
<p>
<a href="https://www.webrtc-experiment.com/RecordRTC/">HOME</a>
<span> © </span>
<a href="http://www.MuazKhan.com/" target="_blank">Muaz Khan</a> .
<a href="http://twitter.com/WebRTCWeb" target="_blank" title="Twitter profile for WebRTC Experiments">@WebRTCWeb</a> .
<a href="https://github.com/muaz-khan?tab=repositories" target="_blank" title="Github Profile">Github</a> .
<a href="https://github.com/muaz-khan/RecordRTC/issues?state=open" target="_blank">Latest issues</a> .
<a href="https://github.com/muaz-khan/RecordRTC/commits/master" target="_blank">What's New?</a>
</p>
</header>
<div class="github-stargazers"></div>
<blockquote class="inline">
This demo allows you record and upload to PHP server. Files on PHP server are auto-deleted as soon as you leave this page.
<br><br>
This demo is open-sourced here: <a href="https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-to-PHP">github/RecordRTC-to-PHP</a>
</blockquote>
<section class="experiment recordrtc">
<h2 class="header">
<select class="recording-media">
<option value="record-video">Video</option>
<option value="record-audio">Audio</option>
<option value="record-screen">Screen</option>
</select>
into
<select class="media-container-format">
<option>WebM</option>
<option disabled>Mp4</option>
<option disabled>WAV</option>
<option disabled>Ogg</option>
<option>Gif</option>
</select>
<button>Start Recording</button>
</h2>
<div style="text-align: center; display: none;">
<button id="save-to-disk">Save To Disk</button>
<button id="open-new-tab">Open New Tab</button>
<button id="upload-to-server">Upload To Server</button>
</div>
<br>
<video controls muted></video>
</section>
<script>
(function() {
var params = {},
r = /([^&=]+)=?([^&]*)/g;
function d(s) {
return decodeURIComponent(s.replace(/\+/g, ' '));
}
var match, search = window.location.search;
while (match = r.exec(search.substring(1))) {
params[d(match[1])] = d(match[2]);
if(d(match[2]) === 'true' || d(match[2]) === 'false') {
params[d(match[1])] = d(match[2]) === 'true' ? true : false;
}
}
window.params = params;
})();
</script>
<script>
var recordingDIV = document.querySelector('.recordrtc');
var recordingMedia = recordingDIV.querySelector('.recording-media');
var recordingPlayer = recordingDIV.querySelector('video');
var mediaContainerFormat = recordingDIV.querySelector('.media-container-format');
recordingDIV.querySelector('button').onclick = function() {
var button = this;
if(button.innerHTML === 'Stop Recording') {
button.disabled = true;
button.disableStateWaiting = true;
setTimeout(function() {
button.disabled = false;
button.disableStateWaiting = false;
}, 2 * 1000);
button.innerHTML = 'Star Recording';
function stopStream() {
if(button.stream && button.stream.stop) {
button.stream.stop();
button.stream = null;
}
}
if(button.recordRTC) {
if(button.recordRTC.length) {
button.recordRTC[0].stopRecording(function(url) {
if(!button.recordRTC[1]) {
button.recordingEndedCallback(url);
stopStream();
saveToDiskOrOpenNewTab(button.recordRTC[0]);
return;
}
button.recordRTC[1].stopRecording(function(url) {
button.recordingEndedCallback(url);
stopStream();
});
});
}
else {
button.recordRTC.stopRecording(function(url) {
button.recordingEndedCallback(url);
stopStream();
saveToDiskOrOpenNewTab(button.recordRTC);
});
}
}
return;
}
button.disabled = true;
var commonConfig = {
onMediaCaptured: function(stream) {
button.stream = stream;
if(button.mediaCapturedCallback) {
button.mediaCapturedCallback();
}
button.innerHTML = 'Stop Recording';
button.disabled = false;
},
onMediaStopped: function() {
button.innerHTML = 'Start Recording';
if(!button.disableStateWaiting) {
button.disabled = false;
}
},
onMediaCapturingFailed: function(error) {
if(error.name === 'PermissionDeniedError' && !!navigator.mozGetUserMedia) {
InstallTrigger.install({
'Foo': {
// https://addons.mozilla.org/firefox/downloads/latest/655146/addon-655146-latest.xpi?src=dp-btn-primary
URL: 'https://addons.mozilla.org/en-US/firefox/addon/enable-screen-capturing/',
toString: function () {
return this.URL;
}
}
});
}
commonConfig.onMediaStopped();
}
};
if(recordingMedia.value === 'record-video') {
captureVideo(commonConfig);
button.mediaCapturedCallback = function() {
button.recordRTC = RecordRTC(button.stream, {
type: mediaContainerFormat.value === 'Gif' ? 'gif' : 'video',
disableLogs: params.disableLogs || false,
canvas: {
width: params.canvas_width || 320,
height: params.canvas_height || 240
},
frameInterval: typeof params.frameInterval !== 'undefined' ? parseInt(params.frameInterval) : 20 // minimum time between pushing frames to Whammy (in milliseconds)
});
button.recordingEndedCallback = function(url) {
recordingPlayer.src = null;
recordingPlayer.srcObject = null;
if(mediaContainerFormat.value === 'Gif') {
recordingPlayer.pause();
recordingPlayer.poster = url;
recordingPlayer.onended = function() {
recordingPlayer.pause();
recordingPlayer.poster = URL.createObjectURL(button.recordRTC.blob);
};
return;
}
recordingPlayer.src = url;
recordingPlayer.play();
recordingPlayer.onended = function() {
recordingPlayer.pause();
recordingPlayer.src = URL.createObjectURL(button.recordRTC.blob);
};
};
button.recordRTC.startRecording();
};
}
if(recordingMedia.value === 'record-audio') {
captureAudio(commonConfig);
button.mediaCapturedCallback = function() {
button.recordRTC = RecordRTC(button.stream, {
type: 'audio',
bufferSize: typeof params.bufferSize == 'undefined' ? 0 : parseInt(params.bufferSize),
sampleRate: typeof params.sampleRate == 'undefined' ? 44100 : parseInt(params.sampleRate),
leftChannel: params.leftChannel || false,
disableLogs: params.disableLogs || false,
recorderType: webrtcDetectedBrowser === 'edge' ? StereoAudioRecorder : null
});
button.recordingEndedCallback = function(url) {
var audio = new Audio();
audio.src = url;
audio.controls = true;
recordingPlayer.parentNode.appendChild(document.createElement('hr'));
recordingPlayer.parentNode.appendChild(audio);
if(audio.paused) audio.play();
audio.onended = function() {
audio.pause();
audio.src = URL.createObjectURL(button.recordRTC.blob);
};
};
button.recordRTC.startRecording();
};
}
if(recordingMedia.value === 'record-audio-plus-video') {
captureAudioPlusVideo(commonConfig);
button.mediaCapturedCallback = function() {
if(webrtcDetectedBrowser !== 'firefox') { // opera or chrome etc.
button.recordRTC = [];
if(!params.bufferSize) {
// it fixes audio issues whilst recording 720p
params.bufferSize = 16384;
}
var audioRecorder = RecordRTC(button.stream, {
type: 'audio',
bufferSize: typeof params.bufferSize == 'undefined' ? 0 : parseInt(params.bufferSize),
sampleRate: typeof params.sampleRate == 'undefined' ? 44100 : parseInt(params.sampleRate),
leftChannel: params.leftChannel || false,
disableLogs: params.disableLogs || false,
recorderType: webrtcDetectedBrowser === 'edge' ? StereoAudioRecorder : null
});
var videoRecorder = RecordRTC(button.stream, {
type: 'video',
disableLogs: params.disableLogs || false,
canvas: {
width: params.canvas_width || 320,
height: params.canvas_height || 240
},
frameInterval: typeof params.frameInterval !== 'undefined' ? parseInt(params.frameInterval) : 20 // minimum time between pushing frames to Whammy (in milliseconds)
});
// to sync audio/video playbacks in browser!
videoRecorder.initRecorder(function() {
audioRecorder.initRecorder(function() {
audioRecorder.startRecording();
videoRecorder.startRecording();
});
});
button.recordRTC.push(audioRecorder, videoRecorder);
button.recordingEndedCallback = function() {
var audio = new Audio();
audio.src = audioRecorder.toURL();
audio.controls = true;
audio.autoplay = true;
audio.onloadedmetadata = function() {
recordingPlayer.src = videoRecorder.toURL();
recordingPlayer.play();
};
recordingPlayer.parentNode.appendChild(document.createElement('hr'));
recordingPlayer.parentNode.appendChild(audio);
if(audio.paused) audio.play();
};
return;
}
button.recordRTC = RecordRTC(button.stream, {
type: 'video',
disableLogs: params.disableLogs || false,
// we can't pass bitrates or framerates here
// Firefox MediaRecorder API lakes these features
});
button.recordingEndedCallback = function(url) {
recordingPlayer.srcObject = null;
recordingPlayer.muted = false;
recordingPlayer.src = url;
recordingPlayer.play();
recordingPlayer.onended = function() {
recordingPlayer.pause();
recordingPlayer.src = URL.createObjectURL(button.recordRTC.blob);
};
};
button.recordRTC.startRecording();
};
}
if(recordingMedia.value === 'record-screen') {
captureScreen(commonConfig);
button.mediaCapturedCallback = function() {
button.recordRTC = RecordRTC(button.stream, {
type: mediaContainerFormat.value === 'Gif' ? 'gif' : 'video',
disableLogs: params.disableLogs || false,
canvas: {
width: params.canvas_width || 320,
height: params.canvas_height || 240
}
});
button.recordingEndedCallback = function(url) {
recordingPlayer.src = null;
recordingPlayer.srcObject = null;
if(mediaContainerFormat.value === 'Gif') {
recordingPlayer.pause();
recordingPlayer.poster = url;
recordingPlayer.onended = function() {
recordingPlayer.pause();
recordingPlayer.poster = URL.createObjectURL(button.recordRTC.blob);
};
return;
}
recordingPlayer.src = url;
recordingPlayer.play();
};
button.recordRTC.startRecording();
};
}
if(recordingMedia.value === 'record-audio-plus-screen') {
captureAudioPlusScreen(commonConfig);
button.mediaCapturedCallback = function() {
button.recordRTC = RecordRTC(button.stream, {
type: 'video',
disableLogs: params.disableLogs || false,
// we can't pass bitrates or framerates here
// Firefox MediaRecorder API lakes these features
});
button.recordingEndedCallback = function(url) {
recordingPlayer.srcObject = null;
recordingPlayer.muted = false;
recordingPlayer.src = url;
recordingPlayer.play();
recordingPlayer.onended = function() {
recordingPlayer.pause();
recordingPlayer.src = URL.createObjectURL(button.recordRTC.blob);
};
};
button.recordRTC.startRecording();
};
}
};
function captureVideo(config) {
captureUserMedia({video: true}, function(videoStream) {
recordingPlayer.srcObject = videoStream;
recordingPlayer.play();
config.onMediaCaptured(videoStream);
videoStream.onended = function() {
config.onMediaStopped();
};
}, function(error) {
config.onMediaCapturingFailed(error);
});
}
function captureAudio(config) {
captureUserMedia({audio: true}, function(audioStream) {
recordingPlayer.srcObject = audioStream;
recordingPlayer.play();
config.onMediaCaptured(audioStream);
audioStream.onended = function() {
config.onMediaStopped();
};
}, function(error) {
config.onMediaCapturingFailed(error);
});
}
function captureAudioPlusVideo(config) {
captureUserMedia({video: true, audio: true}, function(audioVideoStream) {
recordingPlayer.srcObject = audioVideoStream;
recordingPlayer.play();
config.onMediaCaptured(audioVideoStream);
audioVideoStream.onended = function() {
config.onMediaStopped();
};
}, function(error) {
config.onMediaCapturingFailed(error);
});
}
function captureScreen(config) {
getScreenId(function(error, sourceId, screenConstraints) {
if (error === 'not-installed') {
document.write('<h1><a target="_blank" href="https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk">Please install this chrome extension then reload the page.</a></h1>');
}
if (error === 'permission-denied') {
alert('Screen capturing permission is denied.');
}
if (error === 'installed-disabled') {
alert('Please enable chrome screen capturing extension.');
}
if(error) {
config.onMediaCapturingFailed(error);
return;
}
captureUserMedia(screenConstraints, function(screenStream) {
recordingPlayer.srcObject = screenStream;
recordingPlayer.play();
config.onMediaCaptured(screenStream);
screenStream.onended = function() {
config.onMediaStopped();
};
}, function(error) {
config.onMediaCapturingFailed(error);
});
});
}
function captureAudioPlusScreen(config) {
getScreenId(function(error, sourceId, screenConstraints) {
if (error === 'not-installed') {
document.write('<h1><a target="_blank" href="https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk">Please install this chrome extension then reload the page.</a></h1>');
}
if (error === 'permission-denied') {
alert('Screen capturing permission is denied.');
}
if (error === 'installed-disabled') {
alert('Please enable chrome screen capturing extension.');
}
if(error) {
config.onMediaCapturingFailed(error);
return;
}
screenConstraints.audio = true;
captureUserMedia(screenConstraints, function(screenStream) {
recordingPlayer.srcObject = screenStream;
recordingPlayer.play();
config.onMediaCaptured(screenStream);
screenStream.onended = function() {
config.onMediaStopped();
};
}, function(error) {
config.onMediaCapturingFailed(error);
});
});
}
function captureUserMedia(mediaConstraints, successCallback, errorCallback) {
navigator.mediaDevices.getUserMedia(mediaConstraints).then(successCallback).catch(errorCallback);
}
function setMediaContainerFormat(arrayOfOptionsSupported) {
var options = Array.prototype.slice.call(
mediaContainerFormat.querySelectorAll('option')
);
var selectedItem;
options.forEach(function(option) {
option.disabled = true;
if(arrayOfOptionsSupported.indexOf(option.value) !== -1) {
option.disabled = false;
if(!selectedItem) {
option.selected = true;
selectedItem = option;
}
}
});
}
recordingMedia.onchange = function() {
if(this.value === 'record-audio') {
setMediaContainerFormat(['WAV', 'Ogg']);
return;
}
setMediaContainerFormat(['WebM', /*'Mp4',*/ 'Gif']);
};
if(webrtcDetectedBrowser === 'edge') {
// webp isn't supported in Microsoft Edge
// neither MediaRecorder API
// so lets disable both video/screen recording options
console.warn('Neither MediaRecorder API nor webp is supported in Microsoft Edge. You cam merely record audio.');
recordingMedia.innerHTML = '<option value="record-audio">Audio</option>';
setMediaContainerFormat(['WAV']);
}
if(webrtcDetectedBrowser === 'firefox') {
// Firefox implemented both MediaRecorder API as well as WebAudio API
// Their MediaRecorder implementation supports both audio/video recording in single container format
// Remember, we can't currently pass bit-rates or frame-rates values over MediaRecorder API (their implementation lakes these features)
recordingMedia.innerHTML = '<option value="record-audio-plus-video">Audio+Video</option>'
+ '<option value="record-audio-plus-screen">Audio+Screen</option>'
+ recordingMedia.innerHTML;
}
// disabling this option because currently this demo
// doesn't supports publishing two blobs.
// todo: add support of uploading both WAV/WebM to server.
if(false && webrtcDetectedBrowser === 'chrome') {
recordingMedia.innerHTML = '<option value="record-audio-plus-video">Audio+Video</option>'
+ recordingMedia.innerHTML;
console.info('This RecordRTC demo merely tries to playback recorded audio/video sync inside the browser. It still generates two separate files (WAV/WebM).');
}
function saveToDiskOrOpenNewTab(recordRTC) {
recordingDIV.querySelector('#save-to-disk').parentNode.style.display = 'block';
recordingDIV.querySelector('#save-to-disk').onclick = function() {
if(!recordRTC) return alert('No recording found.');
recordRTC.save();
};
recordingDIV.querySelector('#open-new-tab').onclick = function() {
if(!recordRTC) return alert('No recording found.');
window.open(recordRTC.toURL());
};
recordingDIV.querySelector('#upload-to-server').disabled = false;
recordingDIV.querySelector('#upload-to-server').onclick = function() {
if(!recordRTC) return alert('No recording found.');
this.disabled = true;
var button = this;
uploadToServer(recordRTC, function(progress, fileURL) {
if(progress === 'ended') {
button.disabled = false;
button.innerHTML = 'Click to download from server';
button.onclick = function() {
window.open(fileURL);
};
return;
}
button.innerHTML = progress;
});
};
}
var listOfFilesUploaded = [];
function uploadToServer(recordRTC, callback) {
var blob = recordRTC instanceof Blob ? recordRTC : recordRTC.blob;
var fileType = blob.type.split('/')[0] || 'audio';
var fileName = (Math.random() * 1000).toString().replace('.', '');
if (fileType === 'audio') {
fileName += '.' + (!!navigator.mozGetUserMedia ? 'ogg' : 'wav');
} else {
fileName += '.webm';
}
// create FormData
var formData = new FormData();
formData.append(fileType + '-filename', fileName);
formData.append(fileType + '-blob', blob);
callback('Uploading ' + fileType + ' recording to server.');
makeXMLHttpRequest('save.php', formData, function(progress) {
if (progress !== 'upload-ended') {
callback(progress);
return;
}
var initialURL = location.href.replace(location.href.split('/').pop(), '') + 'uploads/';
callback('ended', initialURL + fileName);
// to make sure we can delete as soon as visitor leaves
listOfFilesUploaded.push(initialURL + fileName);
});
}
function makeXMLHttpRequest(url, data, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
callback('upload-ended');
}
};
request.upload.onloadstart = function() {
callback('Upload started...');
};
request.upload.onprogress = function(event) {
callback('Upload Progress ' + Math.round(event.loaded / event.total * 100) + "%");
};
request.upload.onload = function() {
callback('progress-about-to-end');
};
request.upload.onload = function() {
callback('progress-ended');
};
request.upload.onerror = function(error) {
callback('Failed to upload to server');
console.error('XMLHttpRequest failed', error);
};
request.upload.onabort = function(error) {
callback('Upload aborted.');
console.error('XMLHttpRequest aborted', error);
};
request.open('POST', url);
request.send(data);
}
window.onbeforeunload = function() {
recordingDIV.querySelector('button').disabled = false;
recordingMedia.disabled = false;
mediaContainerFormat.disabled = false;
if(!listOfFilesUploaded.length) return;
listOfFilesUploaded.forEach(function(fileURL) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
if(this.responseText === ' problem deleting files.') {
alert('Failed to delete ' + fileURL + ' from the server.');
return;
}
listOfFilesUploaded = [];
alert('You can leave now. Your files are removed from the server.');
}
};
request.open('POST', 'delete.php');
var formData = new FormData();
formData.append('delete-file', fileURL.split('/').pop());
request.send(formData);
});
return 'Please wait few seconds before your recordings are deleted from the server.';
};
</script>
<section class="experiment">
<h2 class="header">
URL Parameters
</h2>
<pre>
// AUDIO
<a href="https://www.webrtc-experiment.com/RecordRTC/PHP/?bufferSize=16384&sampleRate=44100">?bufferSize=16384&sampleRate=44100</a>
<a href="https://www.webrtc-experiment.com/RecordRTC/PHP/?leftChannel=false&disableLogs=false">?leftChannel=false&disableLogs=false</a>
// VIDEO
<a href="https://www.webrtc-experiment.com/RecordRTC/PHP/?canvas_width=1280&canvas_height=720">?canvas_width=1280&canvas_height=720</a>
<a href="https://www.webrtc-experiment.com/RecordRTC/PHP/?frameInterval=10">?frameInterval=10</a>
</pre>
</section>
<section class="experiment">
<h2 class="header">
RecordRTC <a href="https://github.com/muaz-khan/RecordRTC">Sources Codes</a> / <a href="https://github.com/muaz-khan/RecordRTC/wiki">Wiki Pages</a>
</h2>
<ol>
<li>
<a href="https://www.webrtc-experiment.com/RecordRTC/">RecordRTC Main Demo</a> (Records screen/video/audio in all browsers!)
</li>
<li>
<a href="https://www.webrtc-experiment.com/RecordRTC/PHP/">RecordRTC-to-PHP</a>
(audio/video recording and uploading to server)
</li>
<li>
<a href="https://www.webrtc-experiment.com/RecordRTC/Canvas-Recording/">Canvas Recording!</a> (Web-Page Recording)
</li>
<li>
<a href="https://www.webrtc-experiment.com/RecordRTC/Record-Mp3-or-Wav.html">Record Mp3 or Wav</a> (Pre-recorded audio) i.e. (Audio on Demand)
</li>
<li>
<a href="https://www.webrtc-experiment.com/RecordRTC/MRecordRTC/">MRecordRTC and writeToDisk/getFromDisk!</a>
</li>
<li>
<a href="https://www.webrtc-experiment.com/RecordRTC/AudioVideo-on-Firefox.html">Audio+Video Recording on Firefox</a>
</li>
<li>
<a href="https://github.com/muaz-khan/RecordRTC/tree/master/PHP-and-FFmpeg">
RecordRTC / PHP / FFmpeg
</a>
(Syncing/Merging audio/video in single file!)
</li>
<li>
<a href="https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-to-Nodejs">RecordRTC-to-Nodejs</a>
(used ffmpeg to merge wav/webm in single WebM container)
</li>
<li>
<a href="https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-to-ASPNETMVC">RecordRTC-to-ASP.NET MVC</a>
(audio/video recording and uploading to server)
</li>
<li>
<a href="https://github.com/muaz-khan/RecordRTC/tree/master/RecordRTC-over-Socketio">RecordRTC-to-Socket.io</a>
(used ffmpeg to merge wav/webm in single WebM container)
</li>
<li><a href="https://www.webrtc-experiment.com/ffmpeg/">RecordRTC and ffmpeg-asm.js</a> (ffmpeg inside the browser!)</li>
</ol>
</section>
<section class="experiment own-widgets">
<h2 class="header" id="updates" style="color: red; padding-bottom: .1em;"><a href="https://github.com/muaz-khan/RecordRTC/issues" target="_blank">RecordRTC Issues</a>
</h2>
<div id="github-issues"></div>
</section>
<section class="experiment">
<h2 class="header" id="feedback">Feedback</h2>
<div>
<textarea id="message" style="border: 1px solid rgb(189, 189, 189); height: 8em; margin: .2em; outline: none; resize: vertical; width: 98%;" placeholder="Have any message? Suggestions or something went wrong?"></textarea>
</div>
<button id="send-message" style="font-size: 1em;">Send Message</button>
<small style="margin-left: 1em;">Enter your email too; if you want "direct" reply!</small>
</section>
<section class="experiment">
<h2 class="header">Using RecordRTC...</h2>
<ol>
<li>
You can record both Audio/Video in single file in Firefox.
</li>
<li>
You can record both Audio/Screen in single file in Firefox.
</li>
<li>
You can record audio as WAV and video as WebM in Chrome/Opera.
</li>
<li>
You can record audio as WAV in Microsoft Edge.
</li>
<li>
You can record remote audios (RTCPeerConnection.onaddstream) in Firefox using "recorderType:StereoAudioRecorder"
</li>
<li>
You can record Gif in all browsers.
</li>
</ol>
<p style="margin-top: 0;">
You can even control buffer-size, sample-rates, video-resolutions, etc.
</p>
</section>
<section class="experiment">
<h2 class="header">Technical Guide</h2>
<ol>
<li>
Chrome allows getUserMedia invocation on majority of non-file protocols e.g. HTTP/HTTPS/ or inside chrome extension pages. Though, there is always options to use CL (command-line) flags to support file protocols.
</li>
<li>
(
<strong>In Chrome</strong>) RecordRTC captures video frames via Canvas2D; which is encoded in webp-DataURL; now it is using a library named “weppy” which encodes webp into webm.
</li>
<li>
(
<strong>In Firefox</strong>) RecordRTC is using MediaRecorder API; which supports both audio/video recordings, both in single and multiple files.
</li>
<li>
(
<strong>In Chrome</strong>) RecordRTC is using WebAudio API for audio-recording. Such API has many issues e.g. unable to capture mono audio in wav format; <a href="https://www.webrtc-experiment.com/demos/remote-stream-recording.html">unable to capture remote audio</a>; failure on XP SP2; etc.
</li>
<li>
(
<strong>In Chrome</strong>) If you’re using notebook’s built-in audio input device for audio recording; then you may get "blank" blob.
</li>
<li>
(
<strong>In Chrome</strong>) RecordRTC is incapable to record audio/video in a single file; however there is ffmpeg merging solution available on Github repository.
</li>
</ol>
</section>
<section class="experiment">
<h2 class="header">
How to use <a href="https://github.com/muaz-khan/RecordRTC" target="_blank">RecordRTC</a>?</h2>
<pre>
<script src="//cdn.webrtc-experiment.com/RecordRTC.js"></script>
</pre>
</section>
<section class="experiment">
<h2 class="header">
How to record audio using <a href="https://github.com/muaz-khan/RecordRTC" target="_blank">RecordRTC</a>?</h2>
<pre>
var recordRTC = <a href="https://github.com/muaz-khan/RecordRTC" target="_blank">RecordRTC</a>(mediaStream, {
<strong>recorderType</strong>: StereoAudioRecorder // optionally force WebAudio API to record audio
});
recordRTC.<strong>startRecording</strong>();
recordRTC.<strong>stopRecording</strong>(function(<strong>audioURL</strong>) {
mediaElement.src = audioURL;
});
</pre>
</section>
<section class="experiment">
<h2 class="header">
How to record video using <a href="https://github.com/muaz-khan/RecordRTC" target="_blank">RecordRTC</a>?</h2>
<pre>
var options = {
<strong>type</strong>: 'video',
<strong>video</strong>: { width: 320, height: 240 },
<strong>canvas</strong>: { width: 320, height: 240 },
<strong>recorderType</strong>: WhammyRecorder // optional
};
var recordRTC = <a href="https://github.com/muaz-khan/RecordRTC" target="_blank">RecordRTC</a>(mediaStream, options);
recordRTC.<strong>startRecording</strong>();
recordRTC.<strong>stopRecording</strong>(function(<strong>videoURL</strong>) {
mediaElement.src = videoURL;
});
</pre>
</section>
<section class="experiment">
<h2 class="header">
How to record animated GIF using <a href="https://github.com/muaz-khan/RecordRTC" target="_blank">RecordRTC</a>?</h2>
<pre>
// you must link: // https://www.webrtc-experiment.com/gif-recorder.js
var options = {
<strong>type</strong>: 'gif',
<strong>video</strong>: { width: 320, height: 240 },
<strong>canvas</strong>: { width: 320, height: 240 },
<strong>frameRate</strong>: 200,
<strong>quality</strong>: 10
};
var recordRTC = <a href="https://github.com/muaz-khan/RecordRTC" target="_blank">RecordRTC</a>(mediaStream, options);
recordRTC.<strong>startRecording</strong>(); recordRTC.
<strong>stopRecording</strong>(function(<strong>gifURL</strong>) {
mediaElement.src = gifURL;
});
</pre>
</section>
<section class="experiment">
<h2>
Possible <a href="https://github.com/muaz-khan/RecordRTC/issues" target="_blank">
issues</a>/<a href="https://github.com/muaz-khan/RecordRTC/issues" target="_blank">failures</a>:
</h2>
<p>
(
<strong>In Chrome</strong>) The biggest issue is that RecordRTC is
<strong>unable to record</strong> both audio and video streams in single file.
<br />
<br /> Do you know "RecordRTC" fails recording audio because following conditions fails (
<strong>applies only to chrome</strong>):
<ol>
<li>Sample rate and channel configuration must be the same for input and output sides on Windows i.e. audio input/output devices must match</li>
<li>Only the Default microphone device can be used for capturing.</li>
<li>The requesting scheme is must be one of the following: http, https, chrome, extension's, or file (only works with --allow-file-access-from-files)</li>
<li>The browser must be able to create/initialize the metadata database for the API under the profile directory</li>
</ol>
</p>
</section>
<section class="experiment">
<p style="margin-top: 0;">
RecordRTC is MIT licensed on Github! <a href="https://github.com/muaz-khan/RecordRTC" target="_blank">Documentation</a>
</p>
</section>
<section class="experiment own-widgets latest-commits">
<h2 class="header" id="updates" style="color: red; padding-bottom: .1em;"><a href="https://github.com/muaz-khan/RecordRTC/commits/master" target="_blank">Latest Updates</a>
</h2>
<div id="github-commits"></div>
</section>
</article>
<a href="https://github.com/muaz-khan/RecordRTC" class="fork-left"></a>
<footer>
<p>
<a href="https://www.webrtc-experiment.com/">WebRTC Experiments</a> © <a href="https://plus.google.com/+MuazKhan" rel="author" target="_blank">Muaz Khan</a>
<a href="mailto:muazkh@gmail.com" target="_blank">muazkh@gmail.com</a>
</p>
</footer>
<!-- commits.js is useless for you! -->
<script>
window.useThisGithubPath = 'muaz-khan/RecordRTC';
</script>
<script src="https://cdn.webrtc-experiment.com/commits.js" async></script>
</body>
</html>