
Research
Security News
Lazarus Strikes npm Again with New Wave of Malicious Packages
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
Cross-Browser recording of audio/video media streams; targets WebRTC/getUserMedia/WebAudio/etc. Works both on Chrome/Firefox/Opera on desktop & android.
A cross-browser implementation to record audio/video streams:
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.
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>
<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();
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);
}
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);
};
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 |
MediaStreamRecorder.js library is released under MIT licence.
FAQs
Cross-Browser recording of audio/video media streams; targets WebRTC/getUserMedia/WebAudio/etc.
The npm package msr receives a total of 1,364 weekly downloads. As such, msr popularity was classified as popular.
We found that msr demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
Security News
Socket CEO Feross Aboukhadijeh discusses the open web, open source security, and how Socket tackles software supply chain attacks on The Pair Program podcast.
Security News
Opengrep continues building momentum with the alpha release of its Playground tool, demonstrating the project's rapid evolution just two months after its initial launch.