Record & Upload Audio From ReactJS

Guy Manzurola
2 min readFeb 9, 2021

--

I spent a day pulling my hairs on this one, trying to find something that works well. The use case is as follows:

  1. On the press of a start button, start recording incoming audio from the mic
  2. On the press of a stop button, upload the recorded audio to a server

With many thanks to this great article, the clear winner is RecorderJS by Matt Diamond. Although no longer maintained (last commit 5 years ago) it works flawlessly. Highly recommended.

Some things to note:

  1. The sample rate of the audio file is determined by the browser (OS). It can range from 16 khz to 48 khz and above. Even though an API exists that allows one to control the recording sample rate, it is best not to rely on it as it seems to be conditioned on the browser.
  2. The recording is done by a background web worker, which means you can record long utterances and it works very smoothly.
  3. I’ve tested a few other libraries that do this, but the generated audio file seemed to be corrupt, at least in my use case. This is the only one that worked out of the box.

Here’s how I integrated it within a react component. No need for fancy useEffect and such.

import './App.css';
import axios from "axios";

let gumStream = null;
let recorder = null;
let audioContext = null;

function RecorderJSDemo() {

const startRecording = () => {
let constraints = {
audio: true,
video: false
}

audioContext = new window.AudioContext();
console.log("sample rate: " + audioContext.sampleRate);

navigator.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
console.log("initializing Recorder.js ...");

gumStream = stream;

let input = audioContext.createMediaStreamSource(stream);

recorder = new window.Recorder(input, {
numChannels: 1
})

recorder.record();
console.log("Recording started");
}).catch(function (err) {
//enable the record button if getUserMedia() fails
});

}

const stopRecording = () => {
console.log("stopButton clicked");

recorder.stop(); //stop microphone access
gumStream.getAudioTracks()[0].stop();

recorder.exportWAV(onStop);
}

const onStop = (blob) => {
console.log("uploading...");

let data = new FormData();

data.append('text', "this is the transcription of the audio file");
data.append('wavfile', blob, "recording.wav");

const config = {
headers: {'content-type': 'multipart/form-data'}
}
axios.post('http://localhost:8080/asr/', data, config);
}

return (
<div>
<button onClick={startRecording} type="button">Start</button>
<button onClick={stopRecording} type="button">Stop</button>
</div>
);
}

export default RecorderJSDemo;

Chenkwee!

--

--

Guy Manzurola

Software Engineer / Electronic Musician / Amateur Computational Linguistic