A cross-browser implementation to record audio/video streams:
- MediaStreamRecorder can record both audio and video in single WebM file on Firefox.
- MediaStreamRecorder can record audio as WAV and video as either WebM or animated gif on Chrome.
MediaStreamRecorder is useful in scenarios where you're planning to submit/upload recorded blobs in realtime to the server! You can get blobs after specific time-intervals.
Demos using MediaStreamRecorder.js library
Experiment Name | Demo | Source Code |
---|---|---|
Audio Recording | Demo | Source |
Video Recording | Demo | Source |
Gif Recording | Demo | Source |
MultiStreamRecorder Demo | Demo | Source |
There is a similar project: RecordRTC! Demo - Documentation
You can install scripts using NPM:
npm install msr
Then link single/standalone "MediaStreamRecorder.js" file:
<script src="./node_modules/msr/MediaStreamRecorder.js"> </script>
<script src="https://cdn.webrtc-experiment.com/MediaStreamRecorder.js"> </script>
<!-- or -->
https://cdn.rawgit.com/streamproc/MediaStreamRecorder/master/MediaStreamRecorder.js
<script src="https://cdn.webrtc-experiment.com/MediaStreamRecorder.js"> </script>
<script>
var mediaConstraints = {
audio: !!navigator.mozGetUserMedia, // don't forget audio!
video: true // don't forget video!
};
navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError);
function onMediaSuccess(stream) {
var mediaRecorder = new MediaStreamRecorder(stream);
mediaRecorder.mimeType = 'video/webm';
mediaRecorder.ondataavailable = function (blob) {
// POST/PUT "Blob" using FormData/XHR2
var blobURL = URL.createObjectURL(blob);
document.write('<a href="' + blobURL + '">' + blobURL + '</a>');
};
mediaRecorder.start(3000);
}
function onMediaError(e) {
console.error('media error', e);
}
</script>
MultiStreamRecorder.js
records both audio/video and returns both blobs in single ondataavailable
event.
<script src="https://cdn.webrtc-experiment.com/MediaStreamRecorder.js"> </script>
<script>
var mediaConstraints = {
audio: true,
video: true
};
navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError);
function onMediaSuccess(stream) {
var multiStreamRecorder = new MultiStreamRecorder(stream);
multiStreamRecorder.video = yourVideoElement; // to get maximum accuracy
multiStreamRecorder.audioChannels = 1;
multiStreamRecorder.ondataavailable = function (blobs) {
// blobs.audio
// blobs.video
};
multiStreamRecorder.start(3 * 1000);
}
function onMediaError(e) {
console.error('media error', e);
}
</script>
<script src="https://cdn.webrtc-experiment.com/MediaStreamRecorder.js"> </script>
var mediaConstraints = {
audio: true
};
navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError);
function onMediaSuccess(stream) {
var mediaRecorder = new MediaStreamRecorder(stream);
mediaRecorder.mimeType = 'audio/ogg';
mediaRecorder.audioChannels = 1;
mediaRecorder.ondataavailable = function (blob) {
// POST/PUT "Blob" using FormData/XHR2
var blobURL = URL.createObjectURL(blob);
document.write('<a href="' + blobURL + '">' + blobURL + '</a>');
};
mediaRecorder.start(3000);
}
function onMediaError(e) {
console.error('media error', e);
}
<script src="https://cdn.webrtc-experiment.com/MediaStreamRecorder.js"> </script>
<script>
var mediaConstraints = {
video: true
};
navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError);
function onMediaSuccess(stream) {
var mediaRecorder = new MediaStreamRecorder(stream);
mediaRecorder.mimeType = 'video/webm';
// for gif recording
// mediaRecorder.mimeType = 'image/gif';
mediaRecorder.width = 320;
mediaRecorder.height = 240;
mediaRecorder.ondataavailable = function (blob) {
// POST/PUT "Blob" using FormData/XHR2
var blobURL = URL.createObjectURL(blob);
document.write('<a href="' + blobURL + '">' + blobURL + '</a>');
};
mediaRecorder.start(3000);
}
function onMediaError(e) {
console.error('media error', e);
}
</script>
mediaRecorder.stop();
mediaRecorder.pause();
mediaRecorder.resume();
// invoke save-as dialog for all recorded blobs
mediaRecorder.save();
// or pass external blob/file
mediaRecorder.save(YourExternalBlob, 'FileName.webm');
PHP code:
<?php
foreach(array('video', 'audio') as $type) {
if (isset($_FILES["${type}-blob"])) {
$fileName = $_POST["${type}-filename"];
$uploadDirectory = "uploads/$fileName";
if (!move_uploaded_file($_FILES["${type}-blob"]["tmp_name"], $uploadDirectory)) {
echo("problem moving uploaded file");
}
echo($uploadDirectory);
}
}
?>
JavaScript Code:
var fileType = 'video'; // or "audio"
var fileName = 'ABCDEF.webm'; // or "wav" or "ogg"
var formData = new FormData();
formData.append(fileType + '-filename', fileName);
formData.append(fileType + '-blob', blob);
xhr('save.php', formData, function (fileURL) {
window.open(fileURL);
});
function xhr(url, data, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200) {
callback(location.href + request.responseText);
}
};
request.open('POST', url);
request.send(data);
}
You can force StereoAudioRecorder or WhammyRecorder or similar records on Firefox or Edge; even on Chrome and Opera.
All browsers will be using your specified recorder:
// force WebAudio API on all browsers
// it allows you record remote audio-streams in Firefox
// it also works in Microsoft Edge
mediaRecorder.type = StereoAudioRecorder;
// force webp based webm encoder on all browsers
mediaRecorder.type = WhammyRecorder;
// force MediaRecorder API on all browsers
// Chrome is going to implement MediaRecorder API soon;
// so this property allows you force MediaRecorder in Chrome.
mediaRecorder.type = MediaRecorderWrapper;
// force GifRecorder in all browsers. Both WhammyRecorder and MediaRecorder API will be ignored.
mediaRecorder.type = GifRecorder;
It is an integer value that accepts either 1 or 2. "1" means record only left-channel and skip right-one. The default value is "2".
mediaRecorder.audioChannels = 1;
You can set following audio-bufferSize values: 0, 256, 512, 1024, 2048, 4096, 8192, and 16384. "0" means: let chrome decide the device's default bufferSize. Default value is "2048".
mediaRecorder.bufferSize = 0;
Default "sampleRate" value is "44100". Currently you can't modify sample-rate in windows that's why this property isn't yet exposed to public API.
It accepts values only in range: 22050 to 96000
// set sampleRate for NON-windows systems
mediaRecorder.sampleRate = 96000;
It is recommended to pass your HTMLVideoElement to get most accurate result.
videoRecorder.video = yourHTMLVideoElement;
videoRecorder.onStartedDrawingNonBlankFrames = function() {
// record audio here to fix sync issues
// Note: MultiStreamRecorder auto handles audio sync issues.
videoRecorder.clearOldRecordedFrames(); // clear all blank frames
audioRecorder.start(interval);
};
This method allows you stop recording.
mediaRecorder.stop();
This method allows you pause recording.
mediaRecorder.pause();
This method allows you resume recording.
mediaRecorder.resume();
This method allows you save recording to disk (via save-as dialog).
// invoke save-as dialog for all recorded blobs
mediaRecorder.save();
// or pass external blob/file
mediaRecorder.save(YourExternalBlob, 'FileName.webm');
Using this property, you can pass video resolutions:
mediaRecorder.canvas = {
width: 1280,
height: 720
};
You can stretch video to specific width/height:
mediaRecorder.videoWidth = 1280;
mediaRecorder.videoHeight = 720;
This method allows you clear current video-frames. You can use it to remove blank-frames.
videoRecorder.video = yourHTMLVideoElement;
videoRecorder.onStartedDrawingNonBlankFrames = function() {
videoRecorder.clearOldRecordedFrames(); // clear all blank frames
audioRecorder.start(interval);
};
This method allows you stop entire recording process.
mediaRecorder.stop();
This method takes "interval" as the only argument and it starts recording process:
mediaRecorder.start(5 * 1000); // it takes milliseconds
This event is fired according to your interval and "stop" method.
mediaRecorder.ondataavailable = function(blob) {
POST_to_Server(blob);
};
This event is fired when recording is stopped, either by invoking "stop" method or in case of any unexpected error:
mediaRecorder.onstop = function() {
// recording has been stopped.
};
This property allows you set output media type:
// video:
videoRecorder.mimeType = 'video/webm';
videoRecorder.mimeType = 'video/mp4';
// audio:
audioRecorder.mimeType = 'audio/ogg';
audioRecorder.mimeType = 'audio/wav';
// gif:
gifRecorder.mimeType = 'image/gif';
Browser | Support |
---|---|
Firefox | Stable / Aurora / Nightly |
Google Chrome | Stable / Canary / Beta / Dev |
Opera | Stable / NEXT |
Android | Chrome / Firefox / Opera |
Microsoft Edge | Normal Build |
MediaStreamRecorder.js library is released under MIT licence.