What I ultimately want to do is record from the user's microphone, and upload the file to the server when they're done. So far, I've managed to make a stream to an element with the following code:
var audio = document.getElementById("audio_preview");
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
navigator.getUserMedia({video: false, audio: true}, function(stream) {
audio.src = window.URL.createObjectURL(stream);
}, onRecordFail);
var onRecordFail = function (e) {
console.log(e);
}
How do I go from that, to recording to a file?
This question is related to
javascript
html
html5-audio
audio-recording
This is a simple JavaScript sound recorder and editor. You can try it.
https://www.danieldemmel.me/JSSoundRecorder/
Can download from here
You can use Recordmp3js from GitHub to achieve your requirements. You can record from user's microphone and then get the file as an mp3. Finally upload it to your server.
I used this in my demo. There is a already a sample available with the source code by the author in this location : https://github.com/Audior/Recordmp3js
The demo is here: http://audior.ec/recordmp3js/
But currently works only on Chrome and Firefox.
Seems to work fine and pretty simple. Hope this helps.
Here's a gitHub project that does just that.
It records audio from the browser in mp3 format, and it automatically saves it to the webserver. https://github.com/Audior/Recordmp3js
You can also view a detailed explanation of the implementation: http://audior.ec/blog/recording-mp3-using-only-html5-and-javascript-recordmp3-js/
Update now Chrome also supports MediaRecorder API from v47. The same thing to do would be to use it( guessing native recording method is bound to be faster than work arounds), the API is really easy to use, and you would find tons of answers as to how to upload a blob for the server.
Demo - would work in Chrome and Firefox, intentionally left out pushing blob to server...
Currently, there are three ways to do it:
wav
[ all code client-side, uncompressed recording], you can check out --> Recorderjs. Problem: file size is quite big, more upload bandwidth required.mp3
[ all code client-side, compressed recording], you can check out --> mp3Recorder. Problem: personally, I find the quality bad, also there is this licensing issue.as ogg
[ client+ server(node.js
) code, compressed recording, infinite hours of recording without browser crash ], you can check out --> recordOpus, either only client-side recording, or client-server bundling, the choice is yours.
ogg recording example( only firefox):
var mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start(); // to start recording.
...
mediaRecorder.stop(); // to stop recording.
mediaRecorder.ondataavailable = function(e) {
// do something with the data.
}
Fiddle Demo for ogg recording.
Stream audio in realtime without waiting for recording to end: https://github.com/noamtcohen/AudioStreamer
This streams PCM data but you could modify the code to stream mp3 or Speex
The code shown below is copyrighted to Matt Diamond and available for use under MIT license. The original files are here:
Save this files and use
(function(window){_x000D_
_x000D_
var WORKER_PATH = 'recorderWorker.js';_x000D_
var Recorder = function(source, cfg){_x000D_
var config = cfg || {};_x000D_
var bufferLen = config.bufferLen || 4096;_x000D_
this.context = source.context;_x000D_
this.node = this.context.createScriptProcessor(bufferLen, 2, 2);_x000D_
var worker = new Worker(config.workerPath || WORKER_PATH);_x000D_
worker.postMessage({_x000D_
command: 'init',_x000D_
config: {_x000D_
sampleRate: this.context.sampleRate_x000D_
}_x000D_
});_x000D_
var recording = false,_x000D_
currCallback;_x000D_
_x000D_
this.node.onaudioprocess = function(e){_x000D_
if (!recording) return;_x000D_
worker.postMessage({_x000D_
command: 'record',_x000D_
buffer: [_x000D_
e.inputBuffer.getChannelData(0),_x000D_
e.inputBuffer.getChannelData(1)_x000D_
]_x000D_
});_x000D_
}_x000D_
_x000D_
this.configure = function(cfg){_x000D_
for (var prop in cfg){_x000D_
if (cfg.hasOwnProperty(prop)){_x000D_
config[prop] = cfg[prop];_x000D_
}_x000D_
}_x000D_
}_x000D_
_x000D_
this.record = function(){_x000D_
_x000D_
recording = true;_x000D_
}_x000D_
_x000D_
this.stop = function(){_x000D_
_x000D_
recording = false;_x000D_
}_x000D_
_x000D_
this.clear = function(){_x000D_
worker.postMessage({ command: 'clear' });_x000D_
}_x000D_
_x000D_
this.getBuffer = function(cb) {_x000D_
currCallback = cb || config.callback;_x000D_
worker.postMessage({ command: 'getBuffer' })_x000D_
}_x000D_
_x000D_
this.exportWAV = function(cb, type){_x000D_
currCallback = cb || config.callback;_x000D_
type = type || config.type || 'audio/wav';_x000D_
if (!currCallback) throw new Error('Callback not set');_x000D_
worker.postMessage({_x000D_
command: 'exportWAV',_x000D_
type: type_x000D_
});_x000D_
}_x000D_
_x000D_
worker.onmessage = function(e){_x000D_
var blob = e.data;_x000D_
currCallback(blob);_x000D_
}_x000D_
_x000D_
source.connect(this.node);_x000D_
this.node.connect(this.context.destination); //this should not be necessary_x000D_
};_x000D_
_x000D_
Recorder.forceDownload = function(blob, filename){_x000D_
var url = (window.URL || window.webkitURL).createObjectURL(blob);_x000D_
var link = window.document.createElement('a');_x000D_
link.href = url;_x000D_
link.download = filename || 'output.wav';_x000D_
var click = document.createEvent("Event");_x000D_
click.initEvent("click", true, true);_x000D_
link.dispatchEvent(click);_x000D_
}_x000D_
_x000D_
window.Recorder = Recorder;_x000D_
_x000D_
})(window);_x000D_
_x000D_
//ADDITIONAL JS recorderWorker.js_x000D_
var recLength = 0,_x000D_
recBuffersL = [],_x000D_
recBuffersR = [],_x000D_
sampleRate;_x000D_
this.onmessage = function(e){_x000D_
switch(e.data.command){_x000D_
case 'init':_x000D_
init(e.data.config);_x000D_
break;_x000D_
case 'record':_x000D_
record(e.data.buffer);_x000D_
break;_x000D_
case 'exportWAV':_x000D_
exportWAV(e.data.type);_x000D_
break;_x000D_
case 'getBuffer':_x000D_
getBuffer();_x000D_
break;_x000D_
case 'clear':_x000D_
clear();_x000D_
break;_x000D_
}_x000D_
};_x000D_
_x000D_
function init(config){_x000D_
sampleRate = config.sampleRate;_x000D_
}_x000D_
_x000D_
function record(inputBuffer){_x000D_
_x000D_
recBuffersL.push(inputBuffer[0]);_x000D_
recBuffersR.push(inputBuffer[1]);_x000D_
recLength += inputBuffer[0].length;_x000D_
}_x000D_
_x000D_
function exportWAV(type){_x000D_
var bufferL = mergeBuffers(recBuffersL, recLength);_x000D_
var bufferR = mergeBuffers(recBuffersR, recLength);_x000D_
var interleaved = interleave(bufferL, bufferR);_x000D_
var dataview = encodeWAV(interleaved);_x000D_
var audioBlob = new Blob([dataview], { type: type });_x000D_
_x000D_
this.postMessage(audioBlob);_x000D_
}_x000D_
_x000D_
function getBuffer() {_x000D_
var buffers = [];_x000D_
buffers.push( mergeBuffers(recBuffersL, recLength) );_x000D_
buffers.push( mergeBuffers(recBuffersR, recLength) );_x000D_
this.postMessage(buffers);_x000D_
}_x000D_
_x000D_
function clear(){_x000D_
recLength = 0;_x000D_
recBuffersL = [];_x000D_
recBuffersR = [];_x000D_
}_x000D_
_x000D_
function mergeBuffers(recBuffers, recLength){_x000D_
var result = new Float32Array(recLength);_x000D_
var offset = 0;_x000D_
for (var i = 0; i < recBuffers.length; i++){_x000D_
result.set(recBuffers[i], offset);_x000D_
offset += recBuffers[i].length;_x000D_
}_x000D_
return result;_x000D_
}_x000D_
_x000D_
function interleave(inputL, inputR){_x000D_
var length = inputL.length + inputR.length;_x000D_
var result = new Float32Array(length);_x000D_
_x000D_
var index = 0,_x000D_
inputIndex = 0;_x000D_
_x000D_
while (index < length){_x000D_
result[index++] = inputL[inputIndex];_x000D_
result[index++] = inputR[inputIndex];_x000D_
inputIndex++;_x000D_
}_x000D_
return result;_x000D_
}_x000D_
_x000D_
function floatTo16BitPCM(output, offset, input){_x000D_
for (var i = 0; i < input.length; i++, offset+=2){_x000D_
var s = Math.max(-1, Math.min(1, input[i]));_x000D_
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);_x000D_
}_x000D_
}_x000D_
_x000D_
function writeString(view, offset, string){_x000D_
for (var i = 0; i < string.length; i++){_x000D_
view.setUint8(offset + i, string.charCodeAt(i));_x000D_
}_x000D_
}_x000D_
_x000D_
function encodeWAV(samples){_x000D_
var buffer = new ArrayBuffer(44 + samples.length * 2);_x000D_
var view = new DataView(buffer);_x000D_
_x000D_
/* RIFF identifier */_x000D_
writeString(view, 0, 'RIFF');_x000D_
/* file length */_x000D_
view.setUint32(4, 32 + samples.length * 2, true);_x000D_
/* RIFF type */_x000D_
writeString(view, 8, 'WAVE');_x000D_
/* format chunk identifier */_x000D_
writeString(view, 12, 'fmt ');_x000D_
/* format chunk length */_x000D_
view.setUint32(16, 16, true);_x000D_
/* sample format (raw) */_x000D_
view.setUint16(20, 1, true);_x000D_
/* channel count */_x000D_
view.setUint16(22, 2, true);_x000D_
/* sample rate */_x000D_
view.setUint32(24, sampleRate, true);_x000D_
/* byte rate (sample rate * block align) */_x000D_
view.setUint32(28, sampleRate * 4, true);_x000D_
/* block align (channel count * bytes per sample) */_x000D_
view.setUint16(32, 4, true);_x000D_
/* bits per sample */_x000D_
view.setUint16(34, 16, true);_x000D_
/* data chunk identifier */_x000D_
writeString(view, 36, 'data');_x000D_
/* data chunk length */_x000D_
view.setUint32(40, samples.length * 2, true);_x000D_
_x000D_
floatTo16BitPCM(view, 44, samples);_x000D_
_x000D_
return view;_x000D_
}
_x000D_
<html>_x000D_
<body>_x000D_
<audio controls autoplay></audio>_x000D_
<script type="text/javascript" src="recorder.js"> </script>_x000D_
<fieldset><legend>RECORD AUDIO</legend>_x000D_
<input onclick="startRecording()" type="button" value="start recording" />_x000D_
<input onclick="stopRecording()" type="button" value="stop recording and play" />_x000D_
</fieldset>_x000D_
<script>_x000D_
var onFail = function(e) {_x000D_
console.log('Rejected!', e);_x000D_
};_x000D_
_x000D_
var onSuccess = function(s) {_x000D_
var context = new webkitAudioContext();_x000D_
var mediaStreamSource = context.createMediaStreamSource(s);_x000D_
recorder = new Recorder(mediaStreamSource);_x000D_
recorder.record();_x000D_
_x000D_
// audio loopback_x000D_
// mediaStreamSource.connect(context.destination);_x000D_
}_x000D_
_x000D_
window.URL = window.URL || window.webkitURL;_x000D_
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;_x000D_
_x000D_
var recorder;_x000D_
var audio = document.querySelector('audio');_x000D_
_x000D_
function startRecording() {_x000D_
if (navigator.getUserMedia) {_x000D_
navigator.getUserMedia({audio: true}, onSuccess, onFail);_x000D_
} else {_x000D_
console.log('navigator.getUserMedia not present');_x000D_
}_x000D_
}_x000D_
_x000D_
function stopRecording() {_x000D_
recorder.stop();_x000D_
recorder.exportWAV(function(s) {_x000D_
_x000D_
audio.src = window.URL.createObjectURL(s);_x000D_
});_x000D_
}_x000D_
</script>_x000D_
</body>_x000D_
</html>
_x000D_
Source: Stackoverflow.com